1// Copyright 2012 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include <stdlib.h>
29
30#include "v8.h"
31
32#include "accessors.h"
33#include "api.h"
34#include "arguments.h"
35#include "bootstrapper.h"
36#include "codegen.h"
37#include "compilation-cache.h"
38#include "compiler.h"
39#include "cpu.h"
40#include "dateparser-inl.h"
41#include "debug.h"
42#include "deoptimizer.h"
43#include "date.h"
44#include "execution.h"
45#include "global-handles.h"
46#include "isolate-inl.h"
47#include "jsregexp.h"
48#include "json-parser.h"
49#include "liveedit.h"
50#include "liveobjectlist-inl.h"
51#include "misc-intrinsics.h"
52#include "parser.h"
53#include "platform.h"
54#include "runtime-profiler.h"
55#include "runtime.h"
56#include "scopeinfo.h"
57#include "smart-array-pointer.h"
58#include "string-search.h"
59#include "stub-cache.h"
60#include "v8threads.h"
61#include "vm-state-inl.h"
62
63namespace v8 {
64namespace internal {
65
66
67#define RUNTIME_ASSERT(value) \
68  if (!(value)) return isolate->ThrowIllegalOperation();
69
70// Cast the given object to a value of the specified type and store
71// it in a variable with the given name.  If the object is not of the
72// expected type call IllegalOperation and return.
73#define CONVERT_ARG_CHECKED(Type, name, index)                       \
74  RUNTIME_ASSERT(args[index]->Is##Type());                           \
75  Type* name = Type::cast(args[index]);
76
77#define CONVERT_ARG_HANDLE_CHECKED(Type, name, index)                \
78  RUNTIME_ASSERT(args[index]->Is##Type());                           \
79  Handle<Type> name = args.at<Type>(index);
80
81// Cast the given object to a boolean and store it in a variable with
82// the given name.  If the object is not a boolean call IllegalOperation
83// and return.
84#define CONVERT_BOOLEAN_ARG_CHECKED(name, index)                     \
85  RUNTIME_ASSERT(args[index]->IsBoolean());                          \
86  bool name = args[index]->IsTrue();
87
88// Cast the given argument to a Smi and store its value in an int variable
89// with the given name.  If the argument is not a Smi call IllegalOperation
90// and return.
91#define CONVERT_SMI_ARG_CHECKED(name, index)                         \
92  RUNTIME_ASSERT(args[index]->IsSmi());                              \
93  int name = args.smi_at(index);
94
95// Cast the given argument to a double and store it in a variable with
96// the given name.  If the argument is not a number (as opposed to
97// the number not-a-number) call IllegalOperation and return.
98#define CONVERT_DOUBLE_ARG_CHECKED(name, index)                      \
99  RUNTIME_ASSERT(args[index]->IsNumber());                           \
100  double name = args.number_at(index);
101
102// Call the specified converter on the object *comand store the result in
103// a variable of the specified type with the given name.  If the
104// object is not a Number call IllegalOperation and return.
105#define CONVERT_NUMBER_CHECKED(type, name, Type, obj)                \
106  RUNTIME_ASSERT(obj->IsNumber());                                   \
107  type name = NumberTo##Type(obj);
108
109
110// Cast the given argument to PropertyDetails and store its value in a
111// variable with the given name.  If the argument is not a Smi call
112// IllegalOperation and return.
113#define CONVERT_PROPERTY_DETAILS_CHECKED(name, index)                \
114  RUNTIME_ASSERT(args[index]->IsSmi());                              \
115  PropertyDetails name = PropertyDetails(Smi::cast(args[index]));
116
117
118// Assert that the given argument has a valid value for a StrictModeFlag
119// and store it in a StrictModeFlag variable with the given name.
120#define CONVERT_STRICT_MODE_ARG_CHECKED(name, index)                 \
121  RUNTIME_ASSERT(args[index]->IsSmi());                              \
122  RUNTIME_ASSERT(args.smi_at(index) == kStrictMode ||                \
123                 args.smi_at(index) == kNonStrictMode);              \
124  StrictModeFlag name =                                              \
125      static_cast<StrictModeFlag>(args.smi_at(index));
126
127
128// Assert that the given argument has a valid value for a LanguageMode
129// and store it in a LanguageMode variable with the given name.
130#define CONVERT_LANGUAGE_MODE_ARG(name, index)                       \
131  ASSERT(args[index]->IsSmi());                                      \
132  ASSERT(args.smi_at(index) == CLASSIC_MODE ||                       \
133         args.smi_at(index) == STRICT_MODE ||                        \
134         args.smi_at(index) == EXTENDED_MODE);                       \
135  LanguageMode name =                                                \
136      static_cast<LanguageMode>(args.smi_at(index));
137
138
139MUST_USE_RESULT static MaybeObject* DeepCopyBoilerplate(Isolate* isolate,
140                                                   JSObject* boilerplate) {
141  StackLimitCheck check(isolate);
142  if (check.HasOverflowed()) return isolate->StackOverflow();
143
144  Heap* heap = isolate->heap();
145  Object* result;
146  { MaybeObject* maybe_result = heap->CopyJSObject(boilerplate);
147    if (!maybe_result->ToObject(&result)) return maybe_result;
148  }
149  JSObject* copy = JSObject::cast(result);
150
151  // Deep copy local properties.
152  if (copy->HasFastProperties()) {
153    FixedArray* properties = copy->properties();
154    for (int i = 0; i < properties->length(); i++) {
155      Object* value = properties->get(i);
156      if (value->IsJSObject()) {
157        JSObject* js_object = JSObject::cast(value);
158        { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
159          if (!maybe_result->ToObject(&result)) return maybe_result;
160        }
161        properties->set(i, result);
162      }
163    }
164    int nof = copy->map()->inobject_properties();
165    for (int i = 0; i < nof; i++) {
166      Object* value = copy->InObjectPropertyAt(i);
167      if (value->IsJSObject()) {
168        JSObject* js_object = JSObject::cast(value);
169        { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
170          if (!maybe_result->ToObject(&result)) return maybe_result;
171        }
172        copy->InObjectPropertyAtPut(i, result);
173      }
174    }
175  } else {
176    { MaybeObject* maybe_result =
177          heap->AllocateFixedArray(copy->NumberOfLocalProperties());
178      if (!maybe_result->ToObject(&result)) return maybe_result;
179    }
180    FixedArray* names = FixedArray::cast(result);
181    copy->GetLocalPropertyNames(names, 0);
182    for (int i = 0; i < names->length(); i++) {
183      ASSERT(names->get(i)->IsString());
184      String* key_string = String::cast(names->get(i));
185      PropertyAttributes attributes =
186          copy->GetLocalPropertyAttribute(key_string);
187      // Only deep copy fields from the object literal expression.
188      // In particular, don't try to copy the length attribute of
189      // an array.
190      if (attributes != NONE) continue;
191      Object* value =
192          copy->GetProperty(key_string, &attributes)->ToObjectUnchecked();
193      if (value->IsJSObject()) {
194        JSObject* js_object = JSObject::cast(value);
195        { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
196          if (!maybe_result->ToObject(&result)) return maybe_result;
197        }
198        { MaybeObject* maybe_result =
199              // Creating object copy for literals. No strict mode needed.
200              copy->SetProperty(key_string, result, NONE, kNonStrictMode);
201          if (!maybe_result->ToObject(&result)) return maybe_result;
202        }
203      }
204    }
205  }
206
207  // Deep copy local elements.
208  // Pixel elements cannot be created using an object literal.
209  ASSERT(!copy->HasExternalArrayElements());
210  switch (copy->GetElementsKind()) {
211    case FAST_SMI_ONLY_ELEMENTS:
212    case FAST_ELEMENTS: {
213      FixedArray* elements = FixedArray::cast(copy->elements());
214      if (elements->map() == heap->fixed_cow_array_map()) {
215        isolate->counters()->cow_arrays_created_runtime()->Increment();
216#ifdef DEBUG
217        for (int i = 0; i < elements->length(); i++) {
218          ASSERT(!elements->get(i)->IsJSObject());
219        }
220#endif
221      } else {
222        for (int i = 0; i < elements->length(); i++) {
223          Object* value = elements->get(i);
224          ASSERT(value->IsSmi() ||
225                 value->IsTheHole() ||
226                 (copy->GetElementsKind() == FAST_ELEMENTS));
227          if (value->IsJSObject()) {
228            JSObject* js_object = JSObject::cast(value);
229            { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate,
230                                                              js_object);
231              if (!maybe_result->ToObject(&result)) return maybe_result;
232            }
233            elements->set(i, result);
234          }
235        }
236      }
237      break;
238    }
239    case DICTIONARY_ELEMENTS: {
240      SeededNumberDictionary* element_dictionary = copy->element_dictionary();
241      int capacity = element_dictionary->Capacity();
242      for (int i = 0; i < capacity; i++) {
243        Object* k = element_dictionary->KeyAt(i);
244        if (element_dictionary->IsKey(k)) {
245          Object* value = element_dictionary->ValueAt(i);
246          if (value->IsJSObject()) {
247            JSObject* js_object = JSObject::cast(value);
248            { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate,
249                                                              js_object);
250              if (!maybe_result->ToObject(&result)) return maybe_result;
251            }
252            element_dictionary->ValueAtPut(i, result);
253          }
254        }
255      }
256      break;
257    }
258    case NON_STRICT_ARGUMENTS_ELEMENTS:
259      UNIMPLEMENTED();
260      break;
261    case EXTERNAL_PIXEL_ELEMENTS:
262    case EXTERNAL_BYTE_ELEMENTS:
263    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
264    case EXTERNAL_SHORT_ELEMENTS:
265    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
266    case EXTERNAL_INT_ELEMENTS:
267    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
268    case EXTERNAL_FLOAT_ELEMENTS:
269    case EXTERNAL_DOUBLE_ELEMENTS:
270    case FAST_DOUBLE_ELEMENTS:
271      // No contained objects, nothing to do.
272      break;
273  }
274  return copy;
275}
276
277
278static Handle<Map> ComputeObjectLiteralMap(
279    Handle<Context> context,
280    Handle<FixedArray> constant_properties,
281    bool* is_result_from_cache) {
282  Isolate* isolate = context->GetIsolate();
283  int properties_length = constant_properties->length();
284  int number_of_properties = properties_length / 2;
285  // Check that there are only symbols and array indices among keys.
286  int number_of_symbol_keys = 0;
287  for (int p = 0; p != properties_length; p += 2) {
288    Object* key = constant_properties->get(p);
289    uint32_t element_index = 0;
290    if (key->IsSymbol()) {
291      number_of_symbol_keys++;
292    } else if (key->ToArrayIndex(&element_index)) {
293      // An index key does not require space in the property backing store.
294      number_of_properties--;
295    } else {
296      // Bail out as a non-symbol non-index key makes caching impossible.
297      // ASSERT to make sure that the if condition after the loop is false.
298      ASSERT(number_of_symbol_keys != number_of_properties);
299      break;
300    }
301  }
302  // If we only have symbols and array indices among keys then we can
303  // use the map cache in the global context.
304  const int kMaxKeys = 10;
305  if ((number_of_symbol_keys == number_of_properties) &&
306      (number_of_symbol_keys < kMaxKeys)) {
307    // Create the fixed array with the key.
308    Handle<FixedArray> keys =
309        isolate->factory()->NewFixedArray(number_of_symbol_keys);
310    if (number_of_symbol_keys > 0) {
311      int index = 0;
312      for (int p = 0; p < properties_length; p += 2) {
313        Object* key = constant_properties->get(p);
314        if (key->IsSymbol()) {
315          keys->set(index++, key);
316        }
317      }
318      ASSERT(index == number_of_symbol_keys);
319    }
320    *is_result_from_cache = true;
321    return isolate->factory()->ObjectLiteralMapFromCache(context, keys);
322  }
323  *is_result_from_cache = false;
324  return isolate->factory()->CopyMap(
325      Handle<Map>(context->object_function()->initial_map()),
326      number_of_properties);
327}
328
329
330static Handle<Object> CreateLiteralBoilerplate(
331    Isolate* isolate,
332    Handle<FixedArray> literals,
333    Handle<FixedArray> constant_properties);
334
335
336static Handle<Object> CreateObjectLiteralBoilerplate(
337    Isolate* isolate,
338    Handle<FixedArray> literals,
339    Handle<FixedArray> constant_properties,
340    bool should_have_fast_elements,
341    bool has_function_literal) {
342  // Get the global context from the literals array.  This is the
343  // context in which the function was created and we use the object
344  // function from this context to create the object literal.  We do
345  // not use the object function from the current global context
346  // because this might be the object function from another context
347  // which we should not have access to.
348  Handle<Context> context =
349      Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals));
350
351  // In case we have function literals, we want the object to be in
352  // slow properties mode for now. We don't go in the map cache because
353  // maps with constant functions can't be shared if the functions are
354  // not the same (which is the common case).
355  bool is_result_from_cache = false;
356  Handle<Map> map = has_function_literal
357      ? Handle<Map>(context->object_function()->initial_map())
358      : ComputeObjectLiteralMap(context,
359                                constant_properties,
360                                &is_result_from_cache);
361
362  Handle<JSObject> boilerplate = isolate->factory()->NewJSObjectFromMap(map);
363
364  // Normalize the elements of the boilerplate to save space if needed.
365  if (!should_have_fast_elements) JSObject::NormalizeElements(boilerplate);
366
367  // Add the constant properties to the boilerplate.
368  int length = constant_properties->length();
369  bool should_transform =
370      !is_result_from_cache && boilerplate->HasFastProperties();
371  if (should_transform || has_function_literal) {
372    // Normalize the properties of object to avoid n^2 behavior
373    // when extending the object multiple properties. Indicate the number of
374    // properties to be added.
375    JSObject::NormalizeProperties(
376        boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2);
377  }
378
379  for (int index = 0; index < length; index +=2) {
380    Handle<Object> key(constant_properties->get(index+0), isolate);
381    Handle<Object> value(constant_properties->get(index+1), isolate);
382    if (value->IsFixedArray()) {
383      // The value contains the constant_properties of a
384      // simple object or array literal.
385      Handle<FixedArray> array = Handle<FixedArray>::cast(value);
386      value = CreateLiteralBoilerplate(isolate, literals, array);
387      if (value.is_null()) return value;
388    }
389    Handle<Object> result;
390    uint32_t element_index = 0;
391    if (key->IsSymbol()) {
392      if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
393        // Array index as string (uint32).
394        result = JSObject::SetOwnElement(
395            boilerplate, element_index, value, kNonStrictMode);
396      } else {
397        Handle<String> name(String::cast(*key));
398        ASSERT(!name->AsArrayIndex(&element_index));
399        result = JSObject::SetLocalPropertyIgnoreAttributes(
400            boilerplate, name, value, NONE);
401      }
402    } else if (key->ToArrayIndex(&element_index)) {
403      // Array index (uint32).
404      result = JSObject::SetOwnElement(
405          boilerplate, element_index, value, kNonStrictMode);
406    } else {
407      // Non-uint32 number.
408      ASSERT(key->IsNumber());
409      double num = key->Number();
410      char arr[100];
411      Vector<char> buffer(arr, ARRAY_SIZE(arr));
412      const char* str = DoubleToCString(num, buffer);
413      Handle<String> name =
414          isolate->factory()->NewStringFromAscii(CStrVector(str));
415      result = JSObject::SetLocalPropertyIgnoreAttributes(
416          boilerplate, name, value, NONE);
417    }
418    // If setting the property on the boilerplate throws an
419    // exception, the exception is converted to an empty handle in
420    // the handle based operations.  In that case, we need to
421    // convert back to an exception.
422    if (result.is_null()) return result;
423  }
424
425  // Transform to fast properties if necessary. For object literals with
426  // containing function literals we defer this operation until after all
427  // computed properties have been assigned so that we can generate
428  // constant function properties.
429  if (should_transform && !has_function_literal) {
430    JSObject::TransformToFastProperties(
431        boilerplate, boilerplate->map()->unused_property_fields());
432  }
433
434  return boilerplate;
435}
436
437
438MaybeObject* TransitionElements(Handle<Object> object,
439                                ElementsKind to_kind,
440                                Isolate* isolate) {
441  HandleScope scope(isolate);
442  if (!object->IsJSObject()) return isolate->ThrowIllegalOperation();
443  ElementsKind from_kind =
444      Handle<JSObject>::cast(object)->map()->elements_kind();
445  if (Map::IsValidElementsTransition(from_kind, to_kind)) {
446    Handle<Object> result = JSObject::TransitionElementsKind(
447        Handle<JSObject>::cast(object), to_kind);
448    if (result.is_null()) return isolate->ThrowIllegalOperation();
449    return *result;
450  }
451  return isolate->ThrowIllegalOperation();
452}
453
454
455static const int kSmiOnlyLiteralMinimumLength = 1024;
456
457
458Handle<Object> Runtime::CreateArrayLiteralBoilerplate(
459    Isolate* isolate,
460    Handle<FixedArray> literals,
461    Handle<FixedArray> elements) {
462  // Create the JSArray.
463  Handle<JSFunction> constructor(
464      JSFunction::GlobalContextFromLiterals(*literals)->array_function());
465  Handle<JSArray> object =
466      Handle<JSArray>::cast(isolate->factory()->NewJSObject(constructor));
467
468  ElementsKind constant_elements_kind =
469      static_cast<ElementsKind>(Smi::cast(elements->get(0))->value());
470  Handle<FixedArrayBase> constant_elements_values(
471      FixedArrayBase::cast(elements->get(1)));
472
473  Context* global_context = isolate->context()->global_context();
474  if (constant_elements_kind == FAST_SMI_ONLY_ELEMENTS) {
475    object->set_map(Map::cast(global_context->smi_js_array_map()));
476  } else if (constant_elements_kind == FAST_DOUBLE_ELEMENTS) {
477    object->set_map(Map::cast(global_context->double_js_array_map()));
478  } else {
479    object->set_map(Map::cast(global_context->object_js_array_map()));
480  }
481
482  Handle<FixedArrayBase> copied_elements_values;
483  if (constant_elements_kind == FAST_DOUBLE_ELEMENTS) {
484    ASSERT(FLAG_smi_only_arrays);
485    copied_elements_values = isolate->factory()->CopyFixedDoubleArray(
486        Handle<FixedDoubleArray>::cast(constant_elements_values));
487  } else {
488    ASSERT(constant_elements_kind == FAST_SMI_ONLY_ELEMENTS ||
489           constant_elements_kind == FAST_ELEMENTS);
490    const bool is_cow =
491        (constant_elements_values->map() ==
492         isolate->heap()->fixed_cow_array_map());
493    if (is_cow) {
494      copied_elements_values = constant_elements_values;
495#if DEBUG
496      Handle<FixedArray> fixed_array_values =
497          Handle<FixedArray>::cast(copied_elements_values);
498      for (int i = 0; i < fixed_array_values->length(); i++) {
499        ASSERT(!fixed_array_values->get(i)->IsFixedArray());
500      }
501#endif
502    } else {
503      Handle<FixedArray> fixed_array_values =
504          Handle<FixedArray>::cast(constant_elements_values);
505      Handle<FixedArray> fixed_array_values_copy =
506          isolate->factory()->CopyFixedArray(fixed_array_values);
507      copied_elements_values = fixed_array_values_copy;
508      for (int i = 0; i < fixed_array_values->length(); i++) {
509        Object* current = fixed_array_values->get(i);
510        if (current->IsFixedArray()) {
511          // The value contains the constant_properties of a
512          // simple object or array literal.
513          Handle<FixedArray> fa(FixedArray::cast(fixed_array_values->get(i)));
514          Handle<Object> result =
515              CreateLiteralBoilerplate(isolate, literals, fa);
516          if (result.is_null()) return result;
517          fixed_array_values_copy->set(i, *result);
518        }
519      }
520    }
521  }
522  object->set_elements(*copied_elements_values);
523  object->set_length(Smi::FromInt(copied_elements_values->length()));
524
525  //  Ensure that the boilerplate object has FAST_ELEMENTS, unless the flag is
526  //  on or the object is larger than the threshold.
527  if (!FLAG_smi_only_arrays &&
528      constant_elements_values->length() < kSmiOnlyLiteralMinimumLength) {
529    if (object->GetElementsKind() != FAST_ELEMENTS) {
530      CHECK(!TransitionElements(object, FAST_ELEMENTS, isolate)->IsFailure());
531    }
532  }
533
534  return object;
535}
536
537
538static Handle<Object> CreateLiteralBoilerplate(
539    Isolate* isolate,
540    Handle<FixedArray> literals,
541    Handle<FixedArray> array) {
542  Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
543  const bool kHasNoFunctionLiteral = false;
544  switch (CompileTimeValue::GetType(array)) {
545    case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS:
546      return CreateObjectLiteralBoilerplate(isolate,
547                                            literals,
548                                            elements,
549                                            true,
550                                            kHasNoFunctionLiteral);
551    case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS:
552      return CreateObjectLiteralBoilerplate(isolate,
553                                            literals,
554                                            elements,
555                                            false,
556                                            kHasNoFunctionLiteral);
557    case CompileTimeValue::ARRAY_LITERAL:
558      return Runtime::CreateArrayLiteralBoilerplate(
559          isolate, literals, elements);
560    default:
561      UNREACHABLE();
562      return Handle<Object>::null();
563  }
564}
565
566
567RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteral) {
568  HandleScope scope(isolate);
569  ASSERT(args.length() == 4);
570  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
571  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
572  CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2);
573  CONVERT_SMI_ARG_CHECKED(flags, 3);
574  bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
575  bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
576
577  // Check if boilerplate exists. If not, create it first.
578  Handle<Object> boilerplate(literals->get(literals_index), isolate);
579  if (*boilerplate == isolate->heap()->undefined_value()) {
580    boilerplate = CreateObjectLiteralBoilerplate(isolate,
581                                                 literals,
582                                                 constant_properties,
583                                                 should_have_fast_elements,
584                                                 has_function_literal);
585    if (boilerplate.is_null()) return Failure::Exception();
586    // Update the functions literal and return the boilerplate.
587    literals->set(literals_index, *boilerplate);
588  }
589  return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate));
590}
591
592
593RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteralShallow) {
594  HandleScope scope(isolate);
595  ASSERT(args.length() == 4);
596  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
597  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
598  CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2);
599  CONVERT_SMI_ARG_CHECKED(flags, 3);
600  bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
601  bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
602
603  // Check if boilerplate exists. If not, create it first.
604  Handle<Object> boilerplate(literals->get(literals_index), isolate);
605  if (*boilerplate == isolate->heap()->undefined_value()) {
606    boilerplate = CreateObjectLiteralBoilerplate(isolate,
607                                                 literals,
608                                                 constant_properties,
609                                                 should_have_fast_elements,
610                                                 has_function_literal);
611    if (boilerplate.is_null()) return Failure::Exception();
612    // Update the functions literal and return the boilerplate.
613    literals->set(literals_index, *boilerplate);
614  }
615  return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate));
616}
617
618
619RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteral) {
620  HandleScope scope(isolate);
621  ASSERT(args.length() == 3);
622  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
623  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
624  CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
625
626  // Check if boilerplate exists. If not, create it first.
627  Handle<Object> boilerplate(literals->get(literals_index), isolate);
628  if (*boilerplate == isolate->heap()->undefined_value()) {
629    boilerplate =
630        Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
631    if (boilerplate.is_null()) return Failure::Exception();
632    // Update the functions literal and return the boilerplate.
633    literals->set(literals_index, *boilerplate);
634  }
635  return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate));
636}
637
638
639RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralShallow) {
640  HandleScope scope(isolate);
641  ASSERT(args.length() == 3);
642  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
643  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
644  CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
645
646  // Check if boilerplate exists. If not, create it first.
647  Handle<Object> boilerplate(literals->get(literals_index), isolate);
648  if (*boilerplate == isolate->heap()->undefined_value()) {
649    ASSERT(*elements != isolate->heap()->empty_fixed_array());
650    boilerplate =
651        Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
652    if (boilerplate.is_null()) return Failure::Exception();
653    // Update the functions literal and return the boilerplate.
654    literals->set(literals_index, *boilerplate);
655  }
656  if (JSObject::cast(*boilerplate)->elements()->map() ==
657      isolate->heap()->fixed_cow_array_map()) {
658    isolate->counters()->cow_arrays_created_runtime()->Increment();
659  }
660  return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate));
661}
662
663
664RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSProxy) {
665  ASSERT(args.length() == 2);
666  Object* handler = args[0];
667  Object* prototype = args[1];
668  Object* used_prototype =
669      prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
670  return isolate->heap()->AllocateJSProxy(handler, used_prototype);
671}
672
673
674RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSFunctionProxy) {
675  ASSERT(args.length() == 4);
676  Object* handler = args[0];
677  Object* call_trap = args[1];
678  Object* construct_trap = args[2];
679  Object* prototype = args[3];
680  Object* used_prototype =
681      prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
682  return isolate->heap()->AllocateJSFunctionProxy(
683      handler, call_trap, construct_trap, used_prototype);
684}
685
686
687RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSProxy) {
688  ASSERT(args.length() == 1);
689  Object* obj = args[0];
690  return isolate->heap()->ToBoolean(obj->IsJSProxy());
691}
692
693
694RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSFunctionProxy) {
695  ASSERT(args.length() == 1);
696  Object* obj = args[0];
697  return isolate->heap()->ToBoolean(obj->IsJSFunctionProxy());
698}
699
700
701RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHandler) {
702  ASSERT(args.length() == 1);
703  CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
704  return proxy->handler();
705}
706
707
708RUNTIME_FUNCTION(MaybeObject*, Runtime_GetCallTrap) {
709  ASSERT(args.length() == 1);
710  CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
711  return proxy->call_trap();
712}
713
714
715RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructTrap) {
716  ASSERT(args.length() == 1);
717  CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
718  return proxy->construct_trap();
719}
720
721
722RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) {
723  ASSERT(args.length() == 1);
724  CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
725  proxy->Fix();
726  return isolate->heap()->undefined_value();
727}
728
729
730RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInitialize) {
731  HandleScope scope(isolate);
732  ASSERT(args.length() == 1);
733  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
734  Handle<ObjectHashSet> table = isolate->factory()->NewObjectHashSet(0);
735  holder->set_table(*table);
736  return *holder;
737}
738
739
740RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAdd) {
741  HandleScope scope(isolate);
742  ASSERT(args.length() == 2);
743  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
744  Handle<Object> key(args[1]);
745  Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
746  table = ObjectHashSetAdd(table, key);
747  holder->set_table(*table);
748  return isolate->heap()->undefined_symbol();
749}
750
751
752RUNTIME_FUNCTION(MaybeObject*, Runtime_SetHas) {
753  HandleScope scope(isolate);
754  ASSERT(args.length() == 2);
755  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
756  Handle<Object> key(args[1]);
757  Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
758  return isolate->heap()->ToBoolean(table->Contains(*key));
759}
760
761
762RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDelete) {
763  HandleScope scope(isolate);
764  ASSERT(args.length() == 2);
765  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
766  Handle<Object> key(args[1]);
767  Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
768  table = ObjectHashSetRemove(table, key);
769  holder->set_table(*table);
770  return isolate->heap()->undefined_symbol();
771}
772
773
774RUNTIME_FUNCTION(MaybeObject*, Runtime_MapInitialize) {
775  HandleScope scope(isolate);
776  ASSERT(args.length() == 1);
777  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
778  Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
779  holder->set_table(*table);
780  return *holder;
781}
782
783
784RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGet) {
785  HandleScope scope(isolate);
786  ASSERT(args.length() == 2);
787  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
788  Handle<Object> key(args[1]);
789  return ObjectHashTable::cast(holder->table())->Lookup(*key);
790}
791
792
793RUNTIME_FUNCTION(MaybeObject*, Runtime_MapSet) {
794  HandleScope scope(isolate);
795  ASSERT(args.length() == 3);
796  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
797  Handle<Object> key(args[1]);
798  Handle<Object> value(args[2]);
799  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
800  Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
801  holder->set_table(*new_table);
802  return *value;
803}
804
805
806RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapInitialize) {
807  HandleScope scope(isolate);
808  ASSERT(args.length() == 1);
809  CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
810  ASSERT(weakmap->map()->inobject_properties() == 0);
811  Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
812  weakmap->set_table(*table);
813  weakmap->set_next(Smi::FromInt(0));
814  return *weakmap;
815}
816
817
818RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapGet) {
819  NoHandleAllocation ha;
820  ASSERT(args.length() == 2);
821  CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
822  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, key, 1);
823  return ObjectHashTable::cast(weakmap->table())->Lookup(*key);
824}
825
826
827RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapSet) {
828  HandleScope scope(isolate);
829  ASSERT(args.length() == 3);
830  CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
831  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, key, 1);
832  Handle<Object> value(args[2]);
833  Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table()));
834  Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
835  weakmap->set_table(*new_table);
836  return *value;
837}
838
839
840RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) {
841  NoHandleAllocation ha;
842  ASSERT(args.length() == 1);
843  Object* obj = args[0];
844  if (!obj->IsJSObject()) return isolate->heap()->null_value();
845  return JSObject::cast(obj)->class_name();
846}
847
848
849RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) {
850  NoHandleAllocation ha;
851  ASSERT(args.length() == 1);
852  CONVERT_ARG_CHECKED(JSReceiver, input_obj, 0);
853  Object* obj = input_obj;
854  // We don't expect access checks to be needed on JSProxy objects.
855  ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
856  do {
857    if (obj->IsAccessCheckNeeded() &&
858        !isolate->MayNamedAccess(JSObject::cast(obj),
859                                 isolate->heap()->Proto_symbol(),
860                                 v8::ACCESS_GET)) {
861      isolate->ReportFailedAccessCheck(JSObject::cast(obj), v8::ACCESS_GET);
862      return isolate->heap()->undefined_value();
863    }
864    obj = obj->GetPrototype();
865  } while (obj->IsJSObject() &&
866           JSObject::cast(obj)->map()->is_hidden_prototype());
867  return obj;
868}
869
870
871RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) {
872  NoHandleAllocation ha;
873  ASSERT(args.length() == 2);
874  // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
875  Object* O = args[0];
876  Object* V = args[1];
877  while (true) {
878    Object* prototype = V->GetPrototype();
879    if (prototype->IsNull()) return isolate->heap()->false_value();
880    if (O == prototype) return isolate->heap()->true_value();
881    V = prototype;
882  }
883}
884
885
886// Recursively traverses hidden prototypes if property is not found
887static void GetOwnPropertyImplementation(JSObject* obj,
888                                         String* name,
889                                         LookupResult* result) {
890  obj->LocalLookupRealNamedProperty(name, result);
891
892  if (!result->IsProperty()) {
893    Object* proto = obj->GetPrototype();
894    if (proto->IsJSObject() &&
895      JSObject::cast(proto)->map()->is_hidden_prototype())
896      GetOwnPropertyImplementation(JSObject::cast(proto),
897                                   name, result);
898  }
899}
900
901
902static bool CheckAccessException(LookupResult* result,
903                                 v8::AccessType access_type) {
904  if (result->type() == CALLBACKS) {
905    Object* callback = result->GetCallbackObject();
906    if (callback->IsAccessorInfo()) {
907      AccessorInfo* info = AccessorInfo::cast(callback);
908      bool can_access =
909          (access_type == v8::ACCESS_HAS &&
910              (info->all_can_read() || info->all_can_write())) ||
911          (access_type == v8::ACCESS_GET && info->all_can_read()) ||
912          (access_type == v8::ACCESS_SET && info->all_can_write());
913      return can_access;
914    }
915  }
916
917  return false;
918}
919
920
921static bool CheckAccess(JSObject* obj,
922                        String* name,
923                        LookupResult* result,
924                        v8::AccessType access_type) {
925  ASSERT(result->IsProperty());
926
927  JSObject* holder = result->holder();
928  JSObject* current = obj;
929  Isolate* isolate = obj->GetIsolate();
930  while (true) {
931    if (current->IsAccessCheckNeeded() &&
932        !isolate->MayNamedAccess(current, name, access_type)) {
933      // Access check callback denied the access, but some properties
934      // can have a special permissions which override callbacks descision
935      // (currently see v8::AccessControl).
936      break;
937    }
938
939    if (current == holder) {
940      return true;
941    }
942
943    current = JSObject::cast(current->GetPrototype());
944  }
945
946  // API callbacks can have per callback access exceptions.
947  switch (result->type()) {
948    case CALLBACKS: {
949      if (CheckAccessException(result, access_type)) {
950        return true;
951      }
952      break;
953    }
954    case INTERCEPTOR: {
955      // If the object has an interceptor, try real named properties.
956      // Overwrite the result to fetch the correct property later.
957      holder->LookupRealNamedProperty(name, result);
958      if (result->IsProperty()) {
959        if (CheckAccessException(result, access_type)) {
960          return true;
961        }
962      }
963      break;
964    }
965    default:
966      break;
967  }
968
969  isolate->ReportFailedAccessCheck(current, access_type);
970  return false;
971}
972
973
974// TODO(1095): we should traverse hidden prototype hierachy as well.
975static bool CheckElementAccess(JSObject* obj,
976                               uint32_t index,
977                               v8::AccessType access_type) {
978  if (obj->IsAccessCheckNeeded() &&
979      !obj->GetIsolate()->MayIndexedAccess(obj, index, access_type)) {
980    return false;
981  }
982
983  return true;
984}
985
986
987// Enumerator used as indices into the array returned from GetOwnProperty
988enum PropertyDescriptorIndices {
989  IS_ACCESSOR_INDEX,
990  VALUE_INDEX,
991  GETTER_INDEX,
992  SETTER_INDEX,
993  WRITABLE_INDEX,
994  ENUMERABLE_INDEX,
995  CONFIGURABLE_INDEX,
996  DESCRIPTOR_SIZE
997};
998
999
1000static MaybeObject* GetOwnProperty(Isolate* isolate,
1001                                   Handle<JSObject> obj,
1002                                   Handle<String> name) {
1003  Heap* heap = isolate->heap();
1004  Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
1005  Handle<JSArray> desc = isolate->factory()->NewJSArrayWithElements(elms);
1006  LookupResult result(isolate);
1007  // This could be an element.
1008  uint32_t index;
1009  if (name->AsArrayIndex(&index)) {
1010    switch (obj->HasLocalElement(index)) {
1011      case JSObject::UNDEFINED_ELEMENT:
1012        return heap->undefined_value();
1013
1014      case JSObject::STRING_CHARACTER_ELEMENT: {
1015        // Special handling of string objects according to ECMAScript 5
1016        // 15.5.5.2. Note that this might be a string object with elements
1017        // other than the actual string value. This is covered by the
1018        // subsequent cases.
1019        Handle<JSValue> js_value = Handle<JSValue>::cast(obj);
1020        Handle<String> str(String::cast(js_value->value()));
1021        Handle<String> substr = SubString(str, index, index + 1, NOT_TENURED);
1022
1023        elms->set(IS_ACCESSOR_INDEX, heap->false_value());
1024        elms->set(VALUE_INDEX, *substr);
1025        elms->set(WRITABLE_INDEX, heap->false_value());
1026        elms->set(ENUMERABLE_INDEX,  heap->true_value());
1027        elms->set(CONFIGURABLE_INDEX, heap->false_value());
1028        return *desc;
1029      }
1030
1031      case JSObject::INTERCEPTED_ELEMENT:
1032      case JSObject::FAST_ELEMENT: {
1033        elms->set(IS_ACCESSOR_INDEX, heap->false_value());
1034        Handle<Object> value = Object::GetElement(obj, index);
1035        RETURN_IF_EMPTY_HANDLE(isolate, value);
1036        elms->set(VALUE_INDEX, *value);
1037        elms->set(WRITABLE_INDEX, heap->true_value());
1038        elms->set(ENUMERABLE_INDEX,  heap->true_value());
1039        elms->set(CONFIGURABLE_INDEX, heap->true_value());
1040        return *desc;
1041      }
1042
1043      case JSObject::DICTIONARY_ELEMENT: {
1044        Handle<JSObject> holder = obj;
1045        if (obj->IsJSGlobalProxy()) {
1046          Object* proto = obj->GetPrototype();
1047          if (proto->IsNull()) return heap->undefined_value();
1048          ASSERT(proto->IsJSGlobalObject());
1049          holder = Handle<JSObject>(JSObject::cast(proto));
1050        }
1051        FixedArray* elements = FixedArray::cast(holder->elements());
1052        SeededNumberDictionary* dictionary = NULL;
1053        if (elements->map() == heap->non_strict_arguments_elements_map()) {
1054          dictionary = SeededNumberDictionary::cast(elements->get(1));
1055        } else {
1056          dictionary = SeededNumberDictionary::cast(elements);
1057        }
1058        int entry = dictionary->FindEntry(index);
1059        ASSERT(entry != SeededNumberDictionary::kNotFound);
1060        PropertyDetails details = dictionary->DetailsAt(entry);
1061        switch (details.type()) {
1062          case CALLBACKS: {
1063            // This is an accessor property with getter and/or setter.
1064            AccessorPair* accessors =
1065                AccessorPair::cast(dictionary->ValueAt(entry));
1066            elms->set(IS_ACCESSOR_INDEX, heap->true_value());
1067            if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) {
1068              elms->set(GETTER_INDEX, accessors->GetComponent(ACCESSOR_GETTER));
1069            }
1070            if (CheckElementAccess(*obj, index, v8::ACCESS_SET)) {
1071              elms->set(SETTER_INDEX, accessors->GetComponent(ACCESSOR_SETTER));
1072            }
1073            break;
1074          }
1075          case NORMAL: {
1076            // This is a data property.
1077            elms->set(IS_ACCESSOR_INDEX, heap->false_value());
1078            Handle<Object> value = Object::GetElement(obj, index);
1079            ASSERT(!value.is_null());
1080            elms->set(VALUE_INDEX, *value);
1081            elms->set(WRITABLE_INDEX, heap->ToBoolean(!details.IsReadOnly()));
1082            break;
1083          }
1084          default:
1085            UNREACHABLE();
1086            break;
1087        }
1088        elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!details.IsDontEnum()));
1089        elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!details.IsDontDelete()));
1090        return *desc;
1091      }
1092    }
1093  }
1094
1095  // Use recursive implementation to also traverse hidden prototypes
1096  GetOwnPropertyImplementation(*obj, *name, &result);
1097
1098  if (!result.IsProperty()) {
1099    return heap->undefined_value();
1100  }
1101
1102  if (!CheckAccess(*obj, *name, &result, v8::ACCESS_HAS)) {
1103    return heap->false_value();
1104  }
1105
1106  elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!result.IsDontEnum()));
1107  elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!result.IsDontDelete()));
1108
1109  bool is_js_accessor = (result.type() == CALLBACKS) &&
1110                        (result.GetCallbackObject()->IsAccessorPair());
1111
1112  if (is_js_accessor) {
1113    // __defineGetter__/__defineSetter__ callback.
1114    elms->set(IS_ACCESSOR_INDEX, heap->true_value());
1115
1116    AccessorPair* accessors = AccessorPair::cast(result.GetCallbackObject());
1117    if (CheckAccess(*obj, *name, &result, v8::ACCESS_GET)) {
1118      elms->set(GETTER_INDEX, accessors->GetComponent(ACCESSOR_GETTER));
1119    }
1120    if (CheckAccess(*obj, *name, &result, v8::ACCESS_SET)) {
1121      elms->set(SETTER_INDEX, accessors->GetComponent(ACCESSOR_SETTER));
1122    }
1123  } else {
1124    elms->set(IS_ACCESSOR_INDEX, heap->false_value());
1125    elms->set(WRITABLE_INDEX, heap->ToBoolean(!result.IsReadOnly()));
1126
1127    PropertyAttributes attrs;
1128    Object* value;
1129    // GetProperty will check access and report any violations.
1130    { MaybeObject* maybe_value = obj->GetProperty(*obj, &result, *name, &attrs);
1131      if (!maybe_value->ToObject(&value)) return maybe_value;
1132    }
1133    elms->set(VALUE_INDEX, value);
1134  }
1135
1136  return *desc;
1137}
1138
1139
1140// Returns an array with the property description:
1141//  if args[1] is not a property on args[0]
1142//          returns undefined
1143//  if args[1] is a data property on args[0]
1144//         [false, value, Writeable, Enumerable, Configurable]
1145//  if args[1] is an accessor on args[0]
1146//         [true, GetFunction, SetFunction, Enumerable, Configurable]
1147RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) {
1148  ASSERT(args.length() == 2);
1149  HandleScope scope(isolate);
1150  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1151  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
1152  return GetOwnProperty(isolate, obj, name);
1153}
1154
1155
1156RUNTIME_FUNCTION(MaybeObject*, Runtime_PreventExtensions) {
1157  ASSERT(args.length() == 1);
1158  CONVERT_ARG_CHECKED(JSObject, obj, 0);
1159  return obj->PreventExtensions();
1160}
1161
1162
1163RUNTIME_FUNCTION(MaybeObject*, Runtime_IsExtensible) {
1164  ASSERT(args.length() == 1);
1165  CONVERT_ARG_CHECKED(JSObject, obj, 0);
1166  if (obj->IsJSGlobalProxy()) {
1167    Object* proto = obj->GetPrototype();
1168    if (proto->IsNull()) return isolate->heap()->false_value();
1169    ASSERT(proto->IsJSGlobalObject());
1170    obj = JSObject::cast(proto);
1171  }
1172  return isolate->heap()->ToBoolean(obj->map()->is_extensible());
1173}
1174
1175
1176RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpCompile) {
1177  HandleScope scope(isolate);
1178  ASSERT(args.length() == 3);
1179  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, re, 0);
1180  CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
1181  CONVERT_ARG_HANDLE_CHECKED(String, flags, 2);
1182  Handle<Object> result = RegExpImpl::Compile(re, pattern, flags);
1183  if (result.is_null()) return Failure::Exception();
1184  return *result;
1185}
1186
1187
1188RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateApiFunction) {
1189  HandleScope scope(isolate);
1190  ASSERT(args.length() == 1);
1191  CONVERT_ARG_HANDLE_CHECKED(FunctionTemplateInfo, data, 0);
1192  return *isolate->factory()->CreateApiFunction(data);
1193}
1194
1195
1196RUNTIME_FUNCTION(MaybeObject*, Runtime_IsTemplate) {
1197  ASSERT(args.length() == 1);
1198  Object* arg = args[0];
1199  bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
1200  return isolate->heap()->ToBoolean(result);
1201}
1202
1203
1204RUNTIME_FUNCTION(MaybeObject*, Runtime_GetTemplateField) {
1205  ASSERT(args.length() == 2);
1206  CONVERT_ARG_CHECKED(HeapObject, templ, 0);
1207  CONVERT_SMI_ARG_CHECKED(index, 1)
1208  int offset = index * kPointerSize + HeapObject::kHeaderSize;
1209  InstanceType type = templ->map()->instance_type();
1210  RUNTIME_ASSERT(type ==  FUNCTION_TEMPLATE_INFO_TYPE ||
1211                 type ==  OBJECT_TEMPLATE_INFO_TYPE);
1212  RUNTIME_ASSERT(offset > 0);
1213  if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
1214    RUNTIME_ASSERT(offset < FunctionTemplateInfo::kSize);
1215  } else {
1216    RUNTIME_ASSERT(offset < ObjectTemplateInfo::kSize);
1217  }
1218  return *HeapObject::RawField(templ, offset);
1219}
1220
1221
1222RUNTIME_FUNCTION(MaybeObject*, Runtime_DisableAccessChecks) {
1223  ASSERT(args.length() == 1);
1224  CONVERT_ARG_CHECKED(HeapObject, object, 0);
1225  Map* old_map = object->map();
1226  bool needs_access_checks = old_map->is_access_check_needed();
1227  if (needs_access_checks) {
1228    // Copy map so it won't interfere constructor's initial map.
1229    Object* new_map;
1230    { MaybeObject* maybe_new_map = old_map->CopyDropTransitions();
1231      if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
1232    }
1233
1234    Map::cast(new_map)->set_is_access_check_needed(false);
1235    object->set_map(Map::cast(new_map));
1236  }
1237  return isolate->heap()->ToBoolean(needs_access_checks);
1238}
1239
1240
1241RUNTIME_FUNCTION(MaybeObject*, Runtime_EnableAccessChecks) {
1242  ASSERT(args.length() == 1);
1243  CONVERT_ARG_CHECKED(HeapObject, object, 0);
1244  Map* old_map = object->map();
1245  if (!old_map->is_access_check_needed()) {
1246    // Copy map so it won't interfere constructor's initial map.
1247    Object* new_map;
1248    { MaybeObject* maybe_new_map = old_map->CopyDropTransitions();
1249      if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
1250    }
1251
1252    Map::cast(new_map)->set_is_access_check_needed(true);
1253    object->set_map(Map::cast(new_map));
1254  }
1255  return isolate->heap()->undefined_value();
1256}
1257
1258
1259static Failure* ThrowRedeclarationError(Isolate* isolate,
1260                                        const char* type,
1261                                        Handle<String> name) {
1262  HandleScope scope(isolate);
1263  Handle<Object> type_handle =
1264      isolate->factory()->NewStringFromAscii(CStrVector(type));
1265  Handle<Object> args[2] = { type_handle, name };
1266  Handle<Object> error =
1267      isolate->factory()->NewTypeError("redeclaration", HandleVector(args, 2));
1268  return isolate->Throw(*error);
1269}
1270
1271
1272RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
1273  ASSERT(args.length() == 3);
1274  HandleScope scope(isolate);
1275  Handle<GlobalObject> global = Handle<GlobalObject>(
1276      isolate->context()->global());
1277
1278  Handle<Context> context = args.at<Context>(0);
1279  CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1);
1280  CONVERT_SMI_ARG_CHECKED(flags, 2);
1281
1282  // Traverse the name/value pairs and set the properties.
1283  int length = pairs->length();
1284  for (int i = 0; i < length; i += 2) {
1285    HandleScope scope(isolate);
1286    Handle<String> name(String::cast(pairs->get(i)));
1287    Handle<Object> value(pairs->get(i + 1), isolate);
1288
1289    // We have to declare a global const property. To capture we only
1290    // assign to it when evaluating the assignment for "const x =
1291    // <expr>" the initial value is the hole.
1292    bool is_const_property = value->IsTheHole();
1293    bool is_function_declaration = false;
1294    if (value->IsUndefined() || is_const_property) {
1295      // Lookup the property in the global object, and don't set the
1296      // value of the variable if the property is already there.
1297      LookupResult lookup(isolate);
1298      global->Lookup(*name, &lookup);
1299      if (lookup.IsProperty()) {
1300        // We found an existing property. Unless it was an interceptor
1301        // that claims the property is absent, skip this declaration.
1302        if (lookup.type() != INTERCEPTOR) {
1303          continue;
1304        }
1305        PropertyAttributes attributes = global->GetPropertyAttribute(*name);
1306        if (attributes != ABSENT) {
1307          continue;
1308        }
1309        // Fall-through and introduce the absent property by using
1310        // SetProperty.
1311      }
1312    } else {
1313      is_function_declaration = true;
1314      // Copy the function and update its context. Use it as value.
1315      Handle<SharedFunctionInfo> shared =
1316          Handle<SharedFunctionInfo>::cast(value);
1317      Handle<JSFunction> function =
1318          isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
1319                                                                context,
1320                                                                TENURED);
1321      value = function;
1322    }
1323
1324    LookupResult lookup(isolate);
1325    global->LocalLookup(*name, &lookup);
1326
1327    // Compute the property attributes. According to ECMA-262, section
1328    // 13, page 71, the property must be read-only and
1329    // non-deletable. However, neither SpiderMonkey nor KJS creates the
1330    // property as read-only, so we don't either.
1331    int attr = NONE;
1332    if (!DeclareGlobalsEvalFlag::decode(flags)) {
1333      attr |= DONT_DELETE;
1334    }
1335    bool is_native = DeclareGlobalsNativeFlag::decode(flags);
1336    if (is_const_property || (is_native && is_function_declaration)) {
1337      attr |= READ_ONLY;
1338    }
1339
1340    LanguageMode language_mode = DeclareGlobalsLanguageMode::decode(flags);
1341
1342    // Safari does not allow the invocation of callback setters for
1343    // function declarations. To mimic this behavior, we do not allow
1344    // the invocation of setters for function values. This makes a
1345    // difference for global functions with the same names as event
1346    // handlers such as "function onload() {}". Firefox does call the
1347    // onload setter in those case and Safari does not. We follow
1348    // Safari for compatibility.
1349    if (is_function_declaration) {
1350      if (lookup.IsProperty() && (lookup.type() != INTERCEPTOR)) {
1351        // Do not overwrite READ_ONLY properties.
1352        if (lookup.GetAttributes() & READ_ONLY) {
1353          if (language_mode != CLASSIC_MODE) {
1354            Handle<Object> args[] = { name };
1355            return isolate->Throw(*isolate->factory()->NewTypeError(
1356                "strict_cannot_assign", HandleVector(args, ARRAY_SIZE(args))));
1357          }
1358          continue;
1359        }
1360        // Do not change DONT_DELETE to false from true.
1361        attr |= lookup.GetAttributes() & DONT_DELETE;
1362      }
1363      PropertyAttributes attributes = static_cast<PropertyAttributes>(attr);
1364
1365      RETURN_IF_EMPTY_HANDLE(
1366          isolate,
1367          JSObject::SetLocalPropertyIgnoreAttributes(global, name, value,
1368                                                     attributes));
1369    } else {
1370      RETURN_IF_EMPTY_HANDLE(
1371          isolate,
1372          JSReceiver::SetProperty(global, name, value,
1373                                  static_cast<PropertyAttributes>(attr),
1374                                  language_mode == CLASSIC_MODE
1375                                      ? kNonStrictMode : kStrictMode));
1376    }
1377  }
1378
1379  ASSERT(!isolate->has_pending_exception());
1380  return isolate->heap()->undefined_value();
1381}
1382
1383
1384RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
1385  HandleScope scope(isolate);
1386  ASSERT(args.length() == 4);
1387
1388  // Declarations are always made in a function or global context.  In the
1389  // case of eval code, the context passed is the context of the caller,
1390  // which may be some nested context and not the declaration context.
1391  RUNTIME_ASSERT(args[0]->IsContext());
1392  Handle<Context> context(Context::cast(args[0])->declaration_context());
1393
1394  Handle<String> name(String::cast(args[1]));
1395  PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2));
1396  RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE);
1397  Handle<Object> initial_value(args[3], isolate);
1398
1399  int index;
1400  PropertyAttributes attributes;
1401  ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
1402  BindingFlags binding_flags;
1403  Handle<Object> holder =
1404      context->Lookup(name, flags, &index, &attributes, &binding_flags);
1405
1406  if (attributes != ABSENT) {
1407    // The name was declared before; check for conflicting re-declarations.
1408    if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
1409      // Functions are not read-only.
1410      ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
1411      const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
1412      return ThrowRedeclarationError(isolate, type, name);
1413    }
1414
1415    // Initialize it if necessary.
1416    if (*initial_value != NULL) {
1417      if (index >= 0) {
1418        ASSERT(holder.is_identical_to(context));
1419        if (((attributes & READ_ONLY) == 0) ||
1420            context->get(index)->IsTheHole()) {
1421          context->set(index, *initial_value);
1422        }
1423      } else {
1424        // Slow case: The property is in the context extension object of a
1425        // function context or the global object of a global context.
1426        Handle<JSObject> object = Handle<JSObject>::cast(holder);
1427        RETURN_IF_EMPTY_HANDLE(
1428            isolate,
1429            JSReceiver::SetProperty(object, name, initial_value, mode,
1430                                    kNonStrictMode));
1431      }
1432    }
1433
1434  } else {
1435    // The property is not in the function context. It needs to be
1436    // "declared" in the function context's extension context or as a
1437    // property of the the global object.
1438    Handle<JSObject> object;
1439    if (context->has_extension()) {
1440      object = Handle<JSObject>(JSObject::cast(context->extension()));
1441    } else {
1442      // Context extension objects are allocated lazily.
1443      ASSERT(context->IsFunctionContext());
1444      object = isolate->factory()->NewJSObject(
1445          isolate->context_extension_function());
1446      context->set_extension(*object);
1447    }
1448    ASSERT(*object != NULL);
1449
1450    // Declare the property by setting it to the initial value if provided,
1451    // or undefined, and use the correct mode (e.g. READ_ONLY attribute for
1452    // constant declarations).
1453    ASSERT(!object->HasLocalProperty(*name));
1454    Handle<Object> value(isolate->heap()->undefined_value(), isolate);
1455    if (*initial_value != NULL) value = initial_value;
1456    // Declaring a const context slot is a conflicting declaration if
1457    // there is a callback with that name in a prototype. It is
1458    // allowed to introduce const variables in
1459    // JSContextExtensionObjects. They are treated specially in
1460    // SetProperty and no setters are invoked for those since they are
1461    // not real JSObjects.
1462    if (initial_value->IsTheHole() &&
1463        !object->IsJSContextExtensionObject()) {
1464      LookupResult lookup(isolate);
1465      object->Lookup(*name, &lookup);
1466      if (lookup.IsFound() && (lookup.type() == CALLBACKS)) {
1467        return ThrowRedeclarationError(isolate, "const", name);
1468      }
1469    }
1470    RETURN_IF_EMPTY_HANDLE(
1471        isolate,
1472        JSReceiver::SetProperty(object, name, value, mode, kNonStrictMode));
1473  }
1474
1475  return isolate->heap()->undefined_value();
1476}
1477
1478
1479RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
1480  NoHandleAllocation nha;
1481  // args[0] == name
1482  // args[1] == language_mode
1483  // args[2] == value (optional)
1484
1485  // Determine if we need to assign to the variable if it already
1486  // exists (based on the number of arguments).
1487  RUNTIME_ASSERT(args.length() == 2 || args.length() == 3);
1488  bool assign = args.length() == 3;
1489
1490  CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1491  GlobalObject* global = isolate->context()->global();
1492  RUNTIME_ASSERT(args[1]->IsSmi());
1493  CONVERT_LANGUAGE_MODE_ARG(language_mode, 1);
1494  StrictModeFlag strict_mode_flag = (language_mode == CLASSIC_MODE)
1495      ? kNonStrictMode : kStrictMode;
1496
1497  // According to ECMA-262, section 12.2, page 62, the property must
1498  // not be deletable.
1499  PropertyAttributes attributes = DONT_DELETE;
1500
1501  // Lookup the property locally in the global object. If it isn't
1502  // there, there is a property with this name in the prototype chain.
1503  // We follow Safari and Firefox behavior and only set the property
1504  // locally if there is an explicit initialization value that we have
1505  // to assign to the property.
1506  // Note that objects can have hidden prototypes, so we need to traverse
1507  // the whole chain of hidden prototypes to do a 'local' lookup.
1508  Object* object = global;
1509  LookupResult lookup(isolate);
1510  while (object->IsJSObject() &&
1511         JSObject::cast(object)->map()->is_hidden_prototype()) {
1512    JSObject* raw_holder = JSObject::cast(object);
1513    raw_holder->LocalLookup(*name, &lookup);
1514    if (lookup.IsFound() && lookup.type() == INTERCEPTOR) {
1515      HandleScope handle_scope(isolate);
1516      Handle<JSObject> holder(raw_holder);
1517      PropertyAttributes intercepted = holder->GetPropertyAttribute(*name);
1518      // Update the raw pointer in case it's changed due to GC.
1519      raw_holder = *holder;
1520      if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
1521        // Found an interceptor that's not read only.
1522        if (assign) {
1523          return raw_holder->SetProperty(
1524              &lookup, *name, args[2], attributes, strict_mode_flag);
1525        } else {
1526          return isolate->heap()->undefined_value();
1527        }
1528      }
1529    }
1530    object = raw_holder->GetPrototype();
1531  }
1532
1533  // Reload global in case the loop above performed a GC.
1534  global = isolate->context()->global();
1535  if (assign) {
1536    return global->SetProperty(*name, args[2], attributes, strict_mode_flag);
1537  }
1538  return isolate->heap()->undefined_value();
1539}
1540
1541
1542RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
1543  // All constants are declared with an initial value. The name
1544  // of the constant is the first argument and the initial value
1545  // is the second.
1546  RUNTIME_ASSERT(args.length() == 2);
1547  CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1548  Handle<Object> value = args.at<Object>(1);
1549
1550  // Get the current global object from top.
1551  GlobalObject* global = isolate->context()->global();
1552
1553  // According to ECMA-262, section 12.2, page 62, the property must
1554  // not be deletable. Since it's a const, it must be READ_ONLY too.
1555  PropertyAttributes attributes =
1556      static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
1557
1558  // Lookup the property locally in the global object. If it isn't
1559  // there, we add the property and take special precautions to always
1560  // add it as a local property even in case of callbacks in the
1561  // prototype chain (this rules out using SetProperty).
1562  // We use SetLocalPropertyIgnoreAttributes instead
1563  LookupResult lookup(isolate);
1564  global->LocalLookup(*name, &lookup);
1565  if (!lookup.IsProperty()) {
1566    return global->SetLocalPropertyIgnoreAttributes(*name,
1567                                                    *value,
1568                                                    attributes);
1569  }
1570
1571  if (!lookup.IsReadOnly()) {
1572    // Restore global object from context (in case of GC) and continue
1573    // with setting the value.
1574    HandleScope handle_scope(isolate);
1575    Handle<GlobalObject> global(isolate->context()->global());
1576
1577    // BUG 1213575: Handle the case where we have to set a read-only
1578    // property through an interceptor and only do it if it's
1579    // uninitialized, e.g. the hole. Nirk...
1580    // Passing non-strict mode because the property is writable.
1581    RETURN_IF_EMPTY_HANDLE(
1582        isolate,
1583        JSReceiver::SetProperty(global, name, value, attributes,
1584                                kNonStrictMode));
1585    return *value;
1586  }
1587
1588  // Set the value, but only if we're assigning the initial value to a
1589  // constant. For now, we determine this by checking if the
1590  // current value is the hole.
1591  // Strict mode handling not needed (const is disallowed in strict mode).
1592  PropertyType type = lookup.type();
1593  if (type == FIELD) {
1594    FixedArray* properties = global->properties();
1595    int index = lookup.GetFieldIndex();
1596    if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) {
1597      properties->set(index, *value);
1598    }
1599  } else if (type == NORMAL) {
1600    if (global->GetNormalizedProperty(&lookup)->IsTheHole() ||
1601        !lookup.IsReadOnly()) {
1602      global->SetNormalizedProperty(&lookup, *value);
1603    }
1604  } else {
1605    // Ignore re-initialization of constants that have already been
1606    // assigned a function value.
1607    ASSERT(lookup.IsReadOnly() && type == CONSTANT_FUNCTION);
1608  }
1609
1610  // Use the set value as the result of the operation.
1611  return *value;
1612}
1613
1614
1615RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) {
1616  HandleScope scope(isolate);
1617  ASSERT(args.length() == 3);
1618
1619  Handle<Object> value(args[0], isolate);
1620  ASSERT(!value->IsTheHole());
1621
1622  // Initializations are always done in a function or global context.
1623  RUNTIME_ASSERT(args[1]->IsContext());
1624  Handle<Context> context(Context::cast(args[1])->declaration_context());
1625
1626  Handle<String> name(String::cast(args[2]));
1627
1628  int index;
1629  PropertyAttributes attributes;
1630  ContextLookupFlags flags = FOLLOW_CHAINS;
1631  BindingFlags binding_flags;
1632  Handle<Object> holder =
1633      context->Lookup(name, flags, &index, &attributes, &binding_flags);
1634
1635  if (index >= 0) {
1636    ASSERT(holder->IsContext());
1637    // Property was found in a context.  Perform the assignment if we
1638    // found some non-constant or an uninitialized constant.
1639    Handle<Context> context = Handle<Context>::cast(holder);
1640    if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) {
1641      context->set(index, *value);
1642    }
1643    return *value;
1644  }
1645
1646  // The property could not be found, we introduce it as a property of the
1647  // global object.
1648  if (attributes == ABSENT) {
1649    Handle<JSObject> global = Handle<JSObject>(
1650        isolate->context()->global());
1651    // Strict mode not needed (const disallowed in strict mode).
1652    RETURN_IF_EMPTY_HANDLE(
1653        isolate,
1654        JSReceiver::SetProperty(global, name, value, NONE, kNonStrictMode));
1655    return *value;
1656  }
1657
1658  // The property was present in some function's context extension object,
1659  // as a property on the subject of a with, or as a property of the global
1660  // object.
1661  //
1662  // In most situations, eval-introduced consts should still be present in
1663  // the context extension object.  However, because declaration and
1664  // initialization are separate, the property might have been deleted
1665  // before we reach the initialization point.
1666  //
1667  // Example:
1668  //
1669  //    function f() { eval("delete x; const x;"); }
1670  //
1671  // In that case, the initialization behaves like a normal assignment.
1672  Handle<JSObject> object = Handle<JSObject>::cast(holder);
1673
1674  if (*object == context->extension()) {
1675    // This is the property that was introduced by the const declaration.
1676    // Set it if it hasn't been set before.  NOTE: We cannot use
1677    // GetProperty() to get the current value as it 'unholes' the value.
1678    LookupResult lookup(isolate);
1679    object->LocalLookupRealNamedProperty(*name, &lookup);
1680    ASSERT(lookup.IsFound());  // the property was declared
1681    ASSERT(lookup.IsReadOnly());  // and it was declared as read-only
1682
1683    PropertyType type = lookup.type();
1684    if (type == FIELD) {
1685      FixedArray* properties = object->properties();
1686      int index = lookup.GetFieldIndex();
1687      if (properties->get(index)->IsTheHole()) {
1688        properties->set(index, *value);
1689      }
1690    } else if (type == NORMAL) {
1691      if (object->GetNormalizedProperty(&lookup)->IsTheHole()) {
1692        object->SetNormalizedProperty(&lookup, *value);
1693      }
1694    } else {
1695      // We should not reach here. Any real, named property should be
1696      // either a field or a dictionary slot.
1697      UNREACHABLE();
1698    }
1699  } else {
1700    // The property was found on some other object.  Set it if it is not a
1701    // read-only property.
1702    if ((attributes & READ_ONLY) == 0) {
1703      // Strict mode not needed (const disallowed in strict mode).
1704      RETURN_IF_EMPTY_HANDLE(
1705          isolate,
1706          JSReceiver::SetProperty(object, name, value, attributes,
1707                                  kNonStrictMode));
1708    }
1709  }
1710
1711  return *value;
1712}
1713
1714
1715RUNTIME_FUNCTION(MaybeObject*,
1716                 Runtime_OptimizeObjectForAddingMultipleProperties) {
1717  HandleScope scope(isolate);
1718  ASSERT(args.length() == 2);
1719  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1720  CONVERT_SMI_ARG_CHECKED(properties, 1);
1721  if (object->HasFastProperties()) {
1722    JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties);
1723  }
1724  return *object;
1725}
1726
1727
1728RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) {
1729  HandleScope scope(isolate);
1730  ASSERT(args.length() == 4);
1731  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
1732  CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
1733  // Due to the way the JS calls are constructed this must be less than the
1734  // length of a string, i.e. it is always a Smi.  We check anyway for security.
1735  CONVERT_SMI_ARG_CHECKED(index, 2);
1736  CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
1737  RUNTIME_ASSERT(last_match_info->HasFastElements());
1738  RUNTIME_ASSERT(index >= 0);
1739  RUNTIME_ASSERT(index <= subject->length());
1740  isolate->counters()->regexp_entry_runtime()->Increment();
1741  Handle<Object> result = RegExpImpl::Exec(regexp,
1742                                           subject,
1743                                           index,
1744                                           last_match_info);
1745  if (result.is_null()) return Failure::Exception();
1746  return *result;
1747}
1748
1749
1750RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpConstructResult) {
1751  ASSERT(args.length() == 3);
1752  CONVERT_SMI_ARG_CHECKED(elements_count, 0);
1753  if (elements_count < 0 ||
1754      elements_count > FixedArray::kMaxLength ||
1755      !Smi::IsValid(elements_count)) {
1756    return isolate->ThrowIllegalOperation();
1757  }
1758  Object* new_object;
1759  { MaybeObject* maybe_new_object =
1760        isolate->heap()->AllocateFixedArrayWithHoles(elements_count);
1761    if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
1762  }
1763  FixedArray* elements = FixedArray::cast(new_object);
1764  { MaybeObject* maybe_new_object = isolate->heap()->AllocateRaw(
1765      JSRegExpResult::kSize, NEW_SPACE, OLD_POINTER_SPACE);
1766    if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
1767  }
1768  {
1769    AssertNoAllocation no_gc;
1770    HandleScope scope(isolate);
1771    reinterpret_cast<HeapObject*>(new_object)->
1772        set_map(isolate->global_context()->regexp_result_map());
1773  }
1774  JSArray* array = JSArray::cast(new_object);
1775  array->set_properties(isolate->heap()->empty_fixed_array());
1776  array->set_elements(elements);
1777  array->set_length(Smi::FromInt(elements_count));
1778  // Write in-object properties after the length of the array.
1779  array->InObjectPropertyAtPut(JSRegExpResult::kIndexIndex, args[1]);
1780  array->InObjectPropertyAtPut(JSRegExpResult::kInputIndex, args[2]);
1781  return array;
1782}
1783
1784
1785RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) {
1786  AssertNoAllocation no_alloc;
1787  ASSERT(args.length() == 5);
1788  CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
1789  CONVERT_ARG_CHECKED(String, source, 1);
1790
1791  Object* global = args[2];
1792  if (!global->IsTrue()) global = isolate->heap()->false_value();
1793
1794  Object* ignoreCase = args[3];
1795  if (!ignoreCase->IsTrue()) ignoreCase = isolate->heap()->false_value();
1796
1797  Object* multiline = args[4];
1798  if (!multiline->IsTrue()) multiline = isolate->heap()->false_value();
1799
1800  Map* map = regexp->map();
1801  Object* constructor = map->constructor();
1802  if (constructor->IsJSFunction() &&
1803      JSFunction::cast(constructor)->initial_map() == map) {
1804    // If we still have the original map, set in-object properties directly.
1805    regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, source);
1806    // Both true and false are immovable immortal objects so no need for write
1807    // barrier.
1808    regexp->InObjectPropertyAtPut(
1809        JSRegExp::kGlobalFieldIndex, global, SKIP_WRITE_BARRIER);
1810    regexp->InObjectPropertyAtPut(
1811        JSRegExp::kIgnoreCaseFieldIndex, ignoreCase, SKIP_WRITE_BARRIER);
1812    regexp->InObjectPropertyAtPut(
1813        JSRegExp::kMultilineFieldIndex, multiline, SKIP_WRITE_BARRIER);
1814    regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex,
1815                                  Smi::FromInt(0),
1816                                  SKIP_WRITE_BARRIER);  // It's a Smi.
1817    return regexp;
1818  }
1819
1820  // Map has changed, so use generic, but slower, method.
1821  PropertyAttributes final =
1822      static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE);
1823  PropertyAttributes writable =
1824      static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
1825  Heap* heap = isolate->heap();
1826  MaybeObject* result;
1827  result = regexp->SetLocalPropertyIgnoreAttributes(heap->source_symbol(),
1828                                                    source,
1829                                                    final);
1830  ASSERT(!result->IsFailure());
1831  result = regexp->SetLocalPropertyIgnoreAttributes(heap->global_symbol(),
1832                                                    global,
1833                                                    final);
1834  ASSERT(!result->IsFailure());
1835  result =
1836      regexp->SetLocalPropertyIgnoreAttributes(heap->ignore_case_symbol(),
1837                                               ignoreCase,
1838                                               final);
1839  ASSERT(!result->IsFailure());
1840  result = regexp->SetLocalPropertyIgnoreAttributes(heap->multiline_symbol(),
1841                                                    multiline,
1842                                                    final);
1843  ASSERT(!result->IsFailure());
1844  result =
1845      regexp->SetLocalPropertyIgnoreAttributes(heap->last_index_symbol(),
1846                                               Smi::FromInt(0),
1847                                               writable);
1848  ASSERT(!result->IsFailure());
1849  USE(result);
1850  return regexp;
1851}
1852
1853
1854RUNTIME_FUNCTION(MaybeObject*, Runtime_FinishArrayPrototypeSetup) {
1855  HandleScope scope(isolate);
1856  ASSERT(args.length() == 1);
1857  CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0);
1858  // This is necessary to enable fast checks for absence of elements
1859  // on Array.prototype and below.
1860  prototype->set_elements(isolate->heap()->empty_fixed_array());
1861  return Smi::FromInt(0);
1862}
1863
1864
1865static Handle<JSFunction> InstallBuiltin(Isolate* isolate,
1866                                         Handle<JSObject> holder,
1867                                         const char* name,
1868                                         Builtins::Name builtin_name) {
1869  Handle<String> key = isolate->factory()->LookupAsciiSymbol(name);
1870  Handle<Code> code(isolate->builtins()->builtin(builtin_name));
1871  Handle<JSFunction> optimized =
1872      isolate->factory()->NewFunction(key,
1873                                      JS_OBJECT_TYPE,
1874                                      JSObject::kHeaderSize,
1875                                      code,
1876                                      false);
1877  optimized->shared()->DontAdaptArguments();
1878  JSReceiver::SetProperty(holder, key, optimized, NONE, kStrictMode);
1879  return optimized;
1880}
1881
1882
1883RUNTIME_FUNCTION(MaybeObject*, Runtime_SpecialArrayFunctions) {
1884  HandleScope scope(isolate);
1885  ASSERT(args.length() == 1);
1886  CONVERT_ARG_HANDLE_CHECKED(JSObject, holder, 0);
1887
1888  InstallBuiltin(isolate, holder, "pop", Builtins::kArrayPop);
1889  InstallBuiltin(isolate, holder, "push", Builtins::kArrayPush);
1890  InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift);
1891  InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift);
1892  InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice);
1893  InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
1894  InstallBuiltin(isolate, holder, "concat", Builtins::kArrayConcat);
1895
1896  return *holder;
1897}
1898
1899
1900RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultReceiver) {
1901  ASSERT(args.length() == 1);
1902  CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
1903
1904  if (!callable->IsJSFunction()) {
1905    HandleScope scope(isolate);
1906    bool threw = false;
1907    Handle<Object> delegate =
1908        Execution::TryGetFunctionDelegate(Handle<JSReceiver>(callable), &threw);
1909    if (threw) return Failure::Exception();
1910    callable = JSFunction::cast(*delegate);
1911  }
1912  JSFunction* function = JSFunction::cast(callable);
1913
1914  SharedFunctionInfo* shared = function->shared();
1915  if (shared->native() || !shared->is_classic_mode()) {
1916    return isolate->heap()->undefined_value();
1917  }
1918  // Returns undefined for strict or native functions, or
1919  // the associated global receiver for "normal" functions.
1920
1921  Context* global_context =
1922      function->context()->global()->global_context();
1923  return global_context->global()->global_receiver();
1924}
1925
1926
1927RUNTIME_FUNCTION(MaybeObject*, Runtime_MaterializeRegExpLiteral) {
1928  HandleScope scope(isolate);
1929  ASSERT(args.length() == 4);
1930  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
1931  int index = args.smi_at(1);
1932  Handle<String> pattern = args.at<String>(2);
1933  Handle<String> flags = args.at<String>(3);
1934
1935  // Get the RegExp function from the context in the literals array.
1936  // This is the RegExp function from the context in which the
1937  // function was created.  We do not use the RegExp function from the
1938  // current global context because this might be the RegExp function
1939  // from another context which we should not have access to.
1940  Handle<JSFunction> constructor =
1941      Handle<JSFunction>(
1942          JSFunction::GlobalContextFromLiterals(*literals)->regexp_function());
1943  // Compute the regular expression literal.
1944  bool has_pending_exception;
1945  Handle<Object> regexp =
1946      RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
1947                                      &has_pending_exception);
1948  if (has_pending_exception) {
1949    ASSERT(isolate->has_pending_exception());
1950    return Failure::Exception();
1951  }
1952  literals->set(index, *regexp);
1953  return *regexp;
1954}
1955
1956
1957RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetName) {
1958  NoHandleAllocation ha;
1959  ASSERT(args.length() == 1);
1960
1961  CONVERT_ARG_CHECKED(JSFunction, f, 0);
1962  return f->shared()->name();
1963}
1964
1965
1966RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetName) {
1967  NoHandleAllocation ha;
1968  ASSERT(args.length() == 2);
1969
1970  CONVERT_ARG_CHECKED(JSFunction, f, 0);
1971  CONVERT_ARG_CHECKED(String, name, 1);
1972  f->shared()->set_name(name);
1973  return isolate->heap()->undefined_value();
1974}
1975
1976
1977RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionNameShouldPrintAsAnonymous) {
1978  NoHandleAllocation ha;
1979  ASSERT(args.length() == 1);
1980  CONVERT_ARG_CHECKED(JSFunction, f, 0);
1981  return isolate->heap()->ToBoolean(
1982      f->shared()->name_should_print_as_anonymous());
1983}
1984
1985
1986RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) {
1987  NoHandleAllocation ha;
1988  ASSERT(args.length() == 1);
1989  CONVERT_ARG_CHECKED(JSFunction, f, 0);
1990  f->shared()->set_name_should_print_as_anonymous(true);
1991  return isolate->heap()->undefined_value();
1992}
1993
1994
1995RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) {
1996  NoHandleAllocation ha;
1997  ASSERT(args.length() == 1);
1998
1999  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2000  Object* obj = f->RemovePrototype();
2001  if (obj->IsFailure()) return obj;
2002
2003  return isolate->heap()->undefined_value();
2004}
2005
2006
2007RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScript) {
2008  HandleScope scope(isolate);
2009  ASSERT(args.length() == 1);
2010
2011  CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2012  Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate);
2013  if (!script->IsScript()) return isolate->heap()->undefined_value();
2014
2015  return *GetScriptWrapper(Handle<Script>::cast(script));
2016}
2017
2018
2019RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetSourceCode) {
2020  HandleScope scope(isolate);
2021  ASSERT(args.length() == 1);
2022
2023  CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0);
2024  Handle<SharedFunctionInfo> shared(f->shared());
2025  return *shared->GetSourceCode();
2026}
2027
2028
2029RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScriptSourcePosition) {
2030  NoHandleAllocation ha;
2031  ASSERT(args.length() == 1);
2032
2033  CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2034  int pos = fun->shared()->start_position();
2035  return Smi::FromInt(pos);
2036}
2037
2038
2039RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetPositionForOffset) {
2040  ASSERT(args.length() == 2);
2041
2042  CONVERT_ARG_CHECKED(Code, code, 0);
2043  CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]);
2044
2045  RUNTIME_ASSERT(0 <= offset && offset < code->Size());
2046
2047  Address pc = code->address() + offset;
2048  return Smi::FromInt(code->SourcePosition(pc));
2049}
2050
2051
2052RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetInstanceClassName) {
2053  NoHandleAllocation ha;
2054  ASSERT(args.length() == 2);
2055
2056  CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2057  CONVERT_ARG_CHECKED(String, name, 1);
2058  fun->SetInstanceClassName(name);
2059  return isolate->heap()->undefined_value();
2060}
2061
2062
2063RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetLength) {
2064  NoHandleAllocation ha;
2065  ASSERT(args.length() == 2);
2066
2067  CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2068  CONVERT_SMI_ARG_CHECKED(length, 1);
2069  fun->shared()->set_length(length);
2070  return isolate->heap()->undefined_value();
2071}
2072
2073
2074RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) {
2075  NoHandleAllocation ha;
2076  ASSERT(args.length() == 2);
2077
2078  CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2079  ASSERT(fun->should_have_prototype());
2080  Object* obj;
2081  { MaybeObject* maybe_obj =
2082        Accessors::FunctionSetPrototype(fun, args[1], NULL);
2083    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2084  }
2085  return args[0];  // return TOS
2086}
2087
2088
2089RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) {
2090  NoHandleAllocation ha;
2091  RUNTIME_ASSERT(args.length() == 1);
2092  CONVERT_ARG_CHECKED(JSFunction, function, 0);
2093
2094  MaybeObject* maybe_name =
2095      isolate->heap()->AllocateStringFromAscii(CStrVector("prototype"));
2096  String* name;
2097  if (!maybe_name->To(&name)) return maybe_name;
2098
2099  if (function->HasFastProperties()) {
2100    // Construct a new field descriptor with updated attributes.
2101    DescriptorArray* instance_desc = function->map()->instance_descriptors();
2102    int index = instance_desc->Search(name);
2103    ASSERT(index != DescriptorArray::kNotFound);
2104    PropertyDetails details(instance_desc->GetDetails(index));
2105    CallbacksDescriptor new_desc(name,
2106        instance_desc->GetValue(index),
2107        static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
2108        details.index());
2109    // Construct a new field descriptors array containing the new descriptor.
2110    Object* descriptors_unchecked;
2111    { MaybeObject* maybe_descriptors_unchecked =
2112        instance_desc->CopyInsert(&new_desc, REMOVE_TRANSITIONS);
2113      if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) {
2114        return maybe_descriptors_unchecked;
2115      }
2116    }
2117    DescriptorArray* new_descriptors =
2118        DescriptorArray::cast(descriptors_unchecked);
2119    // Create a new map featuring the new field descriptors array.
2120    Object* map_unchecked;
2121    { MaybeObject* maybe_map_unchecked = function->map()->CopyDropDescriptors();
2122      if (!maybe_map_unchecked->ToObject(&map_unchecked)) {
2123        return maybe_map_unchecked;
2124      }
2125    }
2126    Map* new_map = Map::cast(map_unchecked);
2127    new_map->set_instance_descriptors(new_descriptors);
2128    function->set_map(new_map);
2129  } else {  // Dictionary properties.
2130    // Directly manipulate the property details.
2131    int entry = function->property_dictionary()->FindEntry(name);
2132    ASSERT(entry != StringDictionary::kNotFound);
2133    PropertyDetails details = function->property_dictionary()->DetailsAt(entry);
2134    PropertyDetails new_details(
2135        static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
2136        details.type(),
2137        details.index());
2138    function->property_dictionary()->DetailsAtPut(entry, new_details);
2139  }
2140  return function;
2141}
2142
2143
2144RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) {
2145  NoHandleAllocation ha;
2146  ASSERT(args.length() == 1);
2147
2148  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2149  return isolate->heap()->ToBoolean(f->shared()->IsApiFunction());
2150}
2151
2152
2153RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) {
2154  NoHandleAllocation ha;
2155  ASSERT(args.length() == 1);
2156
2157  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2158  return isolate->heap()->ToBoolean(f->IsBuiltin());
2159}
2160
2161
2162RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
2163  HandleScope scope(isolate);
2164  ASSERT(args.length() == 2);
2165
2166  CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
2167  Handle<Object> code = args.at<Object>(1);
2168
2169  Handle<Context> context(target->context());
2170
2171  if (!code->IsNull()) {
2172    RUNTIME_ASSERT(code->IsJSFunction());
2173    Handle<JSFunction> fun = Handle<JSFunction>::cast(code);
2174    Handle<SharedFunctionInfo> shared(fun->shared());
2175
2176    if (!SharedFunctionInfo::EnsureCompiled(shared, KEEP_EXCEPTION)) {
2177      return Failure::Exception();
2178    }
2179    // Since we don't store the source for this we should never
2180    // optimize this.
2181    shared->code()->set_optimizable(false);
2182    // Set the code, scope info, formal parameter count,
2183    // and the length of the target function.
2184    target->shared()->set_code(shared->code());
2185    target->ReplaceCode(shared->code());
2186    target->shared()->set_scope_info(shared->scope_info());
2187    target->shared()->set_length(shared->length());
2188    target->shared()->set_formal_parameter_count(
2189        shared->formal_parameter_count());
2190    // Set the source code of the target function to undefined.
2191    // SetCode is only used for built-in constructors like String,
2192    // Array, and Object, and some web code
2193    // doesn't like seeing source code for constructors.
2194    target->shared()->set_script(isolate->heap()->undefined_value());
2195    target->shared()->code()->set_optimizable(false);
2196    // Clear the optimization hints related to the compiled code as these are no
2197    // longer valid when the code is overwritten.
2198    target->shared()->ClearThisPropertyAssignmentsInfo();
2199    context = Handle<Context>(fun->context());
2200
2201    // Make sure we get a fresh copy of the literal vector to avoid
2202    // cross context contamination.
2203    int number_of_literals = fun->NumberOfLiterals();
2204    Handle<FixedArray> literals =
2205        isolate->factory()->NewFixedArray(number_of_literals, TENURED);
2206    if (number_of_literals > 0) {
2207      // Insert the object, regexp and array functions in the literals
2208      // array prefix.  These are the functions that will be used when
2209      // creating object, regexp and array literals.
2210      literals->set(JSFunction::kLiteralGlobalContextIndex,
2211                    context->global_context());
2212    }
2213    target->set_literals(*literals);
2214    target->set_next_function_link(isolate->heap()->undefined_value());
2215
2216    if (isolate->logger()->is_logging() || CpuProfiler::is_profiling(isolate)) {
2217      isolate->logger()->LogExistingFunction(
2218          shared, Handle<Code>(shared->code()));
2219    }
2220  }
2221
2222  target->set_context(*context);
2223  return *target;
2224}
2225
2226
2227RUNTIME_FUNCTION(MaybeObject*, Runtime_SetExpectedNumberOfProperties) {
2228  HandleScope scope(isolate);
2229  ASSERT(args.length() == 2);
2230  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
2231  CONVERT_SMI_ARG_CHECKED(num, 1);
2232  RUNTIME_ASSERT(num >= 0);
2233  SetExpectedNofProperties(function, num);
2234  return isolate->heap()->undefined_value();
2235}
2236
2237
2238MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate,
2239                                                 Object* char_code) {
2240  uint32_t code;
2241  if (char_code->ToArrayIndex(&code)) {
2242    if (code <= 0xffff) {
2243      return isolate->heap()->LookupSingleCharacterStringFromCode(code);
2244    }
2245  }
2246  return isolate->heap()->empty_string();
2247}
2248
2249
2250RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCharCodeAt) {
2251  NoHandleAllocation ha;
2252  ASSERT(args.length() == 2);
2253
2254  CONVERT_ARG_CHECKED(String, subject, 0);
2255  Object* index = args[1];
2256  RUNTIME_ASSERT(index->IsNumber());
2257
2258  uint32_t i = 0;
2259  if (index->IsSmi()) {
2260    int value = Smi::cast(index)->value();
2261    if (value < 0) return isolate->heap()->nan_value();
2262    i = value;
2263  } else {
2264    ASSERT(index->IsHeapNumber());
2265    double value = HeapNumber::cast(index)->value();
2266    i = static_cast<uint32_t>(DoubleToInteger(value));
2267  }
2268
2269  // Flatten the string.  If someone wants to get a char at an index
2270  // in a cons string, it is likely that more indices will be
2271  // accessed.
2272  Object* flat;
2273  { MaybeObject* maybe_flat = subject->TryFlatten();
2274    if (!maybe_flat->ToObject(&flat)) return maybe_flat;
2275  }
2276  subject = String::cast(flat);
2277
2278  if (i >= static_cast<uint32_t>(subject->length())) {
2279    return isolate->heap()->nan_value();
2280  }
2281
2282  return Smi::FromInt(subject->Get(i));
2283}
2284
2285
2286RUNTIME_FUNCTION(MaybeObject*, Runtime_CharFromCode) {
2287  NoHandleAllocation ha;
2288  ASSERT(args.length() == 1);
2289  return CharFromCode(isolate, args[0]);
2290}
2291
2292
2293class FixedArrayBuilder {
2294 public:
2295  explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity)
2296      : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)),
2297        length_(0),
2298        has_non_smi_elements_(false) {
2299    // Require a non-zero initial size. Ensures that doubling the size to
2300    // extend the array will work.
2301    ASSERT(initial_capacity > 0);
2302  }
2303
2304  explicit FixedArrayBuilder(Handle<FixedArray> backing_store)
2305      : array_(backing_store),
2306        length_(0),
2307        has_non_smi_elements_(false) {
2308    // Require a non-zero initial size. Ensures that doubling the size to
2309    // extend the array will work.
2310    ASSERT(backing_store->length() > 0);
2311  }
2312
2313  bool HasCapacity(int elements) {
2314    int length = array_->length();
2315    int required_length = length_ + elements;
2316    return (length >= required_length);
2317  }
2318
2319  void EnsureCapacity(int elements) {
2320    int length = array_->length();
2321    int required_length = length_ + elements;
2322    if (length < required_length) {
2323      int new_length = length;
2324      do {
2325        new_length *= 2;
2326      } while (new_length < required_length);
2327      Handle<FixedArray> extended_array =
2328          array_->GetIsolate()->factory()->NewFixedArrayWithHoles(new_length);
2329      array_->CopyTo(0, *extended_array, 0, length_);
2330      array_ = extended_array;
2331    }
2332  }
2333
2334  void Add(Object* value) {
2335    ASSERT(!value->IsSmi());
2336    ASSERT(length_ < capacity());
2337    array_->set(length_, value);
2338    length_++;
2339    has_non_smi_elements_ = true;
2340  }
2341
2342  void Add(Smi* value) {
2343    ASSERT(value->IsSmi());
2344    ASSERT(length_ < capacity());
2345    array_->set(length_, value);
2346    length_++;
2347  }
2348
2349  Handle<FixedArray> array() {
2350    return array_;
2351  }
2352
2353  int length() {
2354    return length_;
2355  }
2356
2357  int capacity() {
2358    return array_->length();
2359  }
2360
2361  Handle<JSArray> ToJSArray() {
2362    Handle<JSArray> result_array = FACTORY->NewJSArrayWithElements(array_);
2363    result_array->set_length(Smi::FromInt(length_));
2364    return result_array;
2365  }
2366
2367  Handle<JSArray> ToJSArray(Handle<JSArray> target_array) {
2368    FACTORY->SetContent(target_array, array_);
2369    target_array->set_length(Smi::FromInt(length_));
2370    return target_array;
2371  }
2372
2373 private:
2374  Handle<FixedArray> array_;
2375  int length_;
2376  bool has_non_smi_elements_;
2377};
2378
2379
2380// Forward declarations.
2381const int kStringBuilderConcatHelperLengthBits = 11;
2382const int kStringBuilderConcatHelperPositionBits = 19;
2383
2384template <typename schar>
2385static inline void StringBuilderConcatHelper(String*,
2386                                             schar*,
2387                                             FixedArray*,
2388                                             int);
2389
2390typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits>
2391    StringBuilderSubstringLength;
2392typedef BitField<int,
2393                 kStringBuilderConcatHelperLengthBits,
2394                 kStringBuilderConcatHelperPositionBits>
2395    StringBuilderSubstringPosition;
2396
2397
2398class ReplacementStringBuilder {
2399 public:
2400  ReplacementStringBuilder(Heap* heap,
2401                           Handle<String> subject,
2402                           int estimated_part_count)
2403      : heap_(heap),
2404        array_builder_(heap->isolate(), estimated_part_count),
2405        subject_(subject),
2406        character_count_(0),
2407        is_ascii_(subject->IsAsciiRepresentation()) {
2408    // Require a non-zero initial size. Ensures that doubling the size to
2409    // extend the array will work.
2410    ASSERT(estimated_part_count > 0);
2411  }
2412
2413  static inline void AddSubjectSlice(FixedArrayBuilder* builder,
2414                                     int from,
2415                                     int to) {
2416    ASSERT(from >= 0);
2417    int length = to - from;
2418    ASSERT(length > 0);
2419    if (StringBuilderSubstringLength::is_valid(length) &&
2420        StringBuilderSubstringPosition::is_valid(from)) {
2421      int encoded_slice = StringBuilderSubstringLength::encode(length) |
2422          StringBuilderSubstringPosition::encode(from);
2423      builder->Add(Smi::FromInt(encoded_slice));
2424    } else {
2425      // Otherwise encode as two smis.
2426      builder->Add(Smi::FromInt(-length));
2427      builder->Add(Smi::FromInt(from));
2428    }
2429  }
2430
2431
2432  void EnsureCapacity(int elements) {
2433    array_builder_.EnsureCapacity(elements);
2434  }
2435
2436
2437  void AddSubjectSlice(int from, int to) {
2438    AddSubjectSlice(&array_builder_, from, to);
2439    IncrementCharacterCount(to - from);
2440  }
2441
2442
2443  void AddString(Handle<String> string) {
2444    int length = string->length();
2445    ASSERT(length > 0);
2446    AddElement(*string);
2447    if (!string->IsAsciiRepresentation()) {
2448      is_ascii_ = false;
2449    }
2450    IncrementCharacterCount(length);
2451  }
2452
2453
2454  Handle<String> ToString() {
2455    if (array_builder_.length() == 0) {
2456      return heap_->isolate()->factory()->empty_string();
2457    }
2458
2459    Handle<String> joined_string;
2460    if (is_ascii_) {
2461      Handle<SeqAsciiString> seq = NewRawAsciiString(character_count_);
2462      AssertNoAllocation no_alloc;
2463      char* char_buffer = seq->GetChars();
2464      StringBuilderConcatHelper(*subject_,
2465                                char_buffer,
2466                                *array_builder_.array(),
2467                                array_builder_.length());
2468      joined_string = Handle<String>::cast(seq);
2469    } else {
2470      // Non-ASCII.
2471      Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_);
2472      AssertNoAllocation no_alloc;
2473      uc16* char_buffer = seq->GetChars();
2474      StringBuilderConcatHelper(*subject_,
2475                                char_buffer,
2476                                *array_builder_.array(),
2477                                array_builder_.length());
2478      joined_string = Handle<String>::cast(seq);
2479    }
2480    return joined_string;
2481  }
2482
2483
2484  void IncrementCharacterCount(int by) {
2485    if (character_count_ > String::kMaxLength - by) {
2486      V8::FatalProcessOutOfMemory("String.replace result too large.");
2487    }
2488    character_count_ += by;
2489  }
2490
2491  Handle<JSArray> GetParts() {
2492    return array_builder_.ToJSArray();
2493  }
2494
2495 private:
2496  Handle<SeqAsciiString> NewRawAsciiString(int length) {
2497    return heap_->isolate()->factory()->NewRawAsciiString(length);
2498  }
2499
2500
2501  Handle<SeqTwoByteString> NewRawTwoByteString(int length) {
2502    return heap_->isolate()->factory()->NewRawTwoByteString(length);
2503  }
2504
2505
2506  void AddElement(Object* element) {
2507    ASSERT(element->IsSmi() || element->IsString());
2508    ASSERT(array_builder_.capacity() > array_builder_.length());
2509    array_builder_.Add(element);
2510  }
2511
2512  Heap* heap_;
2513  FixedArrayBuilder array_builder_;
2514  Handle<String> subject_;
2515  int character_count_;
2516  bool is_ascii_;
2517};
2518
2519
2520class CompiledReplacement {
2521 public:
2522  CompiledReplacement()
2523      : parts_(1), replacement_substrings_(0), simple_hint_(false) {}
2524
2525  void Compile(Handle<String> replacement,
2526               int capture_count,
2527               int subject_length);
2528
2529  void Apply(ReplacementStringBuilder* builder,
2530             int match_from,
2531             int match_to,
2532             Handle<JSArray> last_match_info);
2533
2534  // Number of distinct parts of the replacement pattern.
2535  int parts() {
2536    return parts_.length();
2537  }
2538
2539  bool simple_hint() {
2540    return simple_hint_;
2541  }
2542
2543 private:
2544  enum PartType {
2545    SUBJECT_PREFIX = 1,
2546    SUBJECT_SUFFIX,
2547    SUBJECT_CAPTURE,
2548    REPLACEMENT_SUBSTRING,
2549    REPLACEMENT_STRING,
2550
2551    NUMBER_OF_PART_TYPES
2552  };
2553
2554  struct ReplacementPart {
2555    static inline ReplacementPart SubjectMatch() {
2556      return ReplacementPart(SUBJECT_CAPTURE, 0);
2557    }
2558    static inline ReplacementPart SubjectCapture(int capture_index) {
2559      return ReplacementPart(SUBJECT_CAPTURE, capture_index);
2560    }
2561    static inline ReplacementPart SubjectPrefix() {
2562      return ReplacementPart(SUBJECT_PREFIX, 0);
2563    }
2564    static inline ReplacementPart SubjectSuffix(int subject_length) {
2565      return ReplacementPart(SUBJECT_SUFFIX, subject_length);
2566    }
2567    static inline ReplacementPart ReplacementString() {
2568      return ReplacementPart(REPLACEMENT_STRING, 0);
2569    }
2570    static inline ReplacementPart ReplacementSubString(int from, int to) {
2571      ASSERT(from >= 0);
2572      ASSERT(to > from);
2573      return ReplacementPart(-from, to);
2574    }
2575
2576    // If tag <= 0 then it is the negation of a start index of a substring of
2577    // the replacement pattern, otherwise it's a value from PartType.
2578    ReplacementPart(int tag, int data)
2579        : tag(tag), data(data) {
2580      // Must be non-positive or a PartType value.
2581      ASSERT(tag < NUMBER_OF_PART_TYPES);
2582    }
2583    // Either a value of PartType or a non-positive number that is
2584    // the negation of an index into the replacement string.
2585    int tag;
2586    // The data value's interpretation depends on the value of tag:
2587    // tag == SUBJECT_PREFIX ||
2588    // tag == SUBJECT_SUFFIX:  data is unused.
2589    // tag == SUBJECT_CAPTURE: data is the number of the capture.
2590    // tag == REPLACEMENT_SUBSTRING ||
2591    // tag == REPLACEMENT_STRING:    data is index into array of substrings
2592    //                               of the replacement string.
2593    // tag <= 0: Temporary representation of the substring of the replacement
2594    //           string ranging over -tag .. data.
2595    //           Is replaced by REPLACEMENT_{SUB,}STRING when we create the
2596    //           substring objects.
2597    int data;
2598  };
2599
2600  template<typename Char>
2601  static bool ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
2602                                      Vector<Char> characters,
2603                                      int capture_count,
2604                                      int subject_length) {
2605    int length = characters.length();
2606    int last = 0;
2607    for (int i = 0; i < length; i++) {
2608      Char c = characters[i];
2609      if (c == '$') {
2610        int next_index = i + 1;
2611        if (next_index == length) {  // No next character!
2612          break;
2613        }
2614        Char c2 = characters[next_index];
2615        switch (c2) {
2616        case '$':
2617          if (i > last) {
2618            // There is a substring before. Include the first "$".
2619            parts->Add(ReplacementPart::ReplacementSubString(last, next_index));
2620            last = next_index + 1;  // Continue after the second "$".
2621          } else {
2622            // Let the next substring start with the second "$".
2623            last = next_index;
2624          }
2625          i = next_index;
2626          break;
2627        case '`':
2628          if (i > last) {
2629            parts->Add(ReplacementPart::ReplacementSubString(last, i));
2630          }
2631          parts->Add(ReplacementPart::SubjectPrefix());
2632          i = next_index;
2633          last = i + 1;
2634          break;
2635        case '\'':
2636          if (i > last) {
2637            parts->Add(ReplacementPart::ReplacementSubString(last, i));
2638          }
2639          parts->Add(ReplacementPart::SubjectSuffix(subject_length));
2640          i = next_index;
2641          last = i + 1;
2642          break;
2643        case '&':
2644          if (i > last) {
2645            parts->Add(ReplacementPart::ReplacementSubString(last, i));
2646          }
2647          parts->Add(ReplacementPart::SubjectMatch());
2648          i = next_index;
2649          last = i + 1;
2650          break;
2651        case '0':
2652        case '1':
2653        case '2':
2654        case '3':
2655        case '4':
2656        case '5':
2657        case '6':
2658        case '7':
2659        case '8':
2660        case '9': {
2661          int capture_ref = c2 - '0';
2662          if (capture_ref > capture_count) {
2663            i = next_index;
2664            continue;
2665          }
2666          int second_digit_index = next_index + 1;
2667          if (second_digit_index < length) {
2668            // Peek ahead to see if we have two digits.
2669            Char c3 = characters[second_digit_index];
2670            if ('0' <= c3 && c3 <= '9') {  // Double digits.
2671              int double_digit_ref = capture_ref * 10 + c3 - '0';
2672              if (double_digit_ref <= capture_count) {
2673                next_index = second_digit_index;
2674                capture_ref = double_digit_ref;
2675              }
2676            }
2677          }
2678          if (capture_ref > 0) {
2679            if (i > last) {
2680              parts->Add(ReplacementPart::ReplacementSubString(last, i));
2681            }
2682            ASSERT(capture_ref <= capture_count);
2683            parts->Add(ReplacementPart::SubjectCapture(capture_ref));
2684            last = next_index + 1;
2685          }
2686          i = next_index;
2687          break;
2688        }
2689        default:
2690          i = next_index;
2691          break;
2692        }
2693      }
2694    }
2695    if (length > last) {
2696      if (last == 0) {
2697        parts->Add(ReplacementPart::ReplacementString());
2698        return true;
2699      } else {
2700        parts->Add(ReplacementPart::ReplacementSubString(last, length));
2701      }
2702    }
2703    return false;
2704  }
2705
2706  ZoneList<ReplacementPart> parts_;
2707  ZoneList<Handle<String> > replacement_substrings_;
2708  bool simple_hint_;
2709};
2710
2711
2712void CompiledReplacement::Compile(Handle<String> replacement,
2713                                  int capture_count,
2714                                  int subject_length) {
2715  {
2716    AssertNoAllocation no_alloc;
2717    String::FlatContent content = replacement->GetFlatContent();
2718    ASSERT(content.IsFlat());
2719    if (content.IsAscii()) {
2720      simple_hint_ = ParseReplacementPattern(&parts_,
2721                                             content.ToAsciiVector(),
2722                                             capture_count,
2723                                             subject_length);
2724    } else {
2725      ASSERT(content.IsTwoByte());
2726      simple_hint_ = ParseReplacementPattern(&parts_,
2727                                             content.ToUC16Vector(),
2728                                             capture_count,
2729                                             subject_length);
2730    }
2731  }
2732  Isolate* isolate = replacement->GetIsolate();
2733  // Find substrings of replacement string and create them as String objects.
2734  int substring_index = 0;
2735  for (int i = 0, n = parts_.length(); i < n; i++) {
2736    int tag = parts_[i].tag;
2737    if (tag <= 0) {  // A replacement string slice.
2738      int from = -tag;
2739      int to = parts_[i].data;
2740      replacement_substrings_.Add(
2741          isolate->factory()->NewSubString(replacement, from, to));
2742      parts_[i].tag = REPLACEMENT_SUBSTRING;
2743      parts_[i].data = substring_index;
2744      substring_index++;
2745    } else if (tag == REPLACEMENT_STRING) {
2746      replacement_substrings_.Add(replacement);
2747      parts_[i].data = substring_index;
2748      substring_index++;
2749    }
2750  }
2751}
2752
2753
2754void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
2755                                int match_from,
2756                                int match_to,
2757                                Handle<JSArray> last_match_info) {
2758  for (int i = 0, n = parts_.length(); i < n; i++) {
2759    ReplacementPart part = parts_[i];
2760    switch (part.tag) {
2761      case SUBJECT_PREFIX:
2762        if (match_from > 0) builder->AddSubjectSlice(0, match_from);
2763        break;
2764      case SUBJECT_SUFFIX: {
2765        int subject_length = part.data;
2766        if (match_to < subject_length) {
2767          builder->AddSubjectSlice(match_to, subject_length);
2768        }
2769        break;
2770      }
2771      case SUBJECT_CAPTURE: {
2772        int capture = part.data;
2773        FixedArray* match_info = FixedArray::cast(last_match_info->elements());
2774        int from = RegExpImpl::GetCapture(match_info, capture * 2);
2775        int to = RegExpImpl::GetCapture(match_info, capture * 2 + 1);
2776        if (from >= 0 && to > from) {
2777          builder->AddSubjectSlice(from, to);
2778        }
2779        break;
2780      }
2781      case REPLACEMENT_SUBSTRING:
2782      case REPLACEMENT_STRING:
2783        builder->AddString(replacement_substrings_[part.data]);
2784        break;
2785      default:
2786        UNREACHABLE();
2787    }
2788  }
2789}
2790
2791
2792void FindAsciiStringIndices(Vector<const char> subject,
2793                            char pattern,
2794                            ZoneList<int>* indices,
2795                            unsigned int limit) {
2796  ASSERT(limit > 0);
2797  // Collect indices of pattern in subject using memchr.
2798  // Stop after finding at most limit values.
2799  const char* subject_start = reinterpret_cast<const char*>(subject.start());
2800  const char* subject_end = subject_start + subject.length();
2801  const char* pos = subject_start;
2802  while (limit > 0) {
2803    pos = reinterpret_cast<const char*>(
2804        memchr(pos, pattern, subject_end - pos));
2805    if (pos == NULL) return;
2806    indices->Add(static_cast<int>(pos - subject_start));
2807    pos++;
2808    limit--;
2809  }
2810}
2811
2812
2813template <typename SubjectChar, typename PatternChar>
2814void FindStringIndices(Isolate* isolate,
2815                       Vector<const SubjectChar> subject,
2816                       Vector<const PatternChar> pattern,
2817                       ZoneList<int>* indices,
2818                       unsigned int limit) {
2819  ASSERT(limit > 0);
2820  // Collect indices of pattern in subject.
2821  // Stop after finding at most limit values.
2822  int pattern_length = pattern.length();
2823  int index = 0;
2824  StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
2825  while (limit > 0) {
2826    index = search.Search(subject, index);
2827    if (index < 0) return;
2828    indices->Add(index);
2829    index += pattern_length;
2830    limit--;
2831  }
2832}
2833
2834
2835void FindStringIndicesDispatch(Isolate* isolate,
2836                               String* subject,
2837                               String* pattern,
2838                               ZoneList<int>* indices,
2839                               unsigned int limit) {
2840  {
2841    AssertNoAllocation no_gc;
2842    String::FlatContent subject_content = subject->GetFlatContent();
2843    String::FlatContent pattern_content = pattern->GetFlatContent();
2844    ASSERT(subject_content.IsFlat());
2845    ASSERT(pattern_content.IsFlat());
2846    if (subject_content.IsAscii()) {
2847      Vector<const char> subject_vector = subject_content.ToAsciiVector();
2848      if (pattern_content.IsAscii()) {
2849        Vector<const char> pattern_vector = pattern_content.ToAsciiVector();
2850        if (pattern_vector.length() == 1) {
2851          FindAsciiStringIndices(subject_vector,
2852                                 pattern_vector[0],
2853                                 indices,
2854                                 limit);
2855        } else {
2856          FindStringIndices(isolate,
2857                            subject_vector,
2858                            pattern_vector,
2859                            indices,
2860                            limit);
2861        }
2862      } else {
2863        FindStringIndices(isolate,
2864                          subject_vector,
2865                          pattern_content.ToUC16Vector(),
2866                          indices,
2867                          limit);
2868      }
2869    } else {
2870      Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
2871      if (pattern_content.IsAscii()) {
2872        FindStringIndices(isolate,
2873                          subject_vector,
2874                          pattern_content.ToAsciiVector(),
2875                          indices,
2876                          limit);
2877      } else {
2878        FindStringIndices(isolate,
2879                          subject_vector,
2880                          pattern_content.ToUC16Vector(),
2881                          indices,
2882                          limit);
2883      }
2884    }
2885  }
2886}
2887
2888
2889template<typename ResultSeqString>
2890MUST_USE_RESULT static MaybeObject* StringReplaceStringWithString(
2891    Isolate* isolate,
2892    Handle<String> subject,
2893    Handle<JSRegExp> pattern_regexp,
2894    Handle<String> replacement) {
2895  ASSERT(subject->IsFlat());
2896  ASSERT(replacement->IsFlat());
2897
2898  ZoneScope zone_space(isolate, DELETE_ON_EXIT);
2899  ZoneList<int> indices(8);
2900  ASSERT_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag());
2901  String* pattern =
2902      String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex));
2903  int subject_len = subject->length();
2904  int pattern_len = pattern->length();
2905  int replacement_len = replacement->length();
2906
2907  FindStringIndicesDispatch(isolate, *subject, pattern, &indices, 0xffffffff);
2908
2909  int matches = indices.length();
2910  if (matches == 0) return *subject;
2911
2912  int result_len = (replacement_len - pattern_len) * matches + subject_len;
2913  int subject_pos = 0;
2914  int result_pos = 0;
2915
2916  Handle<ResultSeqString> result;
2917  if (ResultSeqString::kHasAsciiEncoding) {
2918    result = Handle<ResultSeqString>::cast(
2919        isolate->factory()->NewRawAsciiString(result_len));
2920  } else {
2921    result = Handle<ResultSeqString>::cast(
2922        isolate->factory()->NewRawTwoByteString(result_len));
2923  }
2924
2925  for (int i = 0; i < matches; i++) {
2926    // Copy non-matched subject content.
2927    if (subject_pos < indices.at(i)) {
2928      String::WriteToFlat(*subject,
2929                          result->GetChars() + result_pos,
2930                          subject_pos,
2931                          indices.at(i));
2932      result_pos += indices.at(i) - subject_pos;
2933    }
2934
2935    // Replace match.
2936    if (replacement_len > 0) {
2937      String::WriteToFlat(*replacement,
2938                          result->GetChars() + result_pos,
2939                          0,
2940                          replacement_len);
2941      result_pos += replacement_len;
2942    }
2943
2944    subject_pos = indices.at(i) + pattern_len;
2945  }
2946  // Add remaining subject content at the end.
2947  if (subject_pos < subject_len) {
2948    String::WriteToFlat(*subject,
2949                        result->GetChars() + result_pos,
2950                        subject_pos,
2951                        subject_len);
2952  }
2953  return *result;
2954}
2955
2956
2957MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithString(
2958    Isolate* isolate,
2959    String* subject,
2960    JSRegExp* regexp,
2961    String* replacement,
2962    JSArray* last_match_info) {
2963  ASSERT(subject->IsFlat());
2964  ASSERT(replacement->IsFlat());
2965
2966  HandleScope handles(isolate);
2967
2968  int length = subject->length();
2969  Handle<String> subject_handle(subject);
2970  Handle<JSRegExp> regexp_handle(regexp);
2971  Handle<String> replacement_handle(replacement);
2972  Handle<JSArray> last_match_info_handle(last_match_info);
2973  Handle<Object> match = RegExpImpl::Exec(regexp_handle,
2974                                          subject_handle,
2975                                          0,
2976                                          last_match_info_handle);
2977  if (match.is_null()) {
2978    return Failure::Exception();
2979  }
2980  if (match->IsNull()) {
2981    return *subject_handle;
2982  }
2983
2984  int capture_count = regexp_handle->CaptureCount();
2985
2986  // CompiledReplacement uses zone allocation.
2987  ZoneScope zone(isolate, DELETE_ON_EXIT);
2988  CompiledReplacement compiled_replacement;
2989  compiled_replacement.Compile(replacement_handle,
2990                               capture_count,
2991                               length);
2992
2993  bool is_global = regexp_handle->GetFlags().is_global();
2994
2995  // Shortcut for simple non-regexp global replacements
2996  if (is_global &&
2997      regexp_handle->TypeTag() == JSRegExp::ATOM &&
2998      compiled_replacement.simple_hint()) {
2999    if (subject_handle->HasOnlyAsciiChars() &&
3000        replacement_handle->HasOnlyAsciiChars()) {
3001      return StringReplaceStringWithString<SeqAsciiString>(
3002          isolate, subject_handle, regexp_handle, replacement_handle);
3003    } else {
3004      return StringReplaceStringWithString<SeqTwoByteString>(
3005          isolate, subject_handle, regexp_handle, replacement_handle);
3006    }
3007  }
3008
3009  // Guessing the number of parts that the final result string is built
3010  // from. Global regexps can match any number of times, so we guess
3011  // conservatively.
3012  int expected_parts =
3013      (compiled_replacement.parts() + 1) * (is_global ? 4 : 1) + 1;
3014  ReplacementStringBuilder builder(isolate->heap(),
3015                                   subject_handle,
3016                                   expected_parts);
3017
3018  // Index of end of last match.
3019  int prev = 0;
3020
3021  // Number of parts added by compiled replacement plus preceeding
3022  // string and possibly suffix after last match.  It is possible for
3023  // all components to use two elements when encoded as two smis.
3024  const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2);
3025  bool matched = true;
3026  do {
3027    ASSERT(last_match_info_handle->HasFastElements());
3028    // Increase the capacity of the builder before entering local handle-scope,
3029    // so its internal buffer can safely allocate a new handle if it grows.
3030    builder.EnsureCapacity(parts_added_per_loop);
3031
3032    HandleScope loop_scope(isolate);
3033    int start, end;
3034    {
3035      AssertNoAllocation match_info_array_is_not_in_a_handle;
3036      FixedArray* match_info_array =
3037          FixedArray::cast(last_match_info_handle->elements());
3038
3039      ASSERT_EQ(capture_count * 2 + 2,
3040                RegExpImpl::GetLastCaptureCount(match_info_array));
3041      start = RegExpImpl::GetCapture(match_info_array, 0);
3042      end = RegExpImpl::GetCapture(match_info_array, 1);
3043    }
3044
3045    if (prev < start) {
3046      builder.AddSubjectSlice(prev, start);
3047    }
3048    compiled_replacement.Apply(&builder,
3049                               start,
3050                               end,
3051                               last_match_info_handle);
3052    prev = end;
3053
3054    // Only continue checking for global regexps.
3055    if (!is_global) break;
3056
3057    // Continue from where the match ended, unless it was an empty match.
3058    int next = end;
3059    if (start == end) {
3060      next = end + 1;
3061      if (next > length) break;
3062    }
3063
3064    match = RegExpImpl::Exec(regexp_handle,
3065                             subject_handle,
3066                             next,
3067                             last_match_info_handle);
3068    if (match.is_null()) {
3069      return Failure::Exception();
3070    }
3071    matched = !match->IsNull();
3072  } while (matched);
3073
3074  if (prev < length) {
3075    builder.AddSubjectSlice(prev, length);
3076  }
3077
3078  return *(builder.ToString());
3079}
3080
3081
3082template <typename ResultSeqString>
3083MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithEmptyString(
3084    Isolate* isolate,
3085    String* subject,
3086    JSRegExp* regexp,
3087    JSArray* last_match_info) {
3088  ASSERT(subject->IsFlat());
3089
3090  HandleScope handles(isolate);
3091
3092  Handle<String> subject_handle(subject);
3093  Handle<JSRegExp> regexp_handle(regexp);
3094
3095  // Shortcut for simple non-regexp global replacements
3096  if (regexp_handle->GetFlags().is_global() &&
3097      regexp_handle->TypeTag() == JSRegExp::ATOM) {
3098    Handle<String> empty_string_handle(HEAP->empty_string());
3099    if (subject_handle->HasOnlyAsciiChars()) {
3100      return StringReplaceStringWithString<SeqAsciiString>(
3101          isolate, subject_handle, regexp_handle, empty_string_handle);
3102    } else {
3103      return StringReplaceStringWithString<SeqTwoByteString>(
3104          isolate, subject_handle, regexp_handle, empty_string_handle);
3105    }
3106  }
3107
3108  Handle<JSArray> last_match_info_handle(last_match_info);
3109  Handle<Object> match = RegExpImpl::Exec(regexp_handle,
3110                                          subject_handle,
3111                                          0,
3112                                          last_match_info_handle);
3113  if (match.is_null()) return Failure::Exception();
3114  if (match->IsNull()) return *subject_handle;
3115
3116  ASSERT(last_match_info_handle->HasFastElements());
3117
3118  int start, end;
3119  {
3120    AssertNoAllocation match_info_array_is_not_in_a_handle;
3121    FixedArray* match_info_array =
3122        FixedArray::cast(last_match_info_handle->elements());
3123
3124    start = RegExpImpl::GetCapture(match_info_array, 0);
3125    end = RegExpImpl::GetCapture(match_info_array, 1);
3126  }
3127
3128  int length = subject_handle->length();
3129  int new_length = length - (end - start);
3130  if (new_length == 0) {
3131    return isolate->heap()->empty_string();
3132  }
3133  Handle<ResultSeqString> answer;
3134  if (ResultSeqString::kHasAsciiEncoding) {
3135    answer = Handle<ResultSeqString>::cast(
3136        isolate->factory()->NewRawAsciiString(new_length));
3137  } else {
3138    answer = Handle<ResultSeqString>::cast(
3139        isolate->factory()->NewRawTwoByteString(new_length));
3140  }
3141
3142  // If the regexp isn't global, only match once.
3143  if (!regexp_handle->GetFlags().is_global()) {
3144    if (start > 0) {
3145      String::WriteToFlat(*subject_handle,
3146                          answer->GetChars(),
3147                          0,
3148                          start);
3149    }
3150    if (end < length) {
3151      String::WriteToFlat(*subject_handle,
3152                          answer->GetChars() + start,
3153                          end,
3154                          length);
3155    }
3156    return *answer;
3157  }
3158
3159  int prev = 0;  // Index of end of last match.
3160  int next = 0;  // Start of next search (prev unless last match was empty).
3161  int position = 0;
3162
3163  do {
3164    if (prev < start) {
3165      // Add substring subject[prev;start] to answer string.
3166      String::WriteToFlat(*subject_handle,
3167                          answer->GetChars() + position,
3168                          prev,
3169                          start);
3170      position += start - prev;
3171    }
3172    prev = end;
3173    next = end;
3174    // Continue from where the match ended, unless it was an empty match.
3175    if (start == end) {
3176      next++;
3177      if (next > length) break;
3178    }
3179    match = RegExpImpl::Exec(regexp_handle,
3180                             subject_handle,
3181                             next,
3182                             last_match_info_handle);
3183    if (match.is_null()) return Failure::Exception();
3184    if (match->IsNull()) break;
3185
3186    ASSERT(last_match_info_handle->HasFastElements());
3187    HandleScope loop_scope(isolate);
3188    {
3189      AssertNoAllocation match_info_array_is_not_in_a_handle;
3190      FixedArray* match_info_array =
3191          FixedArray::cast(last_match_info_handle->elements());
3192      start = RegExpImpl::GetCapture(match_info_array, 0);
3193      end = RegExpImpl::GetCapture(match_info_array, 1);
3194    }
3195  } while (true);
3196
3197  if (prev < length) {
3198    // Add substring subject[prev;length] to answer string.
3199    String::WriteToFlat(*subject_handle,
3200                        answer->GetChars() + position,
3201                        prev,
3202                        length);
3203    position += length - prev;
3204  }
3205
3206  if (position == 0) {
3207    return isolate->heap()->empty_string();
3208  }
3209
3210  // Shorten string and fill
3211  int string_size = ResultSeqString::SizeFor(position);
3212  int allocated_string_size = ResultSeqString::SizeFor(new_length);
3213  int delta = allocated_string_size - string_size;
3214
3215  answer->set_length(position);
3216  if (delta == 0) return *answer;
3217
3218  Address end_of_string = answer->address() + string_size;
3219  isolate->heap()->CreateFillerObjectAt(end_of_string, delta);
3220  if (Marking::IsBlack(Marking::MarkBitFrom(*answer))) {
3221    MemoryChunk::IncrementLiveBytesFromMutator(answer->address(), -delta);
3222  }
3223
3224  return *answer;
3225}
3226
3227
3228RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceRegExpWithString) {
3229  ASSERT(args.length() == 4);
3230
3231  CONVERT_ARG_CHECKED(String, subject, 0);
3232  if (!subject->IsFlat()) {
3233    Object* flat_subject;
3234    { MaybeObject* maybe_flat_subject = subject->TryFlatten();
3235      if (!maybe_flat_subject->ToObject(&flat_subject)) {
3236        return maybe_flat_subject;
3237      }
3238    }
3239    subject = String::cast(flat_subject);
3240  }
3241
3242  CONVERT_ARG_CHECKED(String, replacement, 2);
3243  if (!replacement->IsFlat()) {
3244    Object* flat_replacement;
3245    { MaybeObject* maybe_flat_replacement = replacement->TryFlatten();
3246      if (!maybe_flat_replacement->ToObject(&flat_replacement)) {
3247        return maybe_flat_replacement;
3248      }
3249    }
3250    replacement = String::cast(flat_replacement);
3251  }
3252
3253  CONVERT_ARG_CHECKED(JSRegExp, regexp, 1);
3254  CONVERT_ARG_CHECKED(JSArray, last_match_info, 3);
3255
3256  ASSERT(last_match_info->HasFastElements());
3257
3258  if (replacement->length() == 0) {
3259    if (subject->HasOnlyAsciiChars()) {
3260      return StringReplaceRegExpWithEmptyString<SeqAsciiString>(
3261          isolate, subject, regexp, last_match_info);
3262    } else {
3263      return StringReplaceRegExpWithEmptyString<SeqTwoByteString>(
3264          isolate, subject, regexp, last_match_info);
3265    }
3266  }
3267
3268  return StringReplaceRegExpWithString(isolate,
3269                                       subject,
3270                                       regexp,
3271                                       replacement,
3272                                       last_match_info);
3273}
3274
3275
3276Handle<String> Runtime::StringReplaceOneCharWithString(Isolate* isolate,
3277                                                       Handle<String> subject,
3278                                                       Handle<String> search,
3279                                                       Handle<String> replace,
3280                                                       bool* found,
3281                                                       int recursion_limit) {
3282  if (recursion_limit == 0) return Handle<String>::null();
3283  if (subject->IsConsString()) {
3284    ConsString* cons = ConsString::cast(*subject);
3285    Handle<String> first = Handle<String>(cons->first());
3286    Handle<String> second = Handle<String>(cons->second());
3287    Handle<String> new_first =
3288        StringReplaceOneCharWithString(isolate,
3289                                       first,
3290                                       search,
3291                                       replace,
3292                                       found,
3293                                       recursion_limit - 1);
3294    if (*found) return isolate->factory()->NewConsString(new_first, second);
3295    if (new_first.is_null()) return new_first;
3296
3297    Handle<String> new_second =
3298        StringReplaceOneCharWithString(isolate,
3299                                       second,
3300                                       search,
3301                                       replace,
3302                                       found,
3303                                       recursion_limit - 1);
3304    if (*found) return isolate->factory()->NewConsString(first, new_second);
3305    if (new_second.is_null()) return new_second;
3306
3307    return subject;
3308  } else {
3309    int index = StringMatch(isolate, subject, search, 0);
3310    if (index == -1) return subject;
3311    *found = true;
3312    Handle<String> first = isolate->factory()->NewSubString(subject, 0, index);
3313    Handle<String> cons1 = isolate->factory()->NewConsString(first, replace);
3314    Handle<String> second =
3315        isolate->factory()->NewSubString(subject, index + 1, subject->length());
3316    return isolate->factory()->NewConsString(cons1, second);
3317  }
3318}
3319
3320
3321RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) {
3322  ASSERT(args.length() == 3);
3323  HandleScope scope(isolate);
3324  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
3325  CONVERT_ARG_HANDLE_CHECKED(String, search, 1);
3326  CONVERT_ARG_HANDLE_CHECKED(String, replace, 2);
3327
3328  // If the cons string tree is too deep, we simply abort the recursion and
3329  // retry with a flattened subject string.
3330  const int kRecursionLimit = 0x1000;
3331  bool found = false;
3332  Handle<String> result =
3333      Runtime::StringReplaceOneCharWithString(isolate,
3334                                              subject,
3335                                              search,
3336                                              replace,
3337                                              &found,
3338                                              kRecursionLimit);
3339  if (!result.is_null()) return *result;
3340  return *Runtime::StringReplaceOneCharWithString(isolate,
3341                                                  FlattenGetString(subject),
3342                                                  search,
3343                                                  replace,
3344                                                  &found,
3345                                                  kRecursionLimit);
3346}
3347
3348
3349// Perform string match of pattern on subject, starting at start index.
3350// Caller must ensure that 0 <= start_index <= sub->length(),
3351// and should check that pat->length() + start_index <= sub->length().
3352int Runtime::StringMatch(Isolate* isolate,
3353                         Handle<String> sub,
3354                         Handle<String> pat,
3355                         int start_index) {
3356  ASSERT(0 <= start_index);
3357  ASSERT(start_index <= sub->length());
3358
3359  int pattern_length = pat->length();
3360  if (pattern_length == 0) return start_index;
3361
3362  int subject_length = sub->length();
3363  if (start_index + pattern_length > subject_length) return -1;
3364
3365  if (!sub->IsFlat()) FlattenString(sub);
3366  if (!pat->IsFlat()) FlattenString(pat);
3367
3368  AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
3369  // Extract flattened substrings of cons strings before determining asciiness.
3370  String::FlatContent seq_sub = sub->GetFlatContent();
3371  String::FlatContent seq_pat = pat->GetFlatContent();
3372
3373  // dispatch on type of strings
3374  if (seq_pat.IsAscii()) {
3375    Vector<const char> pat_vector = seq_pat.ToAsciiVector();
3376    if (seq_sub.IsAscii()) {
3377      return SearchString(isolate,
3378                          seq_sub.ToAsciiVector(),
3379                          pat_vector,
3380                          start_index);
3381    }
3382    return SearchString(isolate,
3383                        seq_sub.ToUC16Vector(),
3384                        pat_vector,
3385                        start_index);
3386  }
3387  Vector<const uc16> pat_vector = seq_pat.ToUC16Vector();
3388  if (seq_sub.IsAscii()) {
3389    return SearchString(isolate,
3390                        seq_sub.ToAsciiVector(),
3391                        pat_vector,
3392                        start_index);
3393  }
3394  return SearchString(isolate,
3395                      seq_sub.ToUC16Vector(),
3396                      pat_vector,
3397                      start_index);
3398}
3399
3400
3401RUNTIME_FUNCTION(MaybeObject*, Runtime_StringIndexOf) {
3402  HandleScope scope(isolate);  // create a new handle scope
3403  ASSERT(args.length() == 3);
3404
3405  CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
3406  CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
3407
3408  Object* index = args[2];
3409  uint32_t start_index;
3410  if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
3411
3412  RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
3413  int position =
3414      Runtime::StringMatch(isolate, sub, pat, start_index);
3415  return Smi::FromInt(position);
3416}
3417
3418
3419template <typename schar, typename pchar>
3420static int StringMatchBackwards(Vector<const schar> subject,
3421                                Vector<const pchar> pattern,
3422                                int idx) {
3423  int pattern_length = pattern.length();
3424  ASSERT(pattern_length >= 1);
3425  ASSERT(idx + pattern_length <= subject.length());
3426
3427  if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
3428    for (int i = 0; i < pattern_length; i++) {
3429      uc16 c = pattern[i];
3430      if (c > String::kMaxAsciiCharCode) {
3431        return -1;
3432      }
3433    }
3434  }
3435
3436  pchar pattern_first_char = pattern[0];
3437  for (int i = idx; i >= 0; i--) {
3438    if (subject[i] != pattern_first_char) continue;
3439    int j = 1;
3440    while (j < pattern_length) {
3441      if (pattern[j] != subject[i+j]) {
3442        break;
3443      }
3444      j++;
3445    }
3446    if (j == pattern_length) {
3447      return i;
3448    }
3449  }
3450  return -1;
3451}
3452
3453RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
3454  HandleScope scope(isolate);  // create a new handle scope
3455  ASSERT(args.length() == 3);
3456
3457  CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
3458  CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
3459
3460  Object* index = args[2];
3461  uint32_t start_index;
3462  if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
3463
3464  uint32_t pat_length = pat->length();
3465  uint32_t sub_length = sub->length();
3466
3467  if (start_index + pat_length > sub_length) {
3468    start_index = sub_length - pat_length;
3469  }
3470
3471  if (pat_length == 0) {
3472    return Smi::FromInt(start_index);
3473  }
3474
3475  if (!sub->IsFlat()) FlattenString(sub);
3476  if (!pat->IsFlat()) FlattenString(pat);
3477
3478  int position = -1;
3479  AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
3480
3481  String::FlatContent sub_content = sub->GetFlatContent();
3482  String::FlatContent pat_content = pat->GetFlatContent();
3483
3484  if (pat_content.IsAscii()) {
3485    Vector<const char> pat_vector = pat_content.ToAsciiVector();
3486    if (sub_content.IsAscii()) {
3487      position = StringMatchBackwards(sub_content.ToAsciiVector(),
3488                                      pat_vector,
3489                                      start_index);
3490    } else {
3491      position = StringMatchBackwards(sub_content.ToUC16Vector(),
3492                                      pat_vector,
3493                                      start_index);
3494    }
3495  } else {
3496    Vector<const uc16> pat_vector = pat_content.ToUC16Vector();
3497    if (sub_content.IsAscii()) {
3498      position = StringMatchBackwards(sub_content.ToAsciiVector(),
3499                                      pat_vector,
3500                                      start_index);
3501    } else {
3502      position = StringMatchBackwards(sub_content.ToUC16Vector(),
3503                                      pat_vector,
3504                                      start_index);
3505    }
3506  }
3507
3508  return Smi::FromInt(position);
3509}
3510
3511
3512RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
3513  NoHandleAllocation ha;
3514  ASSERT(args.length() == 2);
3515
3516  CONVERT_ARG_CHECKED(String, str1, 0);
3517  CONVERT_ARG_CHECKED(String, str2, 1);
3518
3519  if (str1 == str2) return Smi::FromInt(0);  // Equal.
3520  int str1_length = str1->length();
3521  int str2_length = str2->length();
3522
3523  // Decide trivial cases without flattening.
3524  if (str1_length == 0) {
3525    if (str2_length == 0) return Smi::FromInt(0);  // Equal.
3526    return Smi::FromInt(-str2_length);
3527  } else {
3528    if (str2_length == 0) return Smi::FromInt(str1_length);
3529  }
3530
3531  int end = str1_length < str2_length ? str1_length : str2_length;
3532
3533  // No need to flatten if we are going to find the answer on the first
3534  // character.  At this point we know there is at least one character
3535  // in each string, due to the trivial case handling above.
3536  int d = str1->Get(0) - str2->Get(0);
3537  if (d != 0) return Smi::FromInt(d);
3538
3539  str1->TryFlatten();
3540  str2->TryFlatten();
3541
3542  StringInputBuffer& buf1 =
3543      *isolate->runtime_state()->string_locale_compare_buf1();
3544  StringInputBuffer& buf2 =
3545      *isolate->runtime_state()->string_locale_compare_buf2();
3546
3547  buf1.Reset(str1);
3548  buf2.Reset(str2);
3549
3550  for (int i = 0; i < end; i++) {
3551    uint16_t char1 = buf1.GetNext();
3552    uint16_t char2 = buf2.GetNext();
3553    if (char1 != char2) return Smi::FromInt(char1 - char2);
3554  }
3555
3556  return Smi::FromInt(str1_length - str2_length);
3557}
3558
3559
3560RUNTIME_FUNCTION(MaybeObject*, Runtime_SubString) {
3561  NoHandleAllocation ha;
3562  ASSERT(args.length() == 3);
3563
3564  CONVERT_ARG_CHECKED(String, value, 0);
3565  int start, end;
3566  // We have a fast integer-only case here to avoid a conversion to double in
3567  // the common case where from and to are Smis.
3568  if (args[1]->IsSmi() && args[2]->IsSmi()) {
3569    CONVERT_SMI_ARG_CHECKED(from_number, 1);
3570    CONVERT_SMI_ARG_CHECKED(to_number, 2);
3571    start = from_number;
3572    end = to_number;
3573  } else {
3574    CONVERT_DOUBLE_ARG_CHECKED(from_number, 1);
3575    CONVERT_DOUBLE_ARG_CHECKED(to_number, 2);
3576    start = FastD2I(from_number);
3577    end = FastD2I(to_number);
3578  }
3579  RUNTIME_ASSERT(end >= start);
3580  RUNTIME_ASSERT(start >= 0);
3581  RUNTIME_ASSERT(end <= value->length());
3582  isolate->counters()->sub_string_runtime()->Increment();
3583  return value->SubString(start, end);
3584}
3585
3586
3587RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) {
3588  ASSERT_EQ(3, args.length());
3589
3590  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
3591  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
3592  CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2);
3593  HandleScope handles;
3594
3595  Handle<Object> match = RegExpImpl::Exec(regexp, subject, 0, regexp_info);
3596
3597  if (match.is_null()) {
3598    return Failure::Exception();
3599  }
3600  if (match->IsNull()) {
3601    return isolate->heap()->null_value();
3602  }
3603  int length = subject->length();
3604
3605  ZoneScope zone_space(isolate, DELETE_ON_EXIT);
3606  ZoneList<int> offsets(8);
3607  int start;
3608  int end;
3609  do {
3610    {
3611      AssertNoAllocation no_alloc;
3612      FixedArray* elements = FixedArray::cast(regexp_info->elements());
3613      start = Smi::cast(elements->get(RegExpImpl::kFirstCapture))->value();
3614      end = Smi::cast(elements->get(RegExpImpl::kFirstCapture + 1))->value();
3615    }
3616    offsets.Add(start);
3617    offsets.Add(end);
3618    if (start == end) if (++end > length) break;
3619    match = RegExpImpl::Exec(regexp, subject, end, regexp_info);
3620    if (match.is_null()) {
3621      return Failure::Exception();
3622    }
3623  } while (!match->IsNull());
3624  int matches = offsets.length() / 2;
3625  Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches);
3626  Handle<String> substring = isolate->factory()->
3627    NewSubString(subject, offsets.at(0), offsets.at(1));
3628  elements->set(0, *substring);
3629  for (int i = 1; i < matches ; i++) {
3630    int from = offsets.at(i * 2);
3631    int to = offsets.at(i * 2 + 1);
3632    Handle<String> substring = isolate->factory()->
3633        NewProperSubString(subject, from, to);
3634    elements->set(i, *substring);
3635  }
3636  Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements);
3637  result->set_length(Smi::FromInt(matches));
3638  return *result;
3639}
3640
3641
3642// Two smis before and after the match, for very long strings.
3643const int kMaxBuilderEntriesPerRegExpMatch = 5;
3644
3645
3646static void SetLastMatchInfoNoCaptures(Handle<String> subject,
3647                                       Handle<JSArray> last_match_info,
3648                                       int match_start,
3649                                       int match_end) {
3650  // Fill last_match_info with a single capture.
3651  last_match_info->EnsureSize(2 + RegExpImpl::kLastMatchOverhead);
3652  AssertNoAllocation no_gc;
3653  FixedArray* elements = FixedArray::cast(last_match_info->elements());
3654  RegExpImpl::SetLastCaptureCount(elements, 2);
3655  RegExpImpl::SetLastInput(elements, *subject);
3656  RegExpImpl::SetLastSubject(elements, *subject);
3657  RegExpImpl::SetCapture(elements, 0, match_start);
3658  RegExpImpl::SetCapture(elements, 1, match_end);
3659}
3660
3661
3662template <typename SubjectChar, typename PatternChar>
3663static bool SearchStringMultiple(Isolate* isolate,
3664                                 Vector<const SubjectChar> subject,
3665                                 Vector<const PatternChar> pattern,
3666                                 String* pattern_string,
3667                                 FixedArrayBuilder* builder,
3668                                 int* match_pos) {
3669  int pos = *match_pos;
3670  int subject_length = subject.length();
3671  int pattern_length = pattern.length();
3672  int max_search_start = subject_length - pattern_length;
3673  StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
3674  while (pos <= max_search_start) {
3675    if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
3676      *match_pos = pos;
3677      return false;
3678    }
3679    // Position of end of previous match.
3680    int match_end = pos + pattern_length;
3681    int new_pos = search.Search(subject, match_end);
3682    if (new_pos >= 0) {
3683      // A match.
3684      if (new_pos > match_end) {
3685        ReplacementStringBuilder::AddSubjectSlice(builder,
3686            match_end,
3687            new_pos);
3688      }
3689      pos = new_pos;
3690      builder->Add(pattern_string);
3691    } else {
3692      break;
3693    }
3694  }
3695
3696  if (pos < max_search_start) {
3697    ReplacementStringBuilder::AddSubjectSlice(builder,
3698                                              pos + pattern_length,
3699                                              subject_length);
3700  }
3701  *match_pos = pos;
3702  return true;
3703}
3704
3705
3706static bool SearchStringMultiple(Isolate* isolate,
3707                                 Handle<String> subject,
3708                                 Handle<String> pattern,
3709                                 Handle<JSArray> last_match_info,
3710                                 FixedArrayBuilder* builder) {
3711  ASSERT(subject->IsFlat());
3712  ASSERT(pattern->IsFlat());
3713
3714  // Treating as if a previous match was before first character.
3715  int match_pos = -pattern->length();
3716
3717  for (;;) {  // Break when search complete.
3718    builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3719    AssertNoAllocation no_gc;
3720    String::FlatContent subject_content = subject->GetFlatContent();
3721    String::FlatContent pattern_content = pattern->GetFlatContent();
3722    if (subject_content.IsAscii()) {
3723      Vector<const char> subject_vector = subject_content.ToAsciiVector();
3724      if (pattern_content.IsAscii()) {
3725        if (SearchStringMultiple(isolate,
3726                                 subject_vector,
3727                                 pattern_content.ToAsciiVector(),
3728                                 *pattern,
3729                                 builder,
3730                                 &match_pos)) break;
3731      } else {
3732        if (SearchStringMultiple(isolate,
3733                                 subject_vector,
3734                                 pattern_content.ToUC16Vector(),
3735                                 *pattern,
3736                                 builder,
3737                                 &match_pos)) break;
3738      }
3739    } else {
3740      Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
3741      if (pattern_content.IsAscii()) {
3742        if (SearchStringMultiple(isolate,
3743                                 subject_vector,
3744                                 pattern_content.ToAsciiVector(),
3745                                 *pattern,
3746                                 builder,
3747                                 &match_pos)) break;
3748      } else {
3749        if (SearchStringMultiple(isolate,
3750                                 subject_vector,
3751                                 pattern_content.ToUC16Vector(),
3752                                 *pattern,
3753                                 builder,
3754                                 &match_pos)) break;
3755      }
3756    }
3757  }
3758
3759  if (match_pos >= 0) {
3760    SetLastMatchInfoNoCaptures(subject,
3761                               last_match_info,
3762                               match_pos,
3763                               match_pos + pattern->length());
3764    return true;
3765  }
3766  return false;  // No matches at all.
3767}
3768
3769
3770static RegExpImpl::IrregexpResult SearchRegExpNoCaptureMultiple(
3771    Isolate* isolate,
3772    Handle<String> subject,
3773    Handle<JSRegExp> regexp,
3774    Handle<JSArray> last_match_array,
3775    FixedArrayBuilder* builder) {
3776  ASSERT(subject->IsFlat());
3777  int match_start = -1;
3778  int match_end = 0;
3779  int pos = 0;
3780  int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject);
3781  if (required_registers < 0) return RegExpImpl::RE_EXCEPTION;
3782
3783  OffsetsVector registers(required_registers, isolate);
3784  Vector<int32_t> register_vector(registers.vector(), registers.length());
3785  int subject_length = subject->length();
3786  bool first = true;
3787
3788  for (;;) {  // Break on failure, return on exception.
3789    RegExpImpl::IrregexpResult result =
3790        RegExpImpl::IrregexpExecOnce(regexp,
3791                                     subject,
3792                                     pos,
3793                                     register_vector);
3794    if (result == RegExpImpl::RE_SUCCESS) {
3795      match_start = register_vector[0];
3796      builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3797      if (match_end < match_start) {
3798        ReplacementStringBuilder::AddSubjectSlice(builder,
3799                                                  match_end,
3800                                                  match_start);
3801      }
3802      match_end = register_vector[1];
3803      HandleScope loop_scope(isolate);
3804      if (!first) {
3805        builder->Add(*isolate->factory()->NewProperSubString(subject,
3806                                                             match_start,
3807                                                             match_end));
3808      } else {
3809        builder->Add(*isolate->factory()->NewSubString(subject,
3810                                                       match_start,
3811                                                       match_end));
3812      }
3813      if (match_start != match_end) {
3814        pos = match_end;
3815      } else {
3816        pos = match_end + 1;
3817        if (pos > subject_length) break;
3818      }
3819    } else if (result == RegExpImpl::RE_FAILURE) {
3820      break;
3821    } else {
3822      ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION);
3823      return result;
3824    }
3825    first = false;
3826  }
3827
3828  if (match_start >= 0) {
3829    if (match_end < subject_length) {
3830      ReplacementStringBuilder::AddSubjectSlice(builder,
3831                                                match_end,
3832                                                subject_length);
3833    }
3834    SetLastMatchInfoNoCaptures(subject,
3835                               last_match_array,
3836                               match_start,
3837                               match_end);
3838    return RegExpImpl::RE_SUCCESS;
3839  } else {
3840    return RegExpImpl::RE_FAILURE;  // No matches at all.
3841  }
3842}
3843
3844
3845static RegExpImpl::IrregexpResult SearchRegExpMultiple(
3846    Isolate* isolate,
3847    Handle<String> subject,
3848    Handle<JSRegExp> regexp,
3849    Handle<JSArray> last_match_array,
3850    FixedArrayBuilder* builder) {
3851
3852  ASSERT(subject->IsFlat());
3853  int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject);
3854  if (required_registers < 0) return RegExpImpl::RE_EXCEPTION;
3855
3856  OffsetsVector registers(required_registers, isolate);
3857  Vector<int32_t> register_vector(registers.vector(), registers.length());
3858
3859  RegExpImpl::IrregexpResult result =
3860      RegExpImpl::IrregexpExecOnce(regexp,
3861                                   subject,
3862                                   0,
3863                                   register_vector);
3864
3865  int capture_count = regexp->CaptureCount();
3866  int subject_length = subject->length();
3867
3868  // Position to search from.
3869  int pos = 0;
3870  // End of previous match. Differs from pos if match was empty.
3871  int match_end = 0;
3872  if (result == RegExpImpl::RE_SUCCESS) {
3873    // Need to keep a copy of the previous match for creating last_match_info
3874    // at the end, so we have two vectors that we swap between.
3875    OffsetsVector registers2(required_registers, isolate);
3876    Vector<int> prev_register_vector(registers2.vector(), registers2.length());
3877    bool first = true;
3878    do {
3879      int match_start = register_vector[0];
3880      builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3881      if (match_end < match_start) {
3882        ReplacementStringBuilder::AddSubjectSlice(builder,
3883                                                  match_end,
3884                                                  match_start);
3885      }
3886      match_end = register_vector[1];
3887
3888      {
3889        // Avoid accumulating new handles inside loop.
3890        HandleScope temp_scope(isolate);
3891        // Arguments array to replace function is match, captures, index and
3892        // subject, i.e., 3 + capture count in total.
3893        Handle<FixedArray> elements =
3894            isolate->factory()->NewFixedArray(3 + capture_count);
3895        Handle<String> match;
3896        if (!first) {
3897          match = isolate->factory()->NewProperSubString(subject,
3898                                                         match_start,
3899                                                         match_end);
3900        } else {
3901          match = isolate->factory()->NewSubString(subject,
3902                                                   match_start,
3903                                                   match_end);
3904        }
3905        elements->set(0, *match);
3906        for (int i = 1; i <= capture_count; i++) {
3907          int start = register_vector[i * 2];
3908          if (start >= 0) {
3909            int end = register_vector[i * 2 + 1];
3910            ASSERT(start <= end);
3911            Handle<String> substring;
3912            if (!first) {
3913              substring = isolate->factory()->NewProperSubString(subject,
3914                                                                 start,
3915                                                                 end);
3916            } else {
3917              substring = isolate->factory()->NewSubString(subject, start, end);
3918            }
3919            elements->set(i, *substring);
3920          } else {
3921            ASSERT(register_vector[i * 2 + 1] < 0);
3922            elements->set(i, isolate->heap()->undefined_value());
3923          }
3924        }
3925        elements->set(capture_count + 1, Smi::FromInt(match_start));
3926        elements->set(capture_count + 2, *subject);
3927        builder->Add(*isolate->factory()->NewJSArrayWithElements(elements));
3928      }
3929      // Swap register vectors, so the last successful match is in
3930      // prev_register_vector.
3931      Vector<int32_t> tmp = prev_register_vector;
3932      prev_register_vector = register_vector;
3933      register_vector = tmp;
3934
3935      if (match_end > match_start) {
3936        pos = match_end;
3937      } else {
3938        pos = match_end + 1;
3939        if (pos > subject_length) {
3940          break;
3941        }
3942      }
3943
3944      result = RegExpImpl::IrregexpExecOnce(regexp,
3945                                            subject,
3946                                            pos,
3947                                            register_vector);
3948      first = false;
3949    } while (result == RegExpImpl::RE_SUCCESS);
3950
3951    if (result != RegExpImpl::RE_EXCEPTION) {
3952      // Finished matching, with at least one match.
3953      if (match_end < subject_length) {
3954        ReplacementStringBuilder::AddSubjectSlice(builder,
3955                                                  match_end,
3956                                                  subject_length);
3957      }
3958
3959      int last_match_capture_count = (capture_count + 1) * 2;
3960      int last_match_array_size =
3961          last_match_capture_count + RegExpImpl::kLastMatchOverhead;
3962      last_match_array->EnsureSize(last_match_array_size);
3963      AssertNoAllocation no_gc;
3964      FixedArray* elements = FixedArray::cast(last_match_array->elements());
3965      RegExpImpl::SetLastCaptureCount(elements, last_match_capture_count);
3966      RegExpImpl::SetLastSubject(elements, *subject);
3967      RegExpImpl::SetLastInput(elements, *subject);
3968      for (int i = 0; i < last_match_capture_count; i++) {
3969        RegExpImpl::SetCapture(elements, i, prev_register_vector[i]);
3970      }
3971      return RegExpImpl::RE_SUCCESS;
3972    }
3973  }
3974  // No matches at all, return failure or exception result directly.
3975  return result;
3976}
3977
3978
3979RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) {
3980  ASSERT(args.length() == 4);
3981  HandleScope handles(isolate);
3982
3983  CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
3984  if (!subject->IsFlat()) FlattenString(subject);
3985  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
3986  CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2);
3987  CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3);
3988
3989  ASSERT(last_match_info->HasFastElements());
3990  ASSERT(regexp->GetFlags().is_global());
3991  Handle<FixedArray> result_elements;
3992  if (result_array->HasFastElements()) {
3993    result_elements =
3994        Handle<FixedArray>(FixedArray::cast(result_array->elements()));
3995  }
3996  if (result_elements.is_null() || result_elements->length() < 16) {
3997    result_elements = isolate->factory()->NewFixedArrayWithHoles(16);
3998  }
3999  FixedArrayBuilder builder(result_elements);
4000
4001  if (regexp->TypeTag() == JSRegExp::ATOM) {
4002    Handle<String> pattern(
4003        String::cast(regexp->DataAt(JSRegExp::kAtomPatternIndex)));
4004    ASSERT(pattern->IsFlat());
4005    if (SearchStringMultiple(isolate, subject, pattern,
4006                             last_match_info, &builder)) {
4007      return *builder.ToJSArray(result_array);
4008    }
4009    return isolate->heap()->null_value();
4010  }
4011
4012  ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP);
4013
4014  RegExpImpl::IrregexpResult result;
4015  if (regexp->CaptureCount() == 0) {
4016    result = SearchRegExpNoCaptureMultiple(isolate,
4017                                           subject,
4018                                           regexp,
4019                                           last_match_info,
4020                                           &builder);
4021  } else {
4022    result = SearchRegExpMultiple(isolate,
4023                                  subject,
4024                                  regexp,
4025                                  last_match_info,
4026                                  &builder);
4027  }
4028  if (result == RegExpImpl::RE_SUCCESS) return *builder.ToJSArray(result_array);
4029  if (result == RegExpImpl::RE_FAILURE) return isolate->heap()->null_value();
4030  ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION);
4031  return Failure::Exception();
4032}
4033
4034
4035RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) {
4036  NoHandleAllocation ha;
4037  ASSERT(args.length() == 2);
4038  CONVERT_SMI_ARG_CHECKED(radix, 1);
4039  RUNTIME_ASSERT(2 <= radix && radix <= 36);
4040
4041  // Fast case where the result is a one character string.
4042  if (args[0]->IsSmi()) {
4043    int value = args.smi_at(0);
4044    if (value >= 0 && value < radix) {
4045      // Character array used for conversion.
4046      static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
4047      return isolate->heap()->
4048          LookupSingleCharacterStringFromCode(kCharTable[value]);
4049    }
4050  }
4051
4052  // Slow case.
4053  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4054  if (isnan(value)) {
4055    return *isolate->factory()->nan_symbol();
4056  }
4057  if (isinf(value)) {
4058    if (value < 0) {
4059      return *isolate->factory()->minus_infinity_symbol();
4060    }
4061    return *isolate->factory()->infinity_symbol();
4062  }
4063  char* str = DoubleToRadixCString(value, radix);
4064  MaybeObject* result =
4065      isolate->heap()->AllocateStringFromAscii(CStrVector(str));
4066  DeleteArray(str);
4067  return result;
4068}
4069
4070
4071RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) {
4072  NoHandleAllocation ha;
4073  ASSERT(args.length() == 2);
4074
4075  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4076  if (isnan(value)) {
4077    return *isolate->factory()->nan_symbol();
4078  }
4079  if (isinf(value)) {
4080    if (value < 0) {
4081      return *isolate->factory()->minus_infinity_symbol();
4082    }
4083    return *isolate->factory()->infinity_symbol();
4084  }
4085  CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4086  int f = FastD2I(f_number);
4087  RUNTIME_ASSERT(f >= 0);
4088  char* str = DoubleToFixedCString(value, f);
4089  MaybeObject* res =
4090      isolate->heap()->AllocateStringFromAscii(CStrVector(str));
4091  DeleteArray(str);
4092  return res;
4093}
4094
4095
4096RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) {
4097  NoHandleAllocation ha;
4098  ASSERT(args.length() == 2);
4099
4100  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4101  if (isnan(value)) {
4102    return *isolate->factory()->nan_symbol();
4103  }
4104  if (isinf(value)) {
4105    if (value < 0) {
4106      return *isolate->factory()->minus_infinity_symbol();
4107    }
4108    return *isolate->factory()->infinity_symbol();
4109  }
4110  CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4111  int f = FastD2I(f_number);
4112  RUNTIME_ASSERT(f >= -1 && f <= 20);
4113  char* str = DoubleToExponentialCString(value, f);
4114  MaybeObject* res =
4115      isolate->heap()->AllocateStringFromAscii(CStrVector(str));
4116  DeleteArray(str);
4117  return res;
4118}
4119
4120
4121RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) {
4122  NoHandleAllocation ha;
4123  ASSERT(args.length() == 2);
4124
4125  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4126  if (isnan(value)) {
4127    return *isolate->factory()->nan_symbol();
4128  }
4129  if (isinf(value)) {
4130    if (value < 0) {
4131      return *isolate->factory()->minus_infinity_symbol();
4132    }
4133    return *isolate->factory()->infinity_symbol();
4134  }
4135  CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4136  int f = FastD2I(f_number);
4137  RUNTIME_ASSERT(f >= 1 && f <= 21);
4138  char* str = DoubleToPrecisionCString(value, f);
4139  MaybeObject* res =
4140      isolate->heap()->AllocateStringFromAscii(CStrVector(str));
4141  DeleteArray(str);
4142  return res;
4143}
4144
4145
4146// Returns a single character string where first character equals
4147// string->Get(index).
4148static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
4149  if (index < static_cast<uint32_t>(string->length())) {
4150    string->TryFlatten();
4151    return LookupSingleCharacterStringFromCode(
4152        string->Get(index));
4153  }
4154  return Execution::CharAt(string, index);
4155}
4156
4157
4158MaybeObject* Runtime::GetElementOrCharAt(Isolate* isolate,
4159                                         Handle<Object> object,
4160                                         uint32_t index) {
4161  // Handle [] indexing on Strings
4162  if (object->IsString()) {
4163    Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
4164    if (!result->IsUndefined()) return *result;
4165  }
4166
4167  // Handle [] indexing on String objects
4168  if (object->IsStringObjectWithCharacterAt(index)) {
4169    Handle<JSValue> js_value = Handle<JSValue>::cast(object);
4170    Handle<Object> result =
4171        GetCharAt(Handle<String>(String::cast(js_value->value())), index);
4172    if (!result->IsUndefined()) return *result;
4173  }
4174
4175  if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
4176    return object->GetPrototype()->GetElement(index);
4177  }
4178
4179  return object->GetElement(index);
4180}
4181
4182
4183MaybeObject* Runtime::GetObjectProperty(Isolate* isolate,
4184                                        Handle<Object> object,
4185                                        Handle<Object> key) {
4186  HandleScope scope(isolate);
4187
4188  if (object->IsUndefined() || object->IsNull()) {
4189    Handle<Object> args[2] = { key, object };
4190    Handle<Object> error =
4191        isolate->factory()->NewTypeError("non_object_property_load",
4192                                         HandleVector(args, 2));
4193    return isolate->Throw(*error);
4194  }
4195
4196  // Check if the given key is an array index.
4197  uint32_t index;
4198  if (key->ToArrayIndex(&index)) {
4199    return GetElementOrCharAt(isolate, object, index);
4200  }
4201
4202  // Convert the key to a string - possibly by calling back into JavaScript.
4203  Handle<String> name;
4204  if (key->IsString()) {
4205    name = Handle<String>::cast(key);
4206  } else {
4207    bool has_pending_exception = false;
4208    Handle<Object> converted =
4209        Execution::ToString(key, &has_pending_exception);
4210    if (has_pending_exception) return Failure::Exception();
4211    name = Handle<String>::cast(converted);
4212  }
4213
4214  // Check if the name is trivially convertible to an index and get
4215  // the element if so.
4216  if (name->AsArrayIndex(&index)) {
4217    return GetElementOrCharAt(isolate, object, index);
4218  } else {
4219    return object->GetProperty(*name);
4220  }
4221}
4222
4223
4224RUNTIME_FUNCTION(MaybeObject*, Runtime_GetProperty) {
4225  NoHandleAllocation ha;
4226  ASSERT(args.length() == 2);
4227
4228  Handle<Object> object = args.at<Object>(0);
4229  Handle<Object> key = args.at<Object>(1);
4230
4231  return Runtime::GetObjectProperty(isolate, object, key);
4232}
4233
4234
4235// KeyedStringGetProperty is called from KeyedLoadIC::GenerateGeneric.
4236RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
4237  NoHandleAllocation ha;
4238  ASSERT(args.length() == 2);
4239
4240  // Fast cases for getting named properties of the receiver JSObject
4241  // itself.
4242  //
4243  // The global proxy objects has to be excluded since LocalLookup on
4244  // the global proxy object can return a valid result even though the
4245  // global proxy object never has properties.  This is the case
4246  // because the global proxy object forwards everything to its hidden
4247  // prototype including local lookups.
4248  //
4249  // Additionally, we need to make sure that we do not cache results
4250  // for objects that require access checks.
4251  if (args[0]->IsJSObject()) {
4252    if (!args[0]->IsJSGlobalProxy() &&
4253        !args[0]->IsAccessCheckNeeded() &&
4254        args[1]->IsString()) {
4255      JSObject* receiver = JSObject::cast(args[0]);
4256      String* key = String::cast(args[1]);
4257      if (receiver->HasFastProperties()) {
4258        // Attempt to use lookup cache.
4259        Map* receiver_map = receiver->map();
4260        KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache();
4261        int offset = keyed_lookup_cache->Lookup(receiver_map, key);
4262        if (offset != -1) {
4263          Object* value = receiver->FastPropertyAt(offset);
4264          return value->IsTheHole()
4265              ? isolate->heap()->undefined_value()
4266              : value;
4267        }
4268        // Lookup cache miss.  Perform lookup and update the cache if
4269        // appropriate.
4270        LookupResult result(isolate);
4271        receiver->LocalLookup(key, &result);
4272        if (result.IsFound() && result.type() == FIELD) {
4273          int offset = result.GetFieldIndex();
4274          keyed_lookup_cache->Update(receiver_map, key, offset);
4275          return receiver->FastPropertyAt(offset);
4276        }
4277      } else {
4278        // Attempt dictionary lookup.
4279        StringDictionary* dictionary = receiver->property_dictionary();
4280        int entry = dictionary->FindEntry(key);
4281        if ((entry != StringDictionary::kNotFound) &&
4282            (dictionary->DetailsAt(entry).type() == NORMAL)) {
4283          Object* value = dictionary->ValueAt(entry);
4284          if (!receiver->IsGlobalObject()) return value;
4285          value = JSGlobalPropertyCell::cast(value)->value();
4286          if (!value->IsTheHole()) return value;
4287          // If value is the hole do the general lookup.
4288        }
4289      }
4290    } else if (FLAG_smi_only_arrays && args.at<Object>(1)->IsSmi()) {
4291      // JSObject without a string key. If the key is a Smi, check for a
4292      // definite out-of-bounds access to elements, which is a strong indicator
4293      // that subsequent accesses will also call the runtime. Proactively
4294      // transition elements to FAST_ELEMENTS to avoid excessive boxing of
4295      // doubles for those future calls in the case that the elements would
4296      // become FAST_DOUBLE_ELEMENTS.
4297      Handle<JSObject> js_object(args.at<JSObject>(0));
4298      ElementsKind elements_kind = js_object->GetElementsKind();
4299      if (elements_kind == FAST_SMI_ONLY_ELEMENTS ||
4300          elements_kind == FAST_DOUBLE_ELEMENTS) {
4301        FixedArrayBase* elements = js_object->elements();
4302        if (args.at<Smi>(1)->value() >= elements->length()) {
4303          MaybeObject* maybe_object = TransitionElements(js_object,
4304                                                         FAST_ELEMENTS,
4305                                                         isolate);
4306          if (maybe_object->IsFailure()) return maybe_object;
4307        }
4308      }
4309    }
4310  } else if (args[0]->IsString() && args[1]->IsSmi()) {
4311    // Fast case for string indexing using [] with a smi index.
4312    HandleScope scope(isolate);
4313    Handle<String> str = args.at<String>(0);
4314    int index = args.smi_at(1);
4315    if (index >= 0 && index < str->length()) {
4316      Handle<Object> result = GetCharAt(str, index);
4317      return *result;
4318    }
4319  }
4320
4321  // Fall back to GetObjectProperty.
4322  return Runtime::GetObjectProperty(isolate,
4323                                    args.at<Object>(0),
4324                                    args.at<Object>(1));
4325}
4326
4327
4328static bool IsValidAccessor(Handle<Object> obj) {
4329  return obj->IsUndefined() || obj->IsSpecFunction() || obj->IsNull();
4330}
4331
4332
4333// Implements part of 8.12.9 DefineOwnProperty.
4334// There are 3 cases that lead here:
4335// Step 4b - define a new accessor property.
4336// Steps 9c & 12 - replace an existing data property with an accessor property.
4337// Step 12 - update an existing accessor property with an accessor or generic
4338//           descriptor.
4339RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) {
4340  ASSERT(args.length() == 5);
4341  HandleScope scope(isolate);
4342  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
4343  RUNTIME_ASSERT(!obj->IsNull());
4344  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
4345  CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
4346  RUNTIME_ASSERT(IsValidAccessor(getter));
4347  CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
4348  RUNTIME_ASSERT(IsValidAccessor(setter));
4349  CONVERT_SMI_ARG_CHECKED(unchecked, 4);
4350  RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4351  PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
4352
4353  bool fast = obj->HasFastProperties();
4354  JSObject::DefineAccessor(obj, name, getter, setter, attr);
4355  if (fast) JSObject::TransformToFastProperties(obj, 0);
4356  return isolate->heap()->undefined_value();
4357}
4358
4359// Implements part of 8.12.9 DefineOwnProperty.
4360// There are 3 cases that lead here:
4361// Step 4a - define a new data property.
4362// Steps 9b & 12 - replace an existing accessor property with a data property.
4363// Step 12 - update an existing data property with a data or generic
4364//           descriptor.
4365RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
4366  ASSERT(args.length() == 4);
4367  HandleScope scope(isolate);
4368  CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
4369  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
4370  CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2);
4371  CONVERT_SMI_ARG_CHECKED(unchecked, 3);
4372  RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4373  PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
4374
4375  LookupResult result(isolate);
4376  js_object->LocalLookupRealNamedProperty(*name, &result);
4377
4378  // Special case for callback properties.
4379  if (result.IsFound() && result.type() == CALLBACKS) {
4380    Object* callback = result.GetCallbackObject();
4381    // To be compatible with Safari we do not change the value on API objects
4382    // in Object.defineProperty(). Firefox disagrees here, and actually changes
4383    // the value.
4384    if (callback->IsAccessorInfo()) {
4385      return isolate->heap()->undefined_value();
4386    }
4387    // Avoid redefining foreign callback as data property, just use the stored
4388    // setter to update the value instead.
4389    // TODO(mstarzinger): So far this only works if property attributes don't
4390    // change, this should be fixed once we cleanup the underlying code.
4391    if (callback->IsForeign() && result.GetAttributes() == attr) {
4392      return js_object->SetPropertyWithCallback(callback,
4393                                                *name,
4394                                                *obj_value,
4395                                                result.holder(),
4396                                                kStrictMode);
4397    }
4398  }
4399
4400  // Take special care when attributes are different and there is already
4401  // a property. For simplicity we normalize the property which enables us
4402  // to not worry about changing the instance_descriptor and creating a new
4403  // map. The current version of SetObjectProperty does not handle attributes
4404  // correctly in the case where a property is a field and is reset with
4405  // new attributes.
4406  if (result.IsProperty() &&
4407      (attr != result.GetAttributes() || result.type() == CALLBACKS)) {
4408    // New attributes - normalize to avoid writing to instance descriptor
4409    if (js_object->IsJSGlobalProxy()) {
4410      // Since the result is a property, the prototype will exist so
4411      // we don't have to check for null.
4412      js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype()));
4413    }
4414    JSObject::NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
4415    // Use IgnoreAttributes version since a readonly property may be
4416    // overridden and SetProperty does not allow this.
4417    return js_object->SetLocalPropertyIgnoreAttributes(*name,
4418                                                       *obj_value,
4419                                                       attr);
4420  }
4421
4422  return Runtime::ForceSetObjectProperty(isolate,
4423                                         js_object,
4424                                         name,
4425                                         obj_value,
4426                                         attr);
4427}
4428
4429
4430MaybeObject* Runtime::SetObjectProperty(Isolate* isolate,
4431                                        Handle<Object> object,
4432                                        Handle<Object> key,
4433                                        Handle<Object> value,
4434                                        PropertyAttributes attr,
4435                                        StrictModeFlag strict_mode) {
4436  SetPropertyMode set_mode = attr == NONE ? SET_PROPERTY : DEFINE_PROPERTY;
4437  HandleScope scope(isolate);
4438
4439  if (object->IsUndefined() || object->IsNull()) {
4440    Handle<Object> args[2] = { key, object };
4441    Handle<Object> error =
4442        isolate->factory()->NewTypeError("non_object_property_store",
4443                                         HandleVector(args, 2));
4444    return isolate->Throw(*error);
4445  }
4446
4447  if (object->IsJSProxy()) {
4448    bool has_pending_exception = false;
4449    Handle<Object> name = Execution::ToString(key, &has_pending_exception);
4450    if (has_pending_exception) return Failure::Exception();
4451    return JSProxy::cast(*object)->SetProperty(
4452        String::cast(*name), *value, attr, strict_mode);
4453  }
4454
4455  // If the object isn't a JavaScript object, we ignore the store.
4456  if (!object->IsJSObject()) return *value;
4457
4458  Handle<JSObject> js_object = Handle<JSObject>::cast(object);
4459
4460  // Check if the given key is an array index.
4461  uint32_t index;
4462  if (key->ToArrayIndex(&index)) {
4463    // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
4464    // of a string using [] notation.  We need to support this too in
4465    // JavaScript.
4466    // In the case of a String object we just need to redirect the assignment to
4467    // the underlying string if the index is in range.  Since the underlying
4468    // string does nothing with the assignment then we can ignore such
4469    // assignments.
4470    if (js_object->IsStringObjectWithCharacterAt(index)) {
4471      return *value;
4472    }
4473
4474    Handle<Object> result = JSObject::SetElement(
4475        js_object, index, value, attr, strict_mode, set_mode);
4476    if (result.is_null()) return Failure::Exception();
4477    return *value;
4478  }
4479
4480  if (key->IsString()) {
4481    Handle<Object> result;
4482    if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
4483      result = JSObject::SetElement(
4484          js_object, index, value, attr, strict_mode, set_mode);
4485    } else {
4486      Handle<String> key_string = Handle<String>::cast(key);
4487      key_string->TryFlatten();
4488      result = JSReceiver::SetProperty(
4489          js_object, key_string, value, attr, strict_mode);
4490    }
4491    if (result.is_null()) return Failure::Exception();
4492    return *value;
4493  }
4494
4495  // Call-back into JavaScript to convert the key to a string.
4496  bool has_pending_exception = false;
4497  Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
4498  if (has_pending_exception) return Failure::Exception();
4499  Handle<String> name = Handle<String>::cast(converted);
4500
4501  if (name->AsArrayIndex(&index)) {
4502    return js_object->SetElement(
4503        index, *value, attr, strict_mode, true, set_mode);
4504  } else {
4505    return js_object->SetProperty(*name, *value, attr, strict_mode);
4506  }
4507}
4508
4509
4510MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate,
4511                                             Handle<JSObject> js_object,
4512                                             Handle<Object> key,
4513                                             Handle<Object> value,
4514                                             PropertyAttributes attr) {
4515  HandleScope scope(isolate);
4516
4517  // Check if the given key is an array index.
4518  uint32_t index;
4519  if (key->ToArrayIndex(&index)) {
4520    // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
4521    // of a string using [] notation.  We need to support this too in
4522    // JavaScript.
4523    // In the case of a String object we just need to redirect the assignment to
4524    // the underlying string if the index is in range.  Since the underlying
4525    // string does nothing with the assignment then we can ignore such
4526    // assignments.
4527    if (js_object->IsStringObjectWithCharacterAt(index)) {
4528      return *value;
4529    }
4530
4531    return js_object->SetElement(
4532        index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
4533  }
4534
4535  if (key->IsString()) {
4536    if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
4537      return js_object->SetElement(
4538          index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
4539    } else {
4540      Handle<String> key_string = Handle<String>::cast(key);
4541      key_string->TryFlatten();
4542      return js_object->SetLocalPropertyIgnoreAttributes(*key_string,
4543                                                         *value,
4544                                                         attr);
4545    }
4546  }
4547
4548  // Call-back into JavaScript to convert the key to a string.
4549  bool has_pending_exception = false;
4550  Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
4551  if (has_pending_exception) return Failure::Exception();
4552  Handle<String> name = Handle<String>::cast(converted);
4553
4554  if (name->AsArrayIndex(&index)) {
4555    return js_object->SetElement(
4556        index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
4557  } else {
4558    return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr);
4559  }
4560}
4561
4562
4563MaybeObject* Runtime::ForceDeleteObjectProperty(Isolate* isolate,
4564                                                Handle<JSReceiver> receiver,
4565                                                Handle<Object> key) {
4566  HandleScope scope(isolate);
4567
4568  // Check if the given key is an array index.
4569  uint32_t index;
4570  if (key->ToArrayIndex(&index)) {
4571    // In Firefox/SpiderMonkey, Safari and Opera you can access the
4572    // characters of a string using [] notation.  In the case of a
4573    // String object we just need to redirect the deletion to the
4574    // underlying string if the index is in range.  Since the
4575    // underlying string does nothing with the deletion, we can ignore
4576    // such deletions.
4577    if (receiver->IsStringObjectWithCharacterAt(index)) {
4578      return isolate->heap()->true_value();
4579    }
4580
4581    return receiver->DeleteElement(index, JSReceiver::FORCE_DELETION);
4582  }
4583
4584  Handle<String> key_string;
4585  if (key->IsString()) {
4586    key_string = Handle<String>::cast(key);
4587  } else {
4588    // Call-back into JavaScript to convert the key to a string.
4589    bool has_pending_exception = false;
4590    Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
4591    if (has_pending_exception) return Failure::Exception();
4592    key_string = Handle<String>::cast(converted);
4593  }
4594
4595  key_string->TryFlatten();
4596  return receiver->DeleteProperty(*key_string, JSReceiver::FORCE_DELETION);
4597}
4598
4599
4600RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) {
4601  NoHandleAllocation ha;
4602  RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
4603
4604  Handle<Object> object = args.at<Object>(0);
4605  Handle<Object> key = args.at<Object>(1);
4606  Handle<Object> value = args.at<Object>(2);
4607  CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3);
4608  RUNTIME_ASSERT(
4609      (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4610  // Compute attributes.
4611  PropertyAttributes attributes =
4612      static_cast<PropertyAttributes>(unchecked_attributes);
4613
4614  StrictModeFlag strict_mode = kNonStrictMode;
4615  if (args.length() == 5) {
4616    CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode_flag, 4);
4617    strict_mode = strict_mode_flag;
4618  }
4619
4620  return Runtime::SetObjectProperty(isolate,
4621                                    object,
4622                                    key,
4623                                    value,
4624                                    attributes,
4625                                    strict_mode);
4626}
4627
4628
4629RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsSmiToDouble) {
4630  NoHandleAllocation ha;
4631  RUNTIME_ASSERT(args.length() == 1);
4632  Handle<Object> object = args.at<Object>(0);
4633  return TransitionElements(object, FAST_DOUBLE_ELEMENTS, isolate);
4634}
4635
4636
4637RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsDoubleToObject) {
4638  NoHandleAllocation ha;
4639  RUNTIME_ASSERT(args.length() == 1);
4640  Handle<Object> object = args.at<Object>(0);
4641  return TransitionElements(object, FAST_ELEMENTS, isolate);
4642}
4643
4644
4645// Set the native flag on the function.
4646// This is used to decide if we should transform null and undefined
4647// into the global object when doing call and apply.
4648RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) {
4649  NoHandleAllocation ha;
4650  RUNTIME_ASSERT(args.length() == 1);
4651
4652  Handle<Object> object = args.at<Object>(0);
4653
4654  if (object->IsJSFunction()) {
4655    JSFunction* func = JSFunction::cast(*object);
4656    func->shared()->set_native(true);
4657  }
4658  return isolate->heap()->undefined_value();
4659}
4660
4661
4662RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) {
4663  RUNTIME_ASSERT(args.length() == 5);
4664  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
4665  CONVERT_SMI_ARG_CHECKED(store_index, 1);
4666  Handle<Object> value = args.at<Object>(2);
4667  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 3);
4668  CONVERT_SMI_ARG_CHECKED(literal_index, 4);
4669  HandleScope scope;
4670
4671  Object* raw_boilerplate_object = literals->get(literal_index);
4672  Handle<JSArray> boilerplate_object(JSArray::cast(raw_boilerplate_object));
4673#if DEBUG
4674  ElementsKind elements_kind = object->GetElementsKind();
4675#endif
4676  ASSERT(elements_kind <= FAST_DOUBLE_ELEMENTS);
4677  // Smis should never trigger transitions.
4678  ASSERT(!value->IsSmi());
4679
4680  if (value->IsNumber()) {
4681    ASSERT(elements_kind == FAST_SMI_ONLY_ELEMENTS);
4682    JSObject::TransitionElementsKind(object, FAST_DOUBLE_ELEMENTS);
4683    JSObject::TransitionElementsKind(boilerplate_object, FAST_DOUBLE_ELEMENTS);
4684    ASSERT(object->GetElementsKind() == FAST_DOUBLE_ELEMENTS);
4685    FixedDoubleArray* double_array =
4686        FixedDoubleArray::cast(object->elements());
4687    HeapNumber* number = HeapNumber::cast(*value);
4688    double_array->set(store_index, number->Number());
4689  } else {
4690    ASSERT(elements_kind == FAST_SMI_ONLY_ELEMENTS ||
4691           elements_kind == FAST_DOUBLE_ELEMENTS);
4692    JSObject::TransitionElementsKind(object, FAST_ELEMENTS);
4693    JSObject::TransitionElementsKind(boilerplate_object, FAST_ELEMENTS);
4694    FixedArray* object_array =
4695        FixedArray::cast(object->elements());
4696    object_array->set(store_index, *value);
4697  }
4698  return *object;
4699}
4700
4701
4702// Set a local property, even if it is READ_ONLY.  If the property does not
4703// exist, it will be added with attributes NONE.
4704RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) {
4705  NoHandleAllocation ha;
4706  RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
4707  CONVERT_ARG_CHECKED(JSObject, object, 0);
4708  CONVERT_ARG_CHECKED(String, name, 1);
4709  // Compute attributes.
4710  PropertyAttributes attributes = NONE;
4711  if (args.length() == 4) {
4712    CONVERT_SMI_ARG_CHECKED(unchecked_value, 3);
4713    // Only attribute bits should be set.
4714    RUNTIME_ASSERT(
4715        (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4716    attributes = static_cast<PropertyAttributes>(unchecked_value);
4717  }
4718
4719  return object->
4720      SetLocalPropertyIgnoreAttributes(name, args[2], attributes);
4721}
4722
4723
4724RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteProperty) {
4725  NoHandleAllocation ha;
4726  ASSERT(args.length() == 3);
4727
4728  CONVERT_ARG_CHECKED(JSReceiver, object, 0);
4729  CONVERT_ARG_CHECKED(String, key, 1);
4730  CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2);
4731  return object->DeleteProperty(key, (strict_mode == kStrictMode)
4732                                      ? JSReceiver::STRICT_DELETION
4733                                      : JSReceiver::NORMAL_DELETION);
4734}
4735
4736
4737static Object* HasLocalPropertyImplementation(Isolate* isolate,
4738                                              Handle<JSObject> object,
4739                                              Handle<String> key) {
4740  if (object->HasLocalProperty(*key)) return isolate->heap()->true_value();
4741  // Handle hidden prototypes.  If there's a hidden prototype above this thing
4742  // then we have to check it for properties, because they are supposed to
4743  // look like they are on this object.
4744  Handle<Object> proto(object->GetPrototype());
4745  if (proto->IsJSObject() &&
4746      Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) {
4747    return HasLocalPropertyImplementation(isolate,
4748                                          Handle<JSObject>::cast(proto),
4749                                          key);
4750  }
4751  return isolate->heap()->false_value();
4752}
4753
4754
4755RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) {
4756  NoHandleAllocation ha;
4757  ASSERT(args.length() == 2);
4758  CONVERT_ARG_CHECKED(String, key, 1);
4759
4760  uint32_t index;
4761  const bool key_is_array_index = key->AsArrayIndex(&index);
4762
4763  Object* obj = args[0];
4764  // Only JS objects can have properties.
4765  if (obj->IsJSObject()) {
4766    JSObject* object = JSObject::cast(obj);
4767    // Fast case: either the key is a real named property or it is not
4768    // an array index and there are no interceptors or hidden
4769    // prototypes.
4770    if (object->HasRealNamedProperty(key)) return isolate->heap()->true_value();
4771    Map* map = object->map();
4772    if (!key_is_array_index &&
4773        !map->has_named_interceptor() &&
4774        !HeapObject::cast(map->prototype())->map()->is_hidden_prototype()) {
4775      return isolate->heap()->false_value();
4776    }
4777    // Slow case.
4778    HandleScope scope(isolate);
4779    return HasLocalPropertyImplementation(isolate,
4780                                          Handle<JSObject>(object),
4781                                          Handle<String>(key));
4782  } else if (obj->IsString() && key_is_array_index) {
4783    // Well, there is one exception:  Handle [] on strings.
4784    String* string = String::cast(obj);
4785    if (index < static_cast<uint32_t>(string->length())) {
4786      return isolate->heap()->true_value();
4787    }
4788  }
4789  return isolate->heap()->false_value();
4790}
4791
4792
4793RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) {
4794  NoHandleAllocation na;
4795  ASSERT(args.length() == 2);
4796  CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
4797  CONVERT_ARG_CHECKED(String, key, 1);
4798
4799  bool result = receiver->HasProperty(key);
4800  if (isolate->has_pending_exception()) return Failure::Exception();
4801  return isolate->heap()->ToBoolean(result);
4802}
4803
4804
4805RUNTIME_FUNCTION(MaybeObject*, Runtime_HasElement) {
4806  NoHandleAllocation na;
4807  ASSERT(args.length() == 2);
4808  CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
4809  CONVERT_SMI_ARG_CHECKED(index, 1);
4810
4811  bool result = receiver->HasElement(index);
4812  if (isolate->has_pending_exception()) return Failure::Exception();
4813  return isolate->heap()->ToBoolean(result);
4814}
4815
4816
4817RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) {
4818  NoHandleAllocation ha;
4819  ASSERT(args.length() == 2);
4820
4821  CONVERT_ARG_CHECKED(JSObject, object, 0);
4822  CONVERT_ARG_CHECKED(String, key, 1);
4823
4824  uint32_t index;
4825  if (key->AsArrayIndex(&index)) {
4826    JSObject::LocalElementType type = object->HasLocalElement(index);
4827    switch (type) {
4828      case JSObject::UNDEFINED_ELEMENT:
4829      case JSObject::STRING_CHARACTER_ELEMENT:
4830        return isolate->heap()->false_value();
4831      case JSObject::INTERCEPTED_ELEMENT:
4832      case JSObject::FAST_ELEMENT:
4833        return isolate->heap()->true_value();
4834      case JSObject::DICTIONARY_ELEMENT: {
4835        if (object->IsJSGlobalProxy()) {
4836          Object* proto = object->GetPrototype();
4837          if (proto->IsNull()) {
4838            return isolate->heap()->false_value();
4839          }
4840          ASSERT(proto->IsJSGlobalObject());
4841          object = JSObject::cast(proto);
4842        }
4843        FixedArray* elements = FixedArray::cast(object->elements());
4844        SeededNumberDictionary* dictionary = NULL;
4845        if (elements->map() ==
4846            isolate->heap()->non_strict_arguments_elements_map()) {
4847          dictionary = SeededNumberDictionary::cast(elements->get(1));
4848        } else {
4849          dictionary = SeededNumberDictionary::cast(elements);
4850        }
4851        int entry = dictionary->FindEntry(index);
4852        ASSERT(entry != SeededNumberDictionary::kNotFound);
4853        PropertyDetails details = dictionary->DetailsAt(entry);
4854        return isolate->heap()->ToBoolean(!details.IsDontEnum());
4855      }
4856    }
4857  }
4858
4859  PropertyAttributes att = object->GetLocalPropertyAttribute(key);
4860  return isolate->heap()->ToBoolean(att != ABSENT && (att & DONT_ENUM) == 0);
4861}
4862
4863
4864RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNames) {
4865  HandleScope scope(isolate);
4866  ASSERT(args.length() == 1);
4867  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
4868  bool threw = false;
4869  Handle<JSArray> result = GetKeysFor(object, &threw);
4870  if (threw) return Failure::Exception();
4871  return *result;
4872}
4873
4874
4875// Returns either a FixedArray as Runtime_GetPropertyNames,
4876// or, if the given object has an enum cache that contains
4877// all enumerable properties of the object and its prototypes
4878// have none, the map of the object. This is used to speed up
4879// the check for deletions during a for-in.
4880RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNamesFast) {
4881  ASSERT(args.length() == 1);
4882
4883  CONVERT_ARG_CHECKED(JSReceiver, raw_object, 0);
4884
4885  if (raw_object->IsSimpleEnum()) return raw_object->map();
4886
4887  HandleScope scope(isolate);
4888  Handle<JSReceiver> object(raw_object);
4889  bool threw = false;
4890  Handle<FixedArray> content =
4891      GetKeysInFixedArrayFor(object, INCLUDE_PROTOS, &threw);
4892  if (threw) return Failure::Exception();
4893
4894  // Test again, since cache may have been built by preceding call.
4895  if (object->IsSimpleEnum()) return object->map();
4896
4897  return *content;
4898}
4899
4900
4901// Find the length of the prototype chain that is to to handled as one. If a
4902// prototype object is hidden it is to be viewed as part of the the object it
4903// is prototype for.
4904static int LocalPrototypeChainLength(JSObject* obj) {
4905  int count = 1;
4906  Object* proto = obj->GetPrototype();
4907  while (proto->IsJSObject() &&
4908         JSObject::cast(proto)->map()->is_hidden_prototype()) {
4909    count++;
4910    proto = JSObject::cast(proto)->GetPrototype();
4911  }
4912  return count;
4913}
4914
4915
4916// Return the names of the local named properties.
4917// args[0]: object
4918RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) {
4919  HandleScope scope(isolate);
4920  ASSERT(args.length() == 1);
4921  if (!args[0]->IsJSObject()) {
4922    return isolate->heap()->undefined_value();
4923  }
4924  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
4925
4926  // Skip the global proxy as it has no properties and always delegates to the
4927  // real global object.
4928  if (obj->IsJSGlobalProxy()) {
4929    // Only collect names if access is permitted.
4930    if (obj->IsAccessCheckNeeded() &&
4931        !isolate->MayNamedAccess(*obj,
4932                                 isolate->heap()->undefined_value(),
4933                                 v8::ACCESS_KEYS)) {
4934      isolate->ReportFailedAccessCheck(*obj, v8::ACCESS_KEYS);
4935      return *isolate->factory()->NewJSArray(0);
4936    }
4937    obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
4938  }
4939
4940  // Find the number of objects making up this.
4941  int length = LocalPrototypeChainLength(*obj);
4942
4943  // Find the number of local properties for each of the objects.
4944  ScopedVector<int> local_property_count(length);
4945  int total_property_count = 0;
4946  Handle<JSObject> jsproto = obj;
4947  for (int i = 0; i < length; i++) {
4948    // Only collect names if access is permitted.
4949    if (jsproto->IsAccessCheckNeeded() &&
4950        !isolate->MayNamedAccess(*jsproto,
4951                                 isolate->heap()->undefined_value(),
4952                                 v8::ACCESS_KEYS)) {
4953      isolate->ReportFailedAccessCheck(*jsproto, v8::ACCESS_KEYS);
4954      return *isolate->factory()->NewJSArray(0);
4955    }
4956    int n;
4957    n = jsproto->NumberOfLocalProperties();
4958    local_property_count[i] = n;
4959    total_property_count += n;
4960    if (i < length - 1) {
4961      jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
4962    }
4963  }
4964
4965  // Allocate an array with storage for all the property names.
4966  Handle<FixedArray> names =
4967      isolate->factory()->NewFixedArray(total_property_count);
4968
4969  // Get the property names.
4970  jsproto = obj;
4971  int proto_with_hidden_properties = 0;
4972  int next_copy_index = 0;
4973  for (int i = 0; i < length; i++) {
4974    jsproto->GetLocalPropertyNames(*names, next_copy_index);
4975    next_copy_index += local_property_count[i];
4976    if (jsproto->HasHiddenProperties()) {
4977      proto_with_hidden_properties++;
4978    }
4979    if (i < length - 1) {
4980      jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
4981    }
4982  }
4983
4984  // Filter out name of hidden propeties object.
4985  if (proto_with_hidden_properties > 0) {
4986    Handle<FixedArray> old_names = names;
4987    names = isolate->factory()->NewFixedArray(
4988        names->length() - proto_with_hidden_properties);
4989    int dest_pos = 0;
4990    for (int i = 0; i < total_property_count; i++) {
4991      Object* name = old_names->get(i);
4992      if (name == isolate->heap()->hidden_symbol()) {
4993        continue;
4994      }
4995      names->set(dest_pos++, name);
4996    }
4997  }
4998
4999  return *isolate->factory()->NewJSArrayWithElements(names);
5000}
5001
5002
5003// Return the names of the local indexed properties.
5004// args[0]: object
5005RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalElementNames) {
5006  HandleScope scope(isolate);
5007  ASSERT(args.length() == 1);
5008  if (!args[0]->IsJSObject()) {
5009    return isolate->heap()->undefined_value();
5010  }
5011  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5012
5013  int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
5014  Handle<FixedArray> names = isolate->factory()->NewFixedArray(n);
5015  obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
5016  return *isolate->factory()->NewJSArrayWithElements(names);
5017}
5018
5019
5020// Return information on whether an object has a named or indexed interceptor.
5021// args[0]: object
5022RUNTIME_FUNCTION(MaybeObject*, Runtime_GetInterceptorInfo) {
5023  HandleScope scope(isolate);
5024  ASSERT(args.length() == 1);
5025  if (!args[0]->IsJSObject()) {
5026    return Smi::FromInt(0);
5027  }
5028  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5029
5030  int result = 0;
5031  if (obj->HasNamedInterceptor()) result |= 2;
5032  if (obj->HasIndexedInterceptor()) result |= 1;
5033
5034  return Smi::FromInt(result);
5035}
5036
5037
5038// Return property names from named interceptor.
5039// args[0]: object
5040RUNTIME_FUNCTION(MaybeObject*, Runtime_GetNamedInterceptorPropertyNames) {
5041  HandleScope scope(isolate);
5042  ASSERT(args.length() == 1);
5043  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5044
5045  if (obj->HasNamedInterceptor()) {
5046    v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
5047    if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
5048  }
5049  return isolate->heap()->undefined_value();
5050}
5051
5052
5053// Return element names from indexed interceptor.
5054// args[0]: object
5055RUNTIME_FUNCTION(MaybeObject*, Runtime_GetIndexedInterceptorElementNames) {
5056  HandleScope scope(isolate);
5057  ASSERT(args.length() == 1);
5058  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5059
5060  if (obj->HasIndexedInterceptor()) {
5061    v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
5062    if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
5063  }
5064  return isolate->heap()->undefined_value();
5065}
5066
5067
5068RUNTIME_FUNCTION(MaybeObject*, Runtime_LocalKeys) {
5069  ASSERT_EQ(args.length(), 1);
5070  CONVERT_ARG_CHECKED(JSObject, raw_object, 0);
5071  HandleScope scope(isolate);
5072  Handle<JSObject> object(raw_object);
5073
5074  if (object->IsJSGlobalProxy()) {
5075    // Do access checks before going to the global object.
5076    if (object->IsAccessCheckNeeded() &&
5077        !isolate->MayNamedAccess(*object, isolate->heap()->undefined_value(),
5078                             v8::ACCESS_KEYS)) {
5079      isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
5080      return *isolate->factory()->NewJSArray(0);
5081    }
5082
5083    Handle<Object> proto(object->GetPrototype());
5084    // If proxy is detached we simply return an empty array.
5085    if (proto->IsNull()) return *isolate->factory()->NewJSArray(0);
5086    object = Handle<JSObject>::cast(proto);
5087  }
5088
5089  bool threw = false;
5090  Handle<FixedArray> contents =
5091      GetKeysInFixedArrayFor(object, LOCAL_ONLY, &threw);
5092  if (threw) return Failure::Exception();
5093
5094  // Some fast paths through GetKeysInFixedArrayFor reuse a cached
5095  // property array and since the result is mutable we have to create
5096  // a fresh clone on each invocation.
5097  int length = contents->length();
5098  Handle<FixedArray> copy = isolate->factory()->NewFixedArray(length);
5099  for (int i = 0; i < length; i++) {
5100    Object* entry = contents->get(i);
5101    if (entry->IsString()) {
5102      copy->set(i, entry);
5103    } else {
5104      ASSERT(entry->IsNumber());
5105      HandleScope scope(isolate);
5106      Handle<Object> entry_handle(entry, isolate);
5107      Handle<Object> entry_str =
5108          isolate->factory()->NumberToString(entry_handle);
5109      copy->set(i, *entry_str);
5110    }
5111  }
5112  return *isolate->factory()->NewJSArrayWithElements(copy);
5113}
5114
5115
5116RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
5117  NoHandleAllocation ha;
5118  ASSERT(args.length() == 1);
5119
5120  // Compute the frame holding the arguments.
5121  JavaScriptFrameIterator it(isolate);
5122  it.AdvanceToArgumentsFrame();
5123  JavaScriptFrame* frame = it.frame();
5124
5125  // Get the actual number of provided arguments.
5126  const uint32_t n = frame->ComputeParametersCount();
5127
5128  // Try to convert the key to an index. If successful and within
5129  // index return the the argument from the frame.
5130  uint32_t index;
5131  if (args[0]->ToArrayIndex(&index) && index < n) {
5132    return frame->GetParameter(index);
5133  }
5134
5135  // Convert the key to a string.
5136  HandleScope scope(isolate);
5137  bool exception = false;
5138  Handle<Object> converted =
5139      Execution::ToString(args.at<Object>(0), &exception);
5140  if (exception) return Failure::Exception();
5141  Handle<String> key = Handle<String>::cast(converted);
5142
5143  // Try to convert the string key into an array index.
5144  if (key->AsArrayIndex(&index)) {
5145    if (index < n) {
5146      return frame->GetParameter(index);
5147    } else {
5148      return isolate->initial_object_prototype()->GetElement(index);
5149    }
5150  }
5151
5152  // Handle special arguments properties.
5153  if (key->Equals(isolate->heap()->length_symbol())) return Smi::FromInt(n);
5154  if (key->Equals(isolate->heap()->callee_symbol())) {
5155    Object* function = frame->function();
5156    if (function->IsJSFunction() &&
5157        !JSFunction::cast(function)->shared()->is_classic_mode()) {
5158      return isolate->Throw(*isolate->factory()->NewTypeError(
5159          "strict_arguments_callee", HandleVector<Object>(NULL, 0)));
5160    }
5161    return function;
5162  }
5163
5164  // Lookup in the initial Object.prototype object.
5165  return isolate->initial_object_prototype()->GetProperty(*key);
5166}
5167
5168
5169RUNTIME_FUNCTION(MaybeObject*, Runtime_ToFastProperties) {
5170  ASSERT(args.length() == 1);
5171  Object* object = args[0];
5172  return (object->IsJSObject() && !object->IsGlobalObject())
5173      ? JSObject::cast(object)->TransformToFastProperties(0)
5174      : object;
5175}
5176
5177
5178RUNTIME_FUNCTION(MaybeObject*, Runtime_ToSlowProperties) {
5179  ASSERT(args.length() == 1);
5180  Object* obj = args[0];
5181  return (obj->IsJSObject() && !obj->IsJSGlobalProxy())
5182      ? JSObject::cast(obj)->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0)
5183      : obj;
5184}
5185
5186
5187RUNTIME_FUNCTION(MaybeObject*, Runtime_ToBool) {
5188  NoHandleAllocation ha;
5189  ASSERT(args.length() == 1);
5190
5191  return args[0]->ToBoolean();
5192}
5193
5194
5195// Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
5196// Possible optimizations: put the type string into the oddballs.
5197RUNTIME_FUNCTION(MaybeObject*, Runtime_Typeof) {
5198  NoHandleAllocation ha;
5199
5200  Object* obj = args[0];
5201  if (obj->IsNumber()) return isolate->heap()->number_symbol();
5202  HeapObject* heap_obj = HeapObject::cast(obj);
5203
5204  // typeof an undetectable object is 'undefined'
5205  if (heap_obj->map()->is_undetectable()) {
5206    return isolate->heap()->undefined_symbol();
5207  }
5208
5209  InstanceType instance_type = heap_obj->map()->instance_type();
5210  if (instance_type < FIRST_NONSTRING_TYPE) {
5211    return isolate->heap()->string_symbol();
5212  }
5213
5214  switch (instance_type) {
5215    case ODDBALL_TYPE:
5216      if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
5217        return isolate->heap()->boolean_symbol();
5218      }
5219      if (heap_obj->IsNull()) {
5220        return FLAG_harmony_typeof
5221            ? isolate->heap()->null_symbol()
5222            : isolate->heap()->object_symbol();
5223      }
5224      ASSERT(heap_obj->IsUndefined());
5225      return isolate->heap()->undefined_symbol();
5226    case JS_FUNCTION_TYPE:
5227    case JS_FUNCTION_PROXY_TYPE:
5228      return isolate->heap()->function_symbol();
5229    default:
5230      // For any kind of object not handled above, the spec rule for
5231      // host objects gives that it is okay to return "object"
5232      return isolate->heap()->object_symbol();
5233  }
5234}
5235
5236
5237static bool AreDigits(const char*s, int from, int to) {
5238  for (int i = from; i < to; i++) {
5239    if (s[i] < '0' || s[i] > '9') return false;
5240  }
5241
5242  return true;
5243}
5244
5245
5246static int ParseDecimalInteger(const char*s, int from, int to) {
5247  ASSERT(to - from < 10);  // Overflow is not possible.
5248  ASSERT(from < to);
5249  int d = s[from] - '0';
5250
5251  for (int i = from + 1; i < to; i++) {
5252    d = 10 * d + (s[i] - '0');
5253  }
5254
5255  return d;
5256}
5257
5258
5259RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
5260  NoHandleAllocation ha;
5261  ASSERT(args.length() == 1);
5262  CONVERT_ARG_CHECKED(String, subject, 0);
5263  subject->TryFlatten();
5264
5265  // Fast case: short integer or some sorts of junk values.
5266  int len = subject->length();
5267  if (subject->IsSeqAsciiString()) {
5268    if (len == 0) return Smi::FromInt(0);
5269
5270    char const* data = SeqAsciiString::cast(subject)->GetChars();
5271    bool minus = (data[0] == '-');
5272    int start_pos = (minus ? 1 : 0);
5273
5274    if (start_pos == len) {
5275      return isolate->heap()->nan_value();
5276    } else if (data[start_pos] > '9') {
5277      // Fast check for a junk value. A valid string may start from a
5278      // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit or
5279      // the 'I' character ('Infinity'). All of that have codes not greater than
5280      // '9' except 'I'.
5281      if (data[start_pos] != 'I') {
5282        return isolate->heap()->nan_value();
5283      }
5284    } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
5285      // The maximal/minimal smi has 10 digits. If the string has less digits we
5286      // know it will fit into the smi-data type.
5287      int d = ParseDecimalInteger(data, start_pos, len);
5288      if (minus) {
5289        if (d == 0) return isolate->heap()->minus_zero_value();
5290        d = -d;
5291      } else if (!subject->HasHashCode() &&
5292                 len <= String::kMaxArrayIndexSize &&
5293                 (len == 1 || data[0] != '0')) {
5294        // String hash is not calculated yet but all the data are present.
5295        // Update the hash field to speed up sequential convertions.
5296        uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
5297#ifdef DEBUG
5298        subject->Hash();  // Force hash calculation.
5299        ASSERT_EQ(static_cast<int>(subject->hash_field()),
5300                  static_cast<int>(hash));
5301#endif
5302        subject->set_hash_field(hash);
5303      }
5304      return Smi::FromInt(d);
5305    }
5306  }
5307
5308  // Slower case.
5309  return isolate->heap()->NumberFromDouble(
5310      StringToDouble(isolate->unicode_cache(), subject, ALLOW_HEX));
5311}
5312
5313
5314RUNTIME_FUNCTION(MaybeObject*, Runtime_StringFromCharCodeArray) {
5315  NoHandleAllocation ha;
5316  ASSERT(args.length() == 1);
5317
5318  CONVERT_ARG_CHECKED(JSArray, codes, 0);
5319  int length = Smi::cast(codes->length())->value();
5320
5321  // Check if the string can be ASCII.
5322  int i;
5323  for (i = 0; i < length; i++) {
5324    Object* element;
5325    { MaybeObject* maybe_element = codes->GetElement(i);
5326      // We probably can't get an exception here, but just in order to enforce
5327      // the checking of inputs in the runtime calls we check here.
5328      if (!maybe_element->ToObject(&element)) return maybe_element;
5329    }
5330    CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
5331    if ((chr & 0xffff) > String::kMaxAsciiCharCode)
5332      break;
5333  }
5334
5335  MaybeObject* maybe_object = NULL;
5336  if (i == length) {  // The string is ASCII.
5337    maybe_object = isolate->heap()->AllocateRawAsciiString(length);
5338  } else {  // The string is not ASCII.
5339    maybe_object = isolate->heap()->AllocateRawTwoByteString(length);
5340  }
5341
5342  Object* object = NULL;
5343  if (!maybe_object->ToObject(&object)) return maybe_object;
5344  String* result = String::cast(object);
5345  for (int i = 0; i < length; i++) {
5346    Object* element;
5347    { MaybeObject* maybe_element = codes->GetElement(i);
5348      if (!maybe_element->ToObject(&element)) return maybe_element;
5349    }
5350    CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
5351    result->Set(i, chr & 0xffff);
5352  }
5353  return result;
5354}
5355
5356
5357// kNotEscaped is generated by the following:
5358//
5359// #!/bin/perl
5360// for (my $i = 0; $i < 256; $i++) {
5361//   print "\n" if $i % 16 == 0;
5362//   my $c = chr($i);
5363//   my $escaped = 1;
5364//   $escaped = 0 if $c =~ m#[A-Za-z0-9@*_+./-]#;
5365//   print $escaped ? "0, " : "1, ";
5366// }
5367
5368
5369static bool IsNotEscaped(uint16_t character) {
5370  // Only for 8 bit characters, the rest are always escaped (in a different way)
5371  ASSERT(character < 256);
5372  static const char kNotEscaped[256] = {
5373    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5374    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5375    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
5376    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
5377    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5378    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
5379    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5380    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
5381    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5382    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5383    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5384    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5385    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5386    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5387    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5388    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5389  };
5390  return kNotEscaped[character] != 0;
5391}
5392
5393
5394RUNTIME_FUNCTION(MaybeObject*, Runtime_URIEscape) {
5395  const char hex_chars[] = "0123456789ABCDEF";
5396  NoHandleAllocation ha;
5397  ASSERT(args.length() == 1);
5398  CONVERT_ARG_CHECKED(String, source, 0);
5399
5400  source->TryFlatten();
5401
5402  int escaped_length = 0;
5403  int length = source->length();
5404  {
5405    Access<StringInputBuffer> buffer(
5406        isolate->runtime_state()->string_input_buffer());
5407    buffer->Reset(source);
5408    while (buffer->has_more()) {
5409      uint16_t character = buffer->GetNext();
5410      if (character >= 256) {
5411        escaped_length += 6;
5412      } else if (IsNotEscaped(character)) {
5413        escaped_length++;
5414      } else {
5415        escaped_length += 3;
5416      }
5417      // We don't allow strings that are longer than a maximal length.
5418      ASSERT(String::kMaxLength < 0x7fffffff - 6);  // Cannot overflow.
5419      if (escaped_length > String::kMaxLength) {
5420        isolate->context()->mark_out_of_memory();
5421        return Failure::OutOfMemoryException();
5422      }
5423    }
5424  }
5425  // No length change implies no change.  Return original string if no change.
5426  if (escaped_length == length) {
5427    return source;
5428  }
5429  Object* o;
5430  { MaybeObject* maybe_o =
5431        isolate->heap()->AllocateRawAsciiString(escaped_length);
5432    if (!maybe_o->ToObject(&o)) return maybe_o;
5433  }
5434  String* destination = String::cast(o);
5435  int dest_position = 0;
5436
5437  Access<StringInputBuffer> buffer(
5438      isolate->runtime_state()->string_input_buffer());
5439  buffer->Rewind();
5440  while (buffer->has_more()) {
5441    uint16_t chr = buffer->GetNext();
5442    if (chr >= 256) {
5443      destination->Set(dest_position, '%');
5444      destination->Set(dest_position+1, 'u');
5445      destination->Set(dest_position+2, hex_chars[chr >> 12]);
5446      destination->Set(dest_position+3, hex_chars[(chr >> 8) & 0xf]);
5447      destination->Set(dest_position+4, hex_chars[(chr >> 4) & 0xf]);
5448      destination->Set(dest_position+5, hex_chars[chr & 0xf]);
5449      dest_position += 6;
5450    } else if (IsNotEscaped(chr)) {
5451      destination->Set(dest_position, chr);
5452      dest_position++;
5453    } else {
5454      destination->Set(dest_position, '%');
5455      destination->Set(dest_position+1, hex_chars[chr >> 4]);
5456      destination->Set(dest_position+2, hex_chars[chr & 0xf]);
5457      dest_position += 3;
5458    }
5459  }
5460  return destination;
5461}
5462
5463
5464static inline int TwoDigitHex(uint16_t character1, uint16_t character2) {
5465  static const signed char kHexValue['g'] = {
5466    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5467    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5468    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5469    0,  1,  2,   3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
5470    -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5471    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5472    -1, 10, 11, 12, 13, 14, 15 };
5473
5474  if (character1 > 'f') return -1;
5475  int hi = kHexValue[character1];
5476  if (hi == -1) return -1;
5477  if (character2 > 'f') return -1;
5478  int lo = kHexValue[character2];
5479  if (lo == -1) return -1;
5480  return (hi << 4) + lo;
5481}
5482
5483
5484static inline int Unescape(String* source,
5485                           int i,
5486                           int length,
5487                           int* step) {
5488  uint16_t character = source->Get(i);
5489  int32_t hi = 0;
5490  int32_t lo = 0;
5491  if (character == '%' &&
5492      i <= length - 6 &&
5493      source->Get(i + 1) == 'u' &&
5494      (hi = TwoDigitHex(source->Get(i + 2),
5495                        source->Get(i + 3))) != -1 &&
5496      (lo = TwoDigitHex(source->Get(i + 4),
5497                        source->Get(i + 5))) != -1) {
5498    *step = 6;
5499    return (hi << 8) + lo;
5500  } else if (character == '%' &&
5501      i <= length - 3 &&
5502      (lo = TwoDigitHex(source->Get(i + 1),
5503                        source->Get(i + 2))) != -1) {
5504    *step = 3;
5505    return lo;
5506  } else {
5507    *step = 1;
5508    return character;
5509  }
5510}
5511
5512
5513RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) {
5514  NoHandleAllocation ha;
5515  ASSERT(args.length() == 1);
5516  CONVERT_ARG_CHECKED(String, source, 0);
5517
5518  source->TryFlatten();
5519
5520  bool ascii = true;
5521  int length = source->length();
5522
5523  int unescaped_length = 0;
5524  for (int i = 0; i < length; unescaped_length++) {
5525    int step;
5526    if (Unescape(source, i, length, &step) > String::kMaxAsciiCharCode) {
5527      ascii = false;
5528    }
5529    i += step;
5530  }
5531
5532  // No length change implies no change.  Return original string if no change.
5533  if (unescaped_length == length)
5534    return source;
5535
5536  Object* o;
5537  { MaybeObject* maybe_o =
5538        ascii ?
5539        isolate->heap()->AllocateRawAsciiString(unescaped_length) :
5540        isolate->heap()->AllocateRawTwoByteString(unescaped_length);
5541    if (!maybe_o->ToObject(&o)) return maybe_o;
5542  }
5543  String* destination = String::cast(o);
5544
5545  int dest_position = 0;
5546  for (int i = 0; i < length; dest_position++) {
5547    int step;
5548    destination->Set(dest_position, Unescape(source, i, length, &step));
5549    i += step;
5550  }
5551  return destination;
5552}
5553
5554
5555static const unsigned int kQuoteTableLength = 128u;
5556
5557static const int kJsonQuotesCharactersPerEntry = 8;
5558static const char* const JsonQuotes =
5559    "\\u0000  \\u0001  \\u0002  \\u0003  "
5560    "\\u0004  \\u0005  \\u0006  \\u0007  "
5561    "\\b      \\t      \\n      \\u000b  "
5562    "\\f      \\r      \\u000e  \\u000f  "
5563    "\\u0010  \\u0011  \\u0012  \\u0013  "
5564    "\\u0014  \\u0015  \\u0016  \\u0017  "
5565    "\\u0018  \\u0019  \\u001a  \\u001b  "
5566    "\\u001c  \\u001d  \\u001e  \\u001f  "
5567    "        !       \\\"      #       "
5568    "$       %       &       '       "
5569    "(       )       *       +       "
5570    ",       -       .       /       "
5571    "0       1       2       3       "
5572    "4       5       6       7       "
5573    "8       9       :       ;       "
5574    "<       =       >       ?       "
5575    "@       A       B       C       "
5576    "D       E       F       G       "
5577    "H       I       J       K       "
5578    "L       M       N       O       "
5579    "P       Q       R       S       "
5580    "T       U       V       W       "
5581    "X       Y       Z       [       "
5582    "\\\\      ]       ^       _       "
5583    "`       a       b       c       "
5584    "d       e       f       g       "
5585    "h       i       j       k       "
5586    "l       m       n       o       "
5587    "p       q       r       s       "
5588    "t       u       v       w       "
5589    "x       y       z       {       "
5590    "|       }       ~       \177       ";
5591
5592
5593// For a string that is less than 32k characters it should always be
5594// possible to allocate it in new space.
5595static const int kMaxGuaranteedNewSpaceString = 32 * 1024;
5596
5597
5598// Doing JSON quoting cannot make the string more than this many times larger.
5599static const int kJsonQuoteWorstCaseBlowup = 6;
5600
5601static const int kSpaceForQuotesAndComma = 3;
5602static const int kSpaceForBrackets = 2;
5603
5604// Covers the entire ASCII range (all other characters are unchanged by JSON
5605// quoting).
5606static const byte JsonQuoteLengths[kQuoteTableLength] = {
5607    6, 6, 6, 6, 6, 6, 6, 6,
5608    2, 2, 2, 6, 2, 2, 6, 6,
5609    6, 6, 6, 6, 6, 6, 6, 6,
5610    6, 6, 6, 6, 6, 6, 6, 6,
5611    1, 1, 2, 1, 1, 1, 1, 1,
5612    1, 1, 1, 1, 1, 1, 1, 1,
5613    1, 1, 1, 1, 1, 1, 1, 1,
5614    1, 1, 1, 1, 1, 1, 1, 1,
5615    1, 1, 1, 1, 1, 1, 1, 1,
5616    1, 1, 1, 1, 1, 1, 1, 1,
5617    1, 1, 1, 1, 1, 1, 1, 1,
5618    1, 1, 1, 1, 2, 1, 1, 1,
5619    1, 1, 1, 1, 1, 1, 1, 1,
5620    1, 1, 1, 1, 1, 1, 1, 1,
5621    1, 1, 1, 1, 1, 1, 1, 1,
5622    1, 1, 1, 1, 1, 1, 1, 1,
5623};
5624
5625
5626template <typename StringType>
5627MaybeObject* AllocateRawString(Isolate* isolate, int length);
5628
5629
5630template <>
5631MaybeObject* AllocateRawString<SeqTwoByteString>(Isolate* isolate, int length) {
5632  return isolate->heap()->AllocateRawTwoByteString(length);
5633}
5634
5635
5636template <>
5637MaybeObject* AllocateRawString<SeqAsciiString>(Isolate* isolate, int length) {
5638  return isolate->heap()->AllocateRawAsciiString(length);
5639}
5640
5641
5642template <typename Char, typename StringType, bool comma>
5643static MaybeObject* SlowQuoteJsonString(Isolate* isolate,
5644                                        Vector<const Char> characters) {
5645  int length = characters.length();
5646  const Char* read_cursor = characters.start();
5647  const Char* end = read_cursor + length;
5648  const int kSpaceForQuotes = 2 + (comma ? 1 :0);
5649  int quoted_length = kSpaceForQuotes;
5650  while (read_cursor < end) {
5651    Char c = *(read_cursor++);
5652    if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) {
5653      quoted_length++;
5654    } else {
5655      quoted_length += JsonQuoteLengths[static_cast<unsigned>(c)];
5656    }
5657  }
5658  MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
5659                                                         quoted_length);
5660  Object* new_object;
5661  if (!new_alloc->ToObject(&new_object)) {
5662    return new_alloc;
5663  }
5664  StringType* new_string = StringType::cast(new_object);
5665
5666  Char* write_cursor = reinterpret_cast<Char*>(
5667      new_string->address() + SeqString::kHeaderSize);
5668  if (comma) *(write_cursor++) = ',';
5669  *(write_cursor++) = '"';
5670
5671  read_cursor = characters.start();
5672  while (read_cursor < end) {
5673    Char c = *(read_cursor++);
5674    if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) {
5675      *(write_cursor++) = c;
5676    } else {
5677      int len = JsonQuoteLengths[static_cast<unsigned>(c)];
5678      const char* replacement = JsonQuotes +
5679          static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry;
5680      for (int i = 0; i < len; i++) {
5681        *write_cursor++ = *replacement++;
5682      }
5683    }
5684  }
5685  *(write_cursor++) = '"';
5686  return new_string;
5687}
5688
5689
5690template <typename SinkChar, typename SourceChar>
5691static inline SinkChar* WriteQuoteJsonString(
5692    Isolate* isolate,
5693    SinkChar* write_cursor,
5694    Vector<const SourceChar> characters) {
5695  // SinkChar is only char if SourceChar is guaranteed to be char.
5696  ASSERT(sizeof(SinkChar) >= sizeof(SourceChar));
5697  const SourceChar* read_cursor = characters.start();
5698  const SourceChar* end = read_cursor + characters.length();
5699  *(write_cursor++) = '"';
5700  while (read_cursor < end) {
5701    SourceChar c = *(read_cursor++);
5702    if (sizeof(SourceChar) > 1u &&
5703        static_cast<unsigned>(c) >= kQuoteTableLength) {
5704      *(write_cursor++) = static_cast<SinkChar>(c);
5705    } else {
5706      int len = JsonQuoteLengths[static_cast<unsigned>(c)];
5707      const char* replacement = JsonQuotes +
5708          static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry;
5709      write_cursor[0] = replacement[0];
5710      if (len > 1) {
5711        write_cursor[1] = replacement[1];
5712        if (len > 2) {
5713          ASSERT(len == 6);
5714          write_cursor[2] = replacement[2];
5715          write_cursor[3] = replacement[3];
5716          write_cursor[4] = replacement[4];
5717          write_cursor[5] = replacement[5];
5718        }
5719      }
5720      write_cursor += len;
5721    }
5722  }
5723  *(write_cursor++) = '"';
5724  return write_cursor;
5725}
5726
5727
5728template <typename Char, typename StringType, bool comma>
5729static MaybeObject* QuoteJsonString(Isolate* isolate,
5730                                    Vector<const Char> characters) {
5731  int length = characters.length();
5732  isolate->counters()->quote_json_char_count()->Increment(length);
5733  int worst_case_length =
5734        length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotesAndComma;
5735  if (worst_case_length > kMaxGuaranteedNewSpaceString) {
5736    return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters);
5737  }
5738
5739  MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
5740                                                         worst_case_length);
5741  Object* new_object;
5742  if (!new_alloc->ToObject(&new_object)) {
5743    return new_alloc;
5744  }
5745  if (!isolate->heap()->new_space()->Contains(new_object)) {
5746    // Even if our string is small enough to fit in new space we still have to
5747    // handle it being allocated in old space as may happen in the third
5748    // attempt.  See CALL_AND_RETRY in heap-inl.h and similar code in
5749    // CEntryStub::GenerateCore.
5750    return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters);
5751  }
5752  StringType* new_string = StringType::cast(new_object);
5753  ASSERT(isolate->heap()->new_space()->Contains(new_string));
5754
5755  Char* write_cursor = reinterpret_cast<Char*>(
5756      new_string->address() + SeqString::kHeaderSize);
5757  if (comma) *(write_cursor++) = ',';
5758  write_cursor = WriteQuoteJsonString<Char, Char>(isolate,
5759                                                  write_cursor,
5760                                                  characters);
5761  int final_length = static_cast<int>(
5762      write_cursor - reinterpret_cast<Char*>(
5763          new_string->address() + SeqString::kHeaderSize));
5764  isolate->heap()->new_space()->
5765      template ShrinkStringAtAllocationBoundary<StringType>(
5766          new_string, final_length);
5767  return new_string;
5768}
5769
5770
5771RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONString) {
5772  NoHandleAllocation ha;
5773  CONVERT_ARG_CHECKED(String, str, 0);
5774  if (!str->IsFlat()) {
5775    MaybeObject* try_flatten = str->TryFlatten();
5776    Object* flat;
5777    if (!try_flatten->ToObject(&flat)) {
5778      return try_flatten;
5779    }
5780    str = String::cast(flat);
5781    ASSERT(str->IsFlat());
5782  }
5783  String::FlatContent flat = str->GetFlatContent();
5784  ASSERT(flat.IsFlat());
5785  if (flat.IsTwoByte()) {
5786    return QuoteJsonString<uc16, SeqTwoByteString, false>(isolate,
5787                                                          flat.ToUC16Vector());
5788  } else {
5789    return QuoteJsonString<char, SeqAsciiString, false>(isolate,
5790                                                        flat.ToAsciiVector());
5791  }
5792}
5793
5794
5795RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringComma) {
5796  NoHandleAllocation ha;
5797  CONVERT_ARG_CHECKED(String, str, 0);
5798  if (!str->IsFlat()) {
5799    MaybeObject* try_flatten = str->TryFlatten();
5800    Object* flat;
5801    if (!try_flatten->ToObject(&flat)) {
5802      return try_flatten;
5803    }
5804    str = String::cast(flat);
5805    ASSERT(str->IsFlat());
5806  }
5807  String::FlatContent flat = str->GetFlatContent();
5808  if (flat.IsTwoByte()) {
5809    return QuoteJsonString<uc16, SeqTwoByteString, true>(isolate,
5810                                                         flat.ToUC16Vector());
5811  } else {
5812    return QuoteJsonString<char, SeqAsciiString, true>(isolate,
5813                                                       flat.ToAsciiVector());
5814  }
5815}
5816
5817
5818template <typename Char, typename StringType>
5819static MaybeObject* QuoteJsonStringArray(Isolate* isolate,
5820                                         FixedArray* array,
5821                                         int worst_case_length) {
5822  int length = array->length();
5823
5824  MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
5825                                                         worst_case_length);
5826  Object* new_object;
5827  if (!new_alloc->ToObject(&new_object)) {
5828    return new_alloc;
5829  }
5830  if (!isolate->heap()->new_space()->Contains(new_object)) {
5831    // Even if our string is small enough to fit in new space we still have to
5832    // handle it being allocated in old space as may happen in the third
5833    // attempt.  See CALL_AND_RETRY in heap-inl.h and similar code in
5834    // CEntryStub::GenerateCore.
5835    return isolate->heap()->undefined_value();
5836  }
5837  AssertNoAllocation no_gc;
5838  StringType* new_string = StringType::cast(new_object);
5839  ASSERT(isolate->heap()->new_space()->Contains(new_string));
5840
5841  Char* write_cursor = reinterpret_cast<Char*>(
5842      new_string->address() + SeqString::kHeaderSize);
5843  *(write_cursor++) = '[';
5844  for (int i = 0; i < length; i++) {
5845    if (i != 0) *(write_cursor++) = ',';
5846    String* str = String::cast(array->get(i));
5847    String::FlatContent content = str->GetFlatContent();
5848    ASSERT(content.IsFlat());
5849    if (content.IsTwoByte()) {
5850      write_cursor = WriteQuoteJsonString<Char, uc16>(isolate,
5851                                                      write_cursor,
5852                                                      content.ToUC16Vector());
5853    } else {
5854      write_cursor = WriteQuoteJsonString<Char, char>(isolate,
5855                                                      write_cursor,
5856                                                      content.ToAsciiVector());
5857    }
5858  }
5859  *(write_cursor++) = ']';
5860
5861  int final_length = static_cast<int>(
5862      write_cursor - reinterpret_cast<Char*>(
5863          new_string->address() + SeqString::kHeaderSize));
5864  isolate->heap()->new_space()->
5865      template ShrinkStringAtAllocationBoundary<StringType>(
5866          new_string, final_length);
5867  return new_string;
5868}
5869
5870
5871RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringArray) {
5872  NoHandleAllocation ha;
5873  ASSERT(args.length() == 1);
5874  CONVERT_ARG_CHECKED(JSArray, array, 0);
5875
5876  if (!array->HasFastElements()) return isolate->heap()->undefined_value();
5877  FixedArray* elements = FixedArray::cast(array->elements());
5878  int n = elements->length();
5879  bool ascii = true;
5880  int total_length = 0;
5881
5882  for (int i = 0; i < n; i++) {
5883    Object* elt = elements->get(i);
5884    if (!elt->IsString()) return isolate->heap()->undefined_value();
5885    String* element = String::cast(elt);
5886    if (!element->IsFlat()) return isolate->heap()->undefined_value();
5887    total_length += element->length();
5888    if (ascii && element->IsTwoByteRepresentation()) {
5889      ascii = false;
5890    }
5891  }
5892
5893  int worst_case_length =
5894      kSpaceForBrackets + n * kSpaceForQuotesAndComma
5895      + total_length * kJsonQuoteWorstCaseBlowup;
5896
5897  if (worst_case_length > kMaxGuaranteedNewSpaceString) {
5898    return isolate->heap()->undefined_value();
5899  }
5900
5901  if (ascii) {
5902    return QuoteJsonStringArray<char, SeqAsciiString>(isolate,
5903                                                      elements,
5904                                                      worst_case_length);
5905  } else {
5906    return QuoteJsonStringArray<uc16, SeqTwoByteString>(isolate,
5907                                                        elements,
5908                                                        worst_case_length);
5909  }
5910}
5911
5912
5913RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) {
5914  NoHandleAllocation ha;
5915
5916  CONVERT_ARG_CHECKED(String, s, 0);
5917  CONVERT_SMI_ARG_CHECKED(radix, 1);
5918
5919  s->TryFlatten();
5920
5921  RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
5922  double value = StringToInt(isolate->unicode_cache(), s, radix);
5923  return isolate->heap()->NumberFromDouble(value);
5924}
5925
5926
5927RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) {
5928  NoHandleAllocation ha;
5929  CONVERT_ARG_CHECKED(String, str, 0);
5930
5931  // ECMA-262 section 15.1.2.3, empty string is NaN
5932  double value = StringToDouble(isolate->unicode_cache(),
5933                                str, ALLOW_TRAILING_JUNK, OS::nan_value());
5934
5935  // Create a number object from the value.
5936  return isolate->heap()->NumberFromDouble(value);
5937}
5938
5939
5940template <class Converter>
5941MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
5942    Isolate* isolate,
5943    String* s,
5944    int length,
5945    int input_string_length,
5946    unibrow::Mapping<Converter, 128>* mapping) {
5947  // We try this twice, once with the assumption that the result is no longer
5948  // than the input and, if that assumption breaks, again with the exact
5949  // length.  This may not be pretty, but it is nicer than what was here before
5950  // and I hereby claim my vaffel-is.
5951  //
5952  // Allocate the resulting string.
5953  //
5954  // NOTE: This assumes that the upper/lower case of an ASCII
5955  // character is also ASCII.  This is currently the case, but it
5956  // might break in the future if we implement more context and locale
5957  // dependent upper/lower conversions.
5958  Object* o;
5959  { MaybeObject* maybe_o = s->IsAsciiRepresentation()
5960        ? isolate->heap()->AllocateRawAsciiString(length)
5961        : isolate->heap()->AllocateRawTwoByteString(length);
5962    if (!maybe_o->ToObject(&o)) return maybe_o;
5963  }
5964  String* result = String::cast(o);
5965  bool has_changed_character = false;
5966
5967  // Convert all characters to upper case, assuming that they will fit
5968  // in the buffer
5969  Access<StringInputBuffer> buffer(
5970      isolate->runtime_state()->string_input_buffer());
5971  buffer->Reset(s);
5972  unibrow::uchar chars[Converter::kMaxWidth];
5973  // We can assume that the string is not empty
5974  uc32 current = buffer->GetNext();
5975  for (int i = 0; i < length;) {
5976    bool has_next = buffer->has_more();
5977    uc32 next = has_next ? buffer->GetNext() : 0;
5978    int char_length = mapping->get(current, next, chars);
5979    if (char_length == 0) {
5980      // The case conversion of this character is the character itself.
5981      result->Set(i, current);
5982      i++;
5983    } else if (char_length == 1) {
5984      // Common case: converting the letter resulted in one character.
5985      ASSERT(static_cast<uc32>(chars[0]) != current);
5986      result->Set(i, chars[0]);
5987      has_changed_character = true;
5988      i++;
5989    } else if (length == input_string_length) {
5990      // We've assumed that the result would be as long as the
5991      // input but here is a character that converts to several
5992      // characters.  No matter, we calculate the exact length
5993      // of the result and try the whole thing again.
5994      //
5995      // Note that this leaves room for optimization.  We could just
5996      // memcpy what we already have to the result string.  Also,
5997      // the result string is the last object allocated we could
5998      // "realloc" it and probably, in the vast majority of cases,
5999      // extend the existing string to be able to hold the full
6000      // result.
6001      int next_length = 0;
6002      if (has_next) {
6003        next_length = mapping->get(next, 0, chars);
6004        if (next_length == 0) next_length = 1;
6005      }
6006      int current_length = i + char_length + next_length;
6007      while (buffer->has_more()) {
6008        current = buffer->GetNext();
6009        // NOTE: we use 0 as the next character here because, while
6010        // the next character may affect what a character converts to,
6011        // it does not in any case affect the length of what it convert
6012        // to.
6013        int char_length = mapping->get(current, 0, chars);
6014        if (char_length == 0) char_length = 1;
6015        current_length += char_length;
6016        if (current_length > Smi::kMaxValue) {
6017          isolate->context()->mark_out_of_memory();
6018          return Failure::OutOfMemoryException();
6019        }
6020      }
6021      // Try again with the real length.
6022      return Smi::FromInt(current_length);
6023    } else {
6024      for (int j = 0; j < char_length; j++) {
6025        result->Set(i, chars[j]);
6026        i++;
6027      }
6028      has_changed_character = true;
6029    }
6030    current = next;
6031  }
6032  if (has_changed_character) {
6033    return result;
6034  } else {
6035    // If we didn't actually change anything in doing the conversion
6036    // we simple return the result and let the converted string
6037    // become garbage; there is no reason to keep two identical strings
6038    // alive.
6039    return s;
6040  }
6041}
6042
6043
6044namespace {
6045
6046static const uintptr_t kOneInEveryByte = kUintptrAllBitsSet / 0xFF;
6047
6048
6049// Given a word and two range boundaries returns a word with high bit
6050// set in every byte iff the corresponding input byte was strictly in
6051// the range (m, n). All the other bits in the result are cleared.
6052// This function is only useful when it can be inlined and the
6053// boundaries are statically known.
6054// Requires: all bytes in the input word and the boundaries must be
6055// ASCII (less than 0x7F).
6056static inline uintptr_t AsciiRangeMask(uintptr_t w, char m, char n) {
6057  // Every byte in an ASCII string is less than or equal to 0x7F.
6058  ASSERT((w & (kOneInEveryByte * 0x7F)) == w);
6059  // Use strict inequalities since in edge cases the function could be
6060  // further simplified.
6061  ASSERT(0 < m && m < n && n < 0x7F);
6062  // Has high bit set in every w byte less than n.
6063  uintptr_t tmp1 = kOneInEveryByte * (0x7F + n) - w;
6064  // Has high bit set in every w byte greater than m.
6065  uintptr_t tmp2 = w + kOneInEveryByte * (0x7F - m);
6066  return (tmp1 & tmp2 & (kOneInEveryByte * 0x80));
6067}
6068
6069
6070enum AsciiCaseConversion {
6071  ASCII_TO_LOWER,
6072  ASCII_TO_UPPER
6073};
6074
6075
6076template <AsciiCaseConversion dir>
6077struct FastAsciiConverter {
6078  static bool Convert(char* dst, char* src, int length) {
6079#ifdef DEBUG
6080    char* saved_dst = dst;
6081    char* saved_src = src;
6082#endif
6083    // We rely on the distance between upper and lower case letters
6084    // being a known power of 2.
6085    ASSERT('a' - 'A' == (1 << 5));
6086    // Boundaries for the range of input characters than require conversion.
6087    const char lo = (dir == ASCII_TO_LOWER) ? 'A' - 1 : 'a' - 1;
6088    const char hi = (dir == ASCII_TO_LOWER) ? 'Z' + 1 : 'z' + 1;
6089    bool changed = false;
6090    char* const limit = src + length;
6091#ifdef V8_HOST_CAN_READ_UNALIGNED
6092    // Process the prefix of the input that requires no conversion one
6093    // (machine) word at a time.
6094    while (src <= limit - sizeof(uintptr_t)) {
6095      uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
6096      if (AsciiRangeMask(w, lo, hi) != 0) {
6097        changed = true;
6098        break;
6099      }
6100      *reinterpret_cast<uintptr_t*>(dst) = w;
6101      src += sizeof(uintptr_t);
6102      dst += sizeof(uintptr_t);
6103    }
6104    // Process the remainder of the input performing conversion when
6105    // required one word at a time.
6106    while (src <= limit - sizeof(uintptr_t)) {
6107      uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
6108      uintptr_t m = AsciiRangeMask(w, lo, hi);
6109      // The mask has high (7th) bit set in every byte that needs
6110      // conversion and we know that the distance between cases is
6111      // 1 << 5.
6112      *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2);
6113      src += sizeof(uintptr_t);
6114      dst += sizeof(uintptr_t);
6115    }
6116#endif
6117    // Process the last few bytes of the input (or the whole input if
6118    // unaligned access is not supported).
6119    while (src < limit) {
6120      char c = *src;
6121      if (lo < c && c < hi) {
6122        c ^= (1 << 5);
6123        changed = true;
6124      }
6125      *dst = c;
6126      ++src;
6127      ++dst;
6128    }
6129#ifdef DEBUG
6130    CheckConvert(saved_dst, saved_src, length, changed);
6131#endif
6132    return changed;
6133  }
6134
6135#ifdef DEBUG
6136  static void CheckConvert(char* dst, char* src, int length, bool changed) {
6137    bool expected_changed = false;
6138    for (int i = 0; i < length; i++) {
6139      if (dst[i] == src[i]) continue;
6140      expected_changed = true;
6141      if (dir == ASCII_TO_LOWER) {
6142        ASSERT('A' <= src[i] && src[i] <= 'Z');
6143        ASSERT(dst[i] == src[i] + ('a' - 'A'));
6144      } else {
6145        ASSERT(dir == ASCII_TO_UPPER);
6146        ASSERT('a' <= src[i] && src[i] <= 'z');
6147        ASSERT(dst[i] == src[i] - ('a' - 'A'));
6148      }
6149    }
6150    ASSERT(expected_changed == changed);
6151  }
6152#endif
6153};
6154
6155
6156struct ToLowerTraits {
6157  typedef unibrow::ToLowercase UnibrowConverter;
6158
6159  typedef FastAsciiConverter<ASCII_TO_LOWER> AsciiConverter;
6160};
6161
6162
6163struct ToUpperTraits {
6164  typedef unibrow::ToUppercase UnibrowConverter;
6165
6166  typedef FastAsciiConverter<ASCII_TO_UPPER> AsciiConverter;
6167};
6168
6169}  // namespace
6170
6171
6172template <typename ConvertTraits>
6173MUST_USE_RESULT static MaybeObject* ConvertCase(
6174    Arguments args,
6175    Isolate* isolate,
6176    unibrow::Mapping<typename ConvertTraits::UnibrowConverter, 128>* mapping) {
6177  NoHandleAllocation ha;
6178  CONVERT_ARG_CHECKED(String, s, 0);
6179  s = s->TryFlattenGetString();
6180
6181  const int length = s->length();
6182  // Assume that the string is not empty; we need this assumption later
6183  if (length == 0) return s;
6184
6185  // Simpler handling of ASCII strings.
6186  //
6187  // NOTE: This assumes that the upper/lower case of an ASCII
6188  // character is also ASCII.  This is currently the case, but it
6189  // might break in the future if we implement more context and locale
6190  // dependent upper/lower conversions.
6191  if (s->IsSeqAsciiString()) {
6192    Object* o;
6193    { MaybeObject* maybe_o = isolate->heap()->AllocateRawAsciiString(length);
6194      if (!maybe_o->ToObject(&o)) return maybe_o;
6195    }
6196    SeqAsciiString* result = SeqAsciiString::cast(o);
6197    bool has_changed_character = ConvertTraits::AsciiConverter::Convert(
6198        result->GetChars(), SeqAsciiString::cast(s)->GetChars(), length);
6199    return has_changed_character ? result : s;
6200  }
6201
6202  Object* answer;
6203  { MaybeObject* maybe_answer =
6204        ConvertCaseHelper(isolate, s, length, length, mapping);
6205    if (!maybe_answer->ToObject(&answer)) return maybe_answer;
6206  }
6207  if (answer->IsSmi()) {
6208    // Retry with correct length.
6209    { MaybeObject* maybe_answer =
6210          ConvertCaseHelper(isolate,
6211                            s, Smi::cast(answer)->value(), length, mapping);
6212      if (!maybe_answer->ToObject(&answer)) return maybe_answer;
6213    }
6214  }
6215  return answer;
6216}
6217
6218
6219RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) {
6220  return ConvertCase<ToLowerTraits>(
6221      args, isolate, isolate->runtime_state()->to_lower_mapping());
6222}
6223
6224
6225RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToUpperCase) {
6226  return ConvertCase<ToUpperTraits>(
6227      args, isolate, isolate->runtime_state()->to_upper_mapping());
6228}
6229
6230
6231static inline bool IsTrimWhiteSpace(unibrow::uchar c) {
6232  return unibrow::WhiteSpace::Is(c) || c == 0x200b || c == 0xfeff;
6233}
6234
6235
6236RUNTIME_FUNCTION(MaybeObject*, Runtime_StringTrim) {
6237  NoHandleAllocation ha;
6238  ASSERT(args.length() == 3);
6239
6240  CONVERT_ARG_CHECKED(String, s, 0);
6241  CONVERT_BOOLEAN_ARG_CHECKED(trimLeft, 1);
6242  CONVERT_BOOLEAN_ARG_CHECKED(trimRight, 2);
6243
6244  s->TryFlatten();
6245  int length = s->length();
6246
6247  int left = 0;
6248  if (trimLeft) {
6249    while (left < length && IsTrimWhiteSpace(s->Get(left))) {
6250      left++;
6251    }
6252  }
6253
6254  int right = length;
6255  if (trimRight) {
6256    while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) {
6257      right--;
6258    }
6259  }
6260  return s->SubString(left, right);
6261}
6262
6263
6264RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
6265  ASSERT(args.length() == 3);
6266  HandleScope handle_scope(isolate);
6267  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
6268  CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
6269  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]);
6270
6271  int subject_length = subject->length();
6272  int pattern_length = pattern->length();
6273  RUNTIME_ASSERT(pattern_length > 0);
6274
6275  if (limit == 0xffffffffu) {
6276    Handle<Object> cached_answer(StringSplitCache::Lookup(
6277        isolate->heap()->string_split_cache(),
6278        *subject,
6279        *pattern));
6280    if (*cached_answer != Smi::FromInt(0)) {
6281      Handle<JSArray> result =
6282          isolate->factory()->NewJSArrayWithElements(
6283              Handle<FixedArray>::cast(cached_answer));
6284      return *result;
6285    }
6286  }
6287
6288  // The limit can be very large (0xffffffffu), but since the pattern
6289  // isn't empty, we can never create more parts than ~half the length
6290  // of the subject.
6291
6292  if (!subject->IsFlat()) FlattenString(subject);
6293
6294  static const int kMaxInitialListCapacity = 16;
6295
6296  ZoneScope scope(isolate, DELETE_ON_EXIT);
6297
6298  // Find (up to limit) indices of separator and end-of-string in subject
6299  int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit);
6300  ZoneList<int> indices(initial_capacity);
6301  if (!pattern->IsFlat()) FlattenString(pattern);
6302
6303  FindStringIndicesDispatch(isolate, *subject, *pattern, &indices, limit);
6304
6305  if (static_cast<uint32_t>(indices.length()) < limit) {
6306    indices.Add(subject_length);
6307  }
6308
6309  // The list indices now contains the end of each part to create.
6310
6311  // Create JSArray of substrings separated by separator.
6312  int part_count = indices.length();
6313
6314  Handle<JSArray> result = isolate->factory()->NewJSArray(part_count);
6315  MaybeObject* maybe_result = result->EnsureCanContainHeapObjectElements();
6316  if (maybe_result->IsFailure()) return maybe_result;
6317  result->set_length(Smi::FromInt(part_count));
6318
6319  ASSERT(result->HasFastElements());
6320
6321  if (part_count == 1 && indices.at(0) == subject_length) {
6322    FixedArray::cast(result->elements())->set(0, *subject);
6323    return *result;
6324  }
6325
6326  Handle<FixedArray> elements(FixedArray::cast(result->elements()));
6327  int part_start = 0;
6328  for (int i = 0; i < part_count; i++) {
6329    HandleScope local_loop_handle;
6330    int part_end = indices.at(i);
6331    Handle<String> substring =
6332        isolate->factory()->NewProperSubString(subject, part_start, part_end);
6333    elements->set(i, *substring);
6334    part_start = part_end + pattern_length;
6335  }
6336
6337  if (limit == 0xffffffffu) {
6338    if (result->HasFastElements()) {
6339      StringSplitCache::Enter(isolate->heap(),
6340                              isolate->heap()->string_split_cache(),
6341                              *subject,
6342                              *pattern,
6343                              *elements);
6344    }
6345  }
6346
6347  return *result;
6348}
6349
6350
6351// Copies ASCII characters to the given fixed array looking up
6352// one-char strings in the cache. Gives up on the first char that is
6353// not in the cache and fills the remainder with smi zeros. Returns
6354// the length of the successfully copied prefix.
6355static int CopyCachedAsciiCharsToArray(Heap* heap,
6356                                       const char* chars,
6357                                       FixedArray* elements,
6358                                       int length) {
6359  AssertNoAllocation no_gc;
6360  FixedArray* ascii_cache = heap->single_character_string_cache();
6361  Object* undefined = heap->undefined_value();
6362  int i;
6363  WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
6364  for (i = 0; i < length; ++i) {
6365    Object* value = ascii_cache->get(chars[i]);
6366    if (value == undefined) break;
6367    elements->set(i, value, mode);
6368  }
6369  if (i < length) {
6370    ASSERT(Smi::FromInt(0) == 0);
6371    memset(elements->data_start() + i, 0, kPointerSize * (length - i));
6372  }
6373#ifdef DEBUG
6374  for (int j = 0; j < length; ++j) {
6375    Object* element = elements->get(j);
6376    ASSERT(element == Smi::FromInt(0) ||
6377           (element->IsString() && String::cast(element)->LooksValid()));
6378  }
6379#endif
6380  return i;
6381}
6382
6383
6384// Converts a String to JSArray.
6385// For example, "foo" => ["f", "o", "o"].
6386RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToArray) {
6387  HandleScope scope(isolate);
6388  ASSERT(args.length() == 2);
6389  CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
6390  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
6391
6392  s = FlattenGetString(s);
6393  const int length = static_cast<int>(Min<uint32_t>(s->length(), limit));
6394
6395  Handle<FixedArray> elements;
6396  int position = 0;
6397  if (s->IsFlat() && s->IsAsciiRepresentation()) {
6398    // Try using cached chars where possible.
6399    Object* obj;
6400    { MaybeObject* maybe_obj =
6401          isolate->heap()->AllocateUninitializedFixedArray(length);
6402      if (!maybe_obj->ToObject(&obj)) return maybe_obj;
6403    }
6404    elements = Handle<FixedArray>(FixedArray::cast(obj), isolate);
6405    String::FlatContent content = s->GetFlatContent();
6406    if (content.IsAscii()) {
6407      Vector<const char> chars = content.ToAsciiVector();
6408      // Note, this will initialize all elements (not only the prefix)
6409      // to prevent GC from seeing partially initialized array.
6410      position = CopyCachedAsciiCharsToArray(isolate->heap(),
6411                                             chars.start(),
6412                                             *elements,
6413                                             length);
6414    } else {
6415      MemsetPointer(elements->data_start(),
6416                    isolate->heap()->undefined_value(),
6417                    length);
6418    }
6419  } else {
6420    elements = isolate->factory()->NewFixedArray(length);
6421  }
6422  for (int i = position; i < length; ++i) {
6423    Handle<Object> str = LookupSingleCharacterStringFromCode(s->Get(i));
6424    elements->set(i, *str);
6425  }
6426
6427#ifdef DEBUG
6428  for (int i = 0; i < length; ++i) {
6429    ASSERT(String::cast(elements->get(i))->length() == 1);
6430  }
6431#endif
6432
6433  return *isolate->factory()->NewJSArrayWithElements(elements);
6434}
6435
6436
6437RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStringWrapper) {
6438  NoHandleAllocation ha;
6439  ASSERT(args.length() == 1);
6440  CONVERT_ARG_CHECKED(String, value, 0);
6441  return value->ToObject();
6442}
6443
6444
6445bool Runtime::IsUpperCaseChar(RuntimeState* runtime_state, uint16_t ch) {
6446  unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth];
6447  int char_length = runtime_state->to_upper_mapping()->get(ch, 0, chars);
6448  return char_length == 0;
6449}
6450
6451
6452RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToString) {
6453  NoHandleAllocation ha;
6454  ASSERT(args.length() == 1);
6455
6456  Object* number = args[0];
6457  RUNTIME_ASSERT(number->IsNumber());
6458
6459  return isolate->heap()->NumberToString(number);
6460}
6461
6462
6463RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToStringSkipCache) {
6464  NoHandleAllocation ha;
6465  ASSERT(args.length() == 1);
6466
6467  Object* number = args[0];
6468  RUNTIME_ASSERT(number->IsNumber());
6469
6470  return isolate->heap()->NumberToString(number, false);
6471}
6472
6473
6474RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToInteger) {
6475  NoHandleAllocation ha;
6476  ASSERT(args.length() == 1);
6477
6478  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6479
6480  // We do not include 0 so that we don't have to treat +0 / -0 cases.
6481  if (number > 0 && number <= Smi::kMaxValue) {
6482    return Smi::FromInt(static_cast<int>(number));
6483  }
6484  return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
6485}
6486
6487
6488RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToIntegerMapMinusZero) {
6489  NoHandleAllocation ha;
6490  ASSERT(args.length() == 1);
6491
6492  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6493
6494  // We do not include 0 so that we don't have to treat +0 / -0 cases.
6495  if (number > 0 && number <= Smi::kMaxValue) {
6496    return Smi::FromInt(static_cast<int>(number));
6497  }
6498
6499  double double_value = DoubleToInteger(number);
6500  // Map both -0 and +0 to +0.
6501  if (double_value == 0) double_value = 0;
6502
6503  return isolate->heap()->NumberFromDouble(double_value);
6504}
6505
6506
6507RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSUint32) {
6508  NoHandleAllocation ha;
6509  ASSERT(args.length() == 1);
6510
6511  CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]);
6512  return isolate->heap()->NumberFromUint32(number);
6513}
6514
6515
6516RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSInt32) {
6517  NoHandleAllocation ha;
6518  ASSERT(args.length() == 1);
6519
6520  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6521
6522  // We do not include 0 so that we don't have to treat +0 / -0 cases.
6523  if (number > 0 && number <= Smi::kMaxValue) {
6524    return Smi::FromInt(static_cast<int>(number));
6525  }
6526  return isolate->heap()->NumberFromInt32(DoubleToInt32(number));
6527}
6528
6529
6530// Converts a Number to a Smi, if possible. Returns NaN if the number is not
6531// a small integer.
6532RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToSmi) {
6533  NoHandleAllocation ha;
6534  ASSERT(args.length() == 1);
6535
6536  Object* obj = args[0];
6537  if (obj->IsSmi()) {
6538    return obj;
6539  }
6540  if (obj->IsHeapNumber()) {
6541    double value = HeapNumber::cast(obj)->value();
6542    int int_value = FastD2I(value);
6543    if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
6544      return Smi::FromInt(int_value);
6545    }
6546  }
6547  return isolate->heap()->nan_value();
6548}
6549
6550
6551RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateHeapNumber) {
6552  NoHandleAllocation ha;
6553  ASSERT(args.length() == 0);
6554  return isolate->heap()->AllocateHeapNumber(0);
6555}
6556
6557
6558RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAdd) {
6559  NoHandleAllocation ha;
6560  ASSERT(args.length() == 2);
6561
6562  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6563  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6564  return isolate->heap()->NumberFromDouble(x + y);
6565}
6566
6567
6568RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSub) {
6569  NoHandleAllocation ha;
6570  ASSERT(args.length() == 2);
6571
6572  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6573  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6574  return isolate->heap()->NumberFromDouble(x - y);
6575}
6576
6577
6578RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMul) {
6579  NoHandleAllocation ha;
6580  ASSERT(args.length() == 2);
6581
6582  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6583  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6584  return isolate->heap()->NumberFromDouble(x * y);
6585}
6586
6587
6588RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberUnaryMinus) {
6589  NoHandleAllocation ha;
6590  ASSERT(args.length() == 1);
6591
6592  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6593  return isolate->heap()->NumberFromDouble(-x);
6594}
6595
6596
6597RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAlloc) {
6598  NoHandleAllocation ha;
6599  ASSERT(args.length() == 0);
6600
6601  return isolate->heap()->NumberFromDouble(9876543210.0);
6602}
6603
6604
6605RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberDiv) {
6606  NoHandleAllocation ha;
6607  ASSERT(args.length() == 2);
6608
6609  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6610  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6611  return isolate->heap()->NumberFromDouble(x / y);
6612}
6613
6614
6615RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMod) {
6616  NoHandleAllocation ha;
6617  ASSERT(args.length() == 2);
6618
6619  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6620  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6621
6622  x = modulo(x, y);
6623  // NumberFromDouble may return a Smi instead of a Number object
6624  return isolate->heap()->NumberFromDouble(x);
6625}
6626
6627
6628RUNTIME_FUNCTION(MaybeObject*, Runtime_StringAdd) {
6629  NoHandleAllocation ha;
6630  ASSERT(args.length() == 2);
6631  CONVERT_ARG_CHECKED(String, str1, 0);
6632  CONVERT_ARG_CHECKED(String, str2, 1);
6633  isolate->counters()->string_add_runtime()->Increment();
6634  return isolate->heap()->AllocateConsString(str1, str2);
6635}
6636
6637
6638template <typename sinkchar>
6639static inline void StringBuilderConcatHelper(String* special,
6640                                             sinkchar* sink,
6641                                             FixedArray* fixed_array,
6642                                             int array_length) {
6643  int position = 0;
6644  for (int i = 0; i < array_length; i++) {
6645    Object* element = fixed_array->get(i);
6646    if (element->IsSmi()) {
6647      // Smi encoding of position and length.
6648      int encoded_slice = Smi::cast(element)->value();
6649      int pos;
6650      int len;
6651      if (encoded_slice > 0) {
6652        // Position and length encoded in one smi.
6653        pos = StringBuilderSubstringPosition::decode(encoded_slice);
6654        len = StringBuilderSubstringLength::decode(encoded_slice);
6655      } else {
6656        // Position and length encoded in two smis.
6657        Object* obj = fixed_array->get(++i);
6658        ASSERT(obj->IsSmi());
6659        pos = Smi::cast(obj)->value();
6660        len = -encoded_slice;
6661      }
6662      String::WriteToFlat(special,
6663                          sink + position,
6664                          pos,
6665                          pos + len);
6666      position += len;
6667    } else {
6668      String* string = String::cast(element);
6669      int element_length = string->length();
6670      String::WriteToFlat(string, sink + position, 0, element_length);
6671      position += element_length;
6672    }
6673  }
6674}
6675
6676
6677RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
6678  NoHandleAllocation ha;
6679  ASSERT(args.length() == 3);
6680  CONVERT_ARG_CHECKED(JSArray, array, 0);
6681  if (!args[1]->IsSmi()) {
6682    isolate->context()->mark_out_of_memory();
6683    return Failure::OutOfMemoryException();
6684  }
6685  int array_length = args.smi_at(1);
6686  CONVERT_ARG_CHECKED(String, special, 2);
6687
6688  // This assumption is used by the slice encoding in one or two smis.
6689  ASSERT(Smi::kMaxValue >= String::kMaxLength);
6690
6691  MaybeObject* maybe_result = array->EnsureCanContainHeapObjectElements();
6692  if (maybe_result->IsFailure()) return maybe_result;
6693
6694  int special_length = special->length();
6695  if (!array->HasFastElements()) {
6696    return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6697  }
6698  FixedArray* fixed_array = FixedArray::cast(array->elements());
6699  if (fixed_array->length() < array_length) {
6700    array_length = fixed_array->length();
6701  }
6702
6703  if (array_length == 0) {
6704    return isolate->heap()->empty_string();
6705  } else if (array_length == 1) {
6706    Object* first = fixed_array->get(0);
6707    if (first->IsString()) return first;
6708  }
6709
6710  bool ascii = special->HasOnlyAsciiChars();
6711  int position = 0;
6712  for (int i = 0; i < array_length; i++) {
6713    int increment = 0;
6714    Object* elt = fixed_array->get(i);
6715    if (elt->IsSmi()) {
6716      // Smi encoding of position and length.
6717      int smi_value = Smi::cast(elt)->value();
6718      int pos;
6719      int len;
6720      if (smi_value > 0) {
6721        // Position and length encoded in one smi.
6722        pos = StringBuilderSubstringPosition::decode(smi_value);
6723        len = StringBuilderSubstringLength::decode(smi_value);
6724      } else {
6725        // Position and length encoded in two smis.
6726        len = -smi_value;
6727        // Get the position and check that it is a positive smi.
6728        i++;
6729        if (i >= array_length) {
6730          return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6731        }
6732        Object* next_smi = fixed_array->get(i);
6733        if (!next_smi->IsSmi()) {
6734          return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6735        }
6736        pos = Smi::cast(next_smi)->value();
6737        if (pos < 0) {
6738          return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6739        }
6740      }
6741      ASSERT(pos >= 0);
6742      ASSERT(len >= 0);
6743      if (pos > special_length || len > special_length - pos) {
6744        return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6745      }
6746      increment = len;
6747    } else if (elt->IsString()) {
6748      String* element = String::cast(elt);
6749      int element_length = element->length();
6750      increment = element_length;
6751      if (ascii && !element->HasOnlyAsciiChars()) {
6752        ascii = false;
6753      }
6754    } else {
6755      ASSERT(!elt->IsTheHole());
6756      return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6757    }
6758    if (increment > String::kMaxLength - position) {
6759      isolate->context()->mark_out_of_memory();
6760      return Failure::OutOfMemoryException();
6761    }
6762    position += increment;
6763  }
6764
6765  int length = position;
6766  Object* object;
6767
6768  if (ascii) {
6769    { MaybeObject* maybe_object =
6770          isolate->heap()->AllocateRawAsciiString(length);
6771      if (!maybe_object->ToObject(&object)) return maybe_object;
6772    }
6773    SeqAsciiString* answer = SeqAsciiString::cast(object);
6774    StringBuilderConcatHelper(special,
6775                              answer->GetChars(),
6776                              fixed_array,
6777                              array_length);
6778    return answer;
6779  } else {
6780    { MaybeObject* maybe_object =
6781          isolate->heap()->AllocateRawTwoByteString(length);
6782      if (!maybe_object->ToObject(&object)) return maybe_object;
6783    }
6784    SeqTwoByteString* answer = SeqTwoByteString::cast(object);
6785    StringBuilderConcatHelper(special,
6786                              answer->GetChars(),
6787                              fixed_array,
6788                              array_length);
6789    return answer;
6790  }
6791}
6792
6793
6794RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
6795  NoHandleAllocation ha;
6796  ASSERT(args.length() == 3);
6797  CONVERT_ARG_CHECKED(JSArray, array, 0);
6798  if (!args[1]->IsSmi()) {
6799    isolate->context()->mark_out_of_memory();
6800    return Failure::OutOfMemoryException();
6801  }
6802  int array_length = args.smi_at(1);
6803  CONVERT_ARG_CHECKED(String, separator, 2);
6804
6805  if (!array->HasFastElements()) {
6806    return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6807  }
6808  FixedArray* fixed_array = FixedArray::cast(array->elements());
6809  if (fixed_array->length() < array_length) {
6810    array_length = fixed_array->length();
6811  }
6812
6813  if (array_length == 0) {
6814    return isolate->heap()->empty_string();
6815  } else if (array_length == 1) {
6816    Object* first = fixed_array->get(0);
6817    if (first->IsString()) return first;
6818  }
6819
6820  int separator_length = separator->length();
6821  int max_nof_separators =
6822      (String::kMaxLength + separator_length - 1) / separator_length;
6823  if (max_nof_separators < (array_length - 1)) {
6824      isolate->context()->mark_out_of_memory();
6825      return Failure::OutOfMemoryException();
6826  }
6827  int length = (array_length - 1) * separator_length;
6828  for (int i = 0; i < array_length; i++) {
6829    Object* element_obj = fixed_array->get(i);
6830    if (!element_obj->IsString()) {
6831      // TODO(1161): handle this case.
6832      return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6833    }
6834    String* element = String::cast(element_obj);
6835    int increment = element->length();
6836    if (increment > String::kMaxLength - length) {
6837      isolate->context()->mark_out_of_memory();
6838      return Failure::OutOfMemoryException();
6839    }
6840    length += increment;
6841  }
6842
6843  Object* object;
6844  { MaybeObject* maybe_object =
6845        isolate->heap()->AllocateRawTwoByteString(length);
6846    if (!maybe_object->ToObject(&object)) return maybe_object;
6847  }
6848  SeqTwoByteString* answer = SeqTwoByteString::cast(object);
6849
6850  uc16* sink = answer->GetChars();
6851#ifdef DEBUG
6852  uc16* end = sink + length;
6853#endif
6854
6855  String* first = String::cast(fixed_array->get(0));
6856  int first_length = first->length();
6857  String::WriteToFlat(first, sink, 0, first_length);
6858  sink += first_length;
6859
6860  for (int i = 1; i < array_length; i++) {
6861    ASSERT(sink + separator_length <= end);
6862    String::WriteToFlat(separator, sink, 0, separator_length);
6863    sink += separator_length;
6864
6865    String* element = String::cast(fixed_array->get(i));
6866    int element_length = element->length();
6867    ASSERT(sink + element_length <= end);
6868    String::WriteToFlat(element, sink, 0, element_length);
6869    sink += element_length;
6870  }
6871  ASSERT(sink == end);
6872
6873  ASSERT(!answer->HasOnlyAsciiChars());  // Use %_FastAsciiArrayJoin instead.
6874  return answer;
6875}
6876
6877template <typename Char>
6878static void JoinSparseArrayWithSeparator(FixedArray* elements,
6879                                         int elements_length,
6880                                         uint32_t array_length,
6881                                         String* separator,
6882                                         Vector<Char> buffer) {
6883  int previous_separator_position = 0;
6884  int separator_length = separator->length();
6885  int cursor = 0;
6886  for (int i = 0; i < elements_length; i += 2) {
6887    int position = NumberToInt32(elements->get(i));
6888    String* string = String::cast(elements->get(i + 1));
6889    int string_length = string->length();
6890    if (string->length() > 0) {
6891      while (previous_separator_position < position) {
6892        String::WriteToFlat<Char>(separator, &buffer[cursor],
6893                                  0, separator_length);
6894        cursor += separator_length;
6895        previous_separator_position++;
6896      }
6897      String::WriteToFlat<Char>(string, &buffer[cursor],
6898                                0, string_length);
6899      cursor += string->length();
6900    }
6901  }
6902  if (separator_length > 0) {
6903    // Array length must be representable as a signed 32-bit number,
6904    // otherwise the total string length would have been too large.
6905    ASSERT(array_length <= 0x7fffffff);  // Is int32_t.
6906    int last_array_index = static_cast<int>(array_length - 1);
6907    while (previous_separator_position < last_array_index) {
6908      String::WriteToFlat<Char>(separator, &buffer[cursor],
6909                                0, separator_length);
6910      cursor += separator_length;
6911      previous_separator_position++;
6912    }
6913  }
6914  ASSERT(cursor <= buffer.length());
6915}
6916
6917
6918RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) {
6919  NoHandleAllocation ha;
6920  ASSERT(args.length() == 3);
6921  CONVERT_ARG_CHECKED(JSArray, elements_array, 0);
6922  RUNTIME_ASSERT(elements_array->HasFastElements() ||
6923                 elements_array->HasFastSmiOnlyElements());
6924  CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]);
6925  CONVERT_ARG_CHECKED(String, separator, 2);
6926  // elements_array is fast-mode JSarray of alternating positions
6927  // (increasing order) and strings.
6928  // array_length is length of original array (used to add separators);
6929  // separator is string to put between elements. Assumed to be non-empty.
6930
6931  // Find total length of join result.
6932  int string_length = 0;
6933  bool is_ascii = separator->IsAsciiRepresentation();
6934  int max_string_length;
6935  if (is_ascii) {
6936    max_string_length = SeqAsciiString::kMaxLength;
6937  } else {
6938    max_string_length = SeqTwoByteString::kMaxLength;
6939  }
6940  bool overflow = false;
6941  CONVERT_NUMBER_CHECKED(int, elements_length,
6942                         Int32, elements_array->length());
6943  RUNTIME_ASSERT((elements_length & 1) == 0);  // Even length.
6944  FixedArray* elements = FixedArray::cast(elements_array->elements());
6945  for (int i = 0; i < elements_length; i += 2) {
6946    RUNTIME_ASSERT(elements->get(i)->IsNumber());
6947    RUNTIME_ASSERT(elements->get(i + 1)->IsString());
6948    String* string = String::cast(elements->get(i + 1));
6949    int length = string->length();
6950    if (is_ascii && !string->IsAsciiRepresentation()) {
6951      is_ascii = false;
6952      max_string_length = SeqTwoByteString::kMaxLength;
6953    }
6954    if (length > max_string_length ||
6955        max_string_length - length < string_length) {
6956      overflow = true;
6957      break;
6958    }
6959    string_length += length;
6960  }
6961  int separator_length = separator->length();
6962  if (!overflow && separator_length > 0) {
6963    if (array_length <= 0x7fffffffu) {
6964      int separator_count = static_cast<int>(array_length) - 1;
6965      int remaining_length = max_string_length - string_length;
6966      if ((remaining_length / separator_length) >= separator_count) {
6967        string_length += separator_length * (array_length - 1);
6968      } else {
6969        // Not room for the separators within the maximal string length.
6970        overflow = true;
6971      }
6972    } else {
6973      // Nonempty separator and at least 2^31-1 separators necessary
6974      // means that the string is too large to create.
6975      STATIC_ASSERT(String::kMaxLength < 0x7fffffff);
6976      overflow = true;
6977    }
6978  }
6979  if (overflow) {
6980    // Throw OutOfMemory exception for creating too large a string.
6981    V8::FatalProcessOutOfMemory("Array join result too large.");
6982  }
6983
6984  if (is_ascii) {
6985    MaybeObject* result_allocation =
6986        isolate->heap()->AllocateRawAsciiString(string_length);
6987    if (result_allocation->IsFailure()) return result_allocation;
6988    SeqAsciiString* result_string =
6989        SeqAsciiString::cast(result_allocation->ToObjectUnchecked());
6990    JoinSparseArrayWithSeparator<char>(elements,
6991                                       elements_length,
6992                                       array_length,
6993                                       separator,
6994                                       Vector<char>(result_string->GetChars(),
6995                                                    string_length));
6996    return result_string;
6997  } else {
6998    MaybeObject* result_allocation =
6999        isolate->heap()->AllocateRawTwoByteString(string_length);
7000    if (result_allocation->IsFailure()) return result_allocation;
7001    SeqTwoByteString* result_string =
7002        SeqTwoByteString::cast(result_allocation->ToObjectUnchecked());
7003    JoinSparseArrayWithSeparator<uc16>(elements,
7004                                       elements_length,
7005                                       array_length,
7006                                       separator,
7007                                       Vector<uc16>(result_string->GetChars(),
7008                                                    string_length));
7009    return result_string;
7010  }
7011}
7012
7013
7014RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberOr) {
7015  NoHandleAllocation ha;
7016  ASSERT(args.length() == 2);
7017
7018  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7019  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7020  return isolate->heap()->NumberFromInt32(x | y);
7021}
7022
7023
7024RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAnd) {
7025  NoHandleAllocation ha;
7026  ASSERT(args.length() == 2);
7027
7028  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7029  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7030  return isolate->heap()->NumberFromInt32(x & y);
7031}
7032
7033
7034RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberXor) {
7035  NoHandleAllocation ha;
7036  ASSERT(args.length() == 2);
7037
7038  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7039  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7040  return isolate->heap()->NumberFromInt32(x ^ y);
7041}
7042
7043
7044RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberNot) {
7045  NoHandleAllocation ha;
7046  ASSERT(args.length() == 1);
7047
7048  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7049  return isolate->heap()->NumberFromInt32(~x);
7050}
7051
7052
7053RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShl) {
7054  NoHandleAllocation ha;
7055  ASSERT(args.length() == 2);
7056
7057  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7058  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7059  return isolate->heap()->NumberFromInt32(x << (y & 0x1f));
7060}
7061
7062
7063RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShr) {
7064  NoHandleAllocation ha;
7065  ASSERT(args.length() == 2);
7066
7067  CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
7068  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7069  return isolate->heap()->NumberFromUint32(x >> (y & 0x1f));
7070}
7071
7072
7073RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSar) {
7074  NoHandleAllocation ha;
7075  ASSERT(args.length() == 2);
7076
7077  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7078  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7079  return isolate->heap()->NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f));
7080}
7081
7082
7083RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberEquals) {
7084  NoHandleAllocation ha;
7085  ASSERT(args.length() == 2);
7086
7087  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7088  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7089  if (isnan(x)) return Smi::FromInt(NOT_EQUAL);
7090  if (isnan(y)) return Smi::FromInt(NOT_EQUAL);
7091  if (x == y) return Smi::FromInt(EQUAL);
7092  Object* result;
7093  if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
7094    result = Smi::FromInt(EQUAL);
7095  } else {
7096    result = Smi::FromInt(NOT_EQUAL);
7097  }
7098  return result;
7099}
7100
7101
7102RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) {
7103  NoHandleAllocation ha;
7104  ASSERT(args.length() == 2);
7105
7106  CONVERT_ARG_CHECKED(String, x, 0);
7107  CONVERT_ARG_CHECKED(String, y, 1);
7108
7109  bool not_equal = !x->Equals(y);
7110  // This is slightly convoluted because the value that signifies
7111  // equality is 0 and inequality is 1 so we have to negate the result
7112  // from String::Equals.
7113  ASSERT(not_equal == 0 || not_equal == 1);
7114  STATIC_CHECK(EQUAL == 0);
7115  STATIC_CHECK(NOT_EQUAL == 1);
7116  return Smi::FromInt(not_equal);
7117}
7118
7119
7120RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberCompare) {
7121  NoHandleAllocation ha;
7122  ASSERT(args.length() == 3);
7123
7124  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7125  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7126  if (isnan(x) || isnan(y)) return args[2];
7127  if (x == y) return Smi::FromInt(EQUAL);
7128  if (isless(x, y)) return Smi::FromInt(LESS);
7129  return Smi::FromInt(GREATER);
7130}
7131
7132
7133// Compare two Smis as if they were converted to strings and then
7134// compared lexicographically.
7135RUNTIME_FUNCTION(MaybeObject*, Runtime_SmiLexicographicCompare) {
7136  NoHandleAllocation ha;
7137  ASSERT(args.length() == 2);
7138  CONVERT_SMI_ARG_CHECKED(x_value, 0);
7139  CONVERT_SMI_ARG_CHECKED(y_value, 1);
7140
7141  // If the integers are equal so are the string representations.
7142  if (x_value == y_value) return Smi::FromInt(EQUAL);
7143
7144  // If one of the integers is zero the normal integer order is the
7145  // same as the lexicographic order of the string representations.
7146  if (x_value == 0 || y_value == 0)
7147    return Smi::FromInt(x_value < y_value ? LESS : GREATER);
7148
7149  // If only one of the integers is negative the negative number is
7150  // smallest because the char code of '-' is less than the char code
7151  // of any digit.  Otherwise, we make both values positive.
7152
7153  // Use unsigned values otherwise the logic is incorrect for -MIN_INT on
7154  // architectures using 32-bit Smis.
7155  uint32_t x_scaled = x_value;
7156  uint32_t y_scaled = y_value;
7157  if (x_value < 0 || y_value < 0) {
7158    if (y_value >= 0) return Smi::FromInt(LESS);
7159    if (x_value >= 0) return Smi::FromInt(GREATER);
7160    x_scaled = -x_value;
7161    y_scaled = -y_value;
7162  }
7163
7164  static const uint32_t kPowersOf10[] = {
7165    1, 10, 100, 1000, 10*1000, 100*1000,
7166    1000*1000, 10*1000*1000, 100*1000*1000,
7167    1000*1000*1000
7168  };
7169
7170  // If the integers have the same number of decimal digits they can be
7171  // compared directly as the numeric order is the same as the
7172  // lexicographic order.  If one integer has fewer digits, it is scaled
7173  // by some power of 10 to have the same number of digits as the longer
7174  // integer.  If the scaled integers are equal it means the shorter
7175  // integer comes first in the lexicographic order.
7176
7177  // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
7178  int x_log2 = IntegerLog2(x_scaled);
7179  int x_log10 = ((x_log2 + 1) * 1233) >> 12;
7180  x_log10 -= x_scaled < kPowersOf10[x_log10];
7181
7182  int y_log2 = IntegerLog2(y_scaled);
7183  int y_log10 = ((y_log2 + 1) * 1233) >> 12;
7184  y_log10 -= y_scaled < kPowersOf10[y_log10];
7185
7186  int tie = EQUAL;
7187
7188  if (x_log10 < y_log10) {
7189    // X has fewer digits.  We would like to simply scale up X but that
7190    // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would
7191    // be scaled up to 9_000_000_000. So we scale up by the next
7192    // smallest power and scale down Y to drop one digit. It is OK to
7193    // drop one digit from the longer integer since the final digit is
7194    // past the length of the shorter integer.
7195    x_scaled *= kPowersOf10[y_log10 - x_log10 - 1];
7196    y_scaled /= 10;
7197    tie = LESS;
7198  } else if (y_log10 < x_log10) {
7199    y_scaled *= kPowersOf10[x_log10 - y_log10 - 1];
7200    x_scaled /= 10;
7201    tie = GREATER;
7202  }
7203
7204  if (x_scaled < y_scaled) return Smi::FromInt(LESS);
7205  if (x_scaled > y_scaled) return Smi::FromInt(GREATER);
7206  return Smi::FromInt(tie);
7207}
7208
7209
7210static Object* StringInputBufferCompare(RuntimeState* state,
7211                                        String* x,
7212                                        String* y) {
7213  StringInputBuffer& bufx = *state->string_input_buffer_compare_bufx();
7214  StringInputBuffer& bufy = *state->string_input_buffer_compare_bufy();
7215  bufx.Reset(x);
7216  bufy.Reset(y);
7217  while (bufx.has_more() && bufy.has_more()) {
7218    int d = bufx.GetNext() - bufy.GetNext();
7219    if (d < 0) return Smi::FromInt(LESS);
7220    else if (d > 0) return Smi::FromInt(GREATER);
7221  }
7222
7223  // x is (non-trivial) prefix of y:
7224  if (bufy.has_more()) return Smi::FromInt(LESS);
7225  // y is prefix of x:
7226  return Smi::FromInt(bufx.has_more() ? GREATER : EQUAL);
7227}
7228
7229
7230static Object* FlatStringCompare(String* x, String* y) {
7231  ASSERT(x->IsFlat());
7232  ASSERT(y->IsFlat());
7233  Object* equal_prefix_result = Smi::FromInt(EQUAL);
7234  int prefix_length = x->length();
7235  if (y->length() < prefix_length) {
7236    prefix_length = y->length();
7237    equal_prefix_result = Smi::FromInt(GREATER);
7238  } else if (y->length() > prefix_length) {
7239    equal_prefix_result = Smi::FromInt(LESS);
7240  }
7241  int r;
7242  String::FlatContent x_content = x->GetFlatContent();
7243  String::FlatContent y_content = y->GetFlatContent();
7244  if (x_content.IsAscii()) {
7245    Vector<const char> x_chars = x_content.ToAsciiVector();
7246    if (y_content.IsAscii()) {
7247      Vector<const char> y_chars = y_content.ToAsciiVector();
7248      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7249    } else {
7250      Vector<const uc16> y_chars = y_content.ToUC16Vector();
7251      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7252    }
7253  } else {
7254    Vector<const uc16> x_chars = x_content.ToUC16Vector();
7255    if (y_content.IsAscii()) {
7256      Vector<const char> y_chars = y_content.ToAsciiVector();
7257      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7258    } else {
7259      Vector<const uc16> y_chars = y_content.ToUC16Vector();
7260      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7261    }
7262  }
7263  Object* result;
7264  if (r == 0) {
7265    result = equal_prefix_result;
7266  } else {
7267    result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
7268  }
7269  ASSERT(result ==
7270      StringInputBufferCompare(Isolate::Current()->runtime_state(), x, y));
7271  return result;
7272}
7273
7274
7275RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCompare) {
7276  NoHandleAllocation ha;
7277  ASSERT(args.length() == 2);
7278
7279  CONVERT_ARG_CHECKED(String, x, 0);
7280  CONVERT_ARG_CHECKED(String, y, 1);
7281
7282  isolate->counters()->string_compare_runtime()->Increment();
7283
7284  // A few fast case tests before we flatten.
7285  if (x == y) return Smi::FromInt(EQUAL);
7286  if (y->length() == 0) {
7287    if (x->length() == 0) return Smi::FromInt(EQUAL);
7288    return Smi::FromInt(GREATER);
7289  } else if (x->length() == 0) {
7290    return Smi::FromInt(LESS);
7291  }
7292
7293  int d = x->Get(0) - y->Get(0);
7294  if (d < 0) return Smi::FromInt(LESS);
7295  else if (d > 0) return Smi::FromInt(GREATER);
7296
7297  Object* obj;
7298  { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(x);
7299    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7300  }
7301  { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(y);
7302    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7303  }
7304
7305  return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
7306      : StringInputBufferCompare(isolate->runtime_state(), x, y);
7307}
7308
7309
7310RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_acos) {
7311  NoHandleAllocation ha;
7312  ASSERT(args.length() == 1);
7313  isolate->counters()->math_acos()->Increment();
7314
7315  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7316  return isolate->transcendental_cache()->Get(TranscendentalCache::ACOS, x);
7317}
7318
7319
7320RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_asin) {
7321  NoHandleAllocation ha;
7322  ASSERT(args.length() == 1);
7323  isolate->counters()->math_asin()->Increment();
7324
7325  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7326  return isolate->transcendental_cache()->Get(TranscendentalCache::ASIN, x);
7327}
7328
7329
7330RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan) {
7331  NoHandleAllocation ha;
7332  ASSERT(args.length() == 1);
7333  isolate->counters()->math_atan()->Increment();
7334
7335  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7336  return isolate->transcendental_cache()->Get(TranscendentalCache::ATAN, x);
7337}
7338
7339
7340static const double kPiDividedBy4 = 0.78539816339744830962;
7341
7342
7343RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan2) {
7344  NoHandleAllocation ha;
7345  ASSERT(args.length() == 2);
7346  isolate->counters()->math_atan2()->Increment();
7347
7348  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7349  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7350  double result;
7351  if (isinf(x) && isinf(y)) {
7352    // Make sure that the result in case of two infinite arguments
7353    // is a multiple of Pi / 4. The sign of the result is determined
7354    // by the first argument (x) and the sign of the second argument
7355    // determines the multiplier: one or three.
7356    int multiplier = (x < 0) ? -1 : 1;
7357    if (y < 0) multiplier *= 3;
7358    result = multiplier * kPiDividedBy4;
7359  } else {
7360    result = atan2(x, y);
7361  }
7362  return isolate->heap()->AllocateHeapNumber(result);
7363}
7364
7365
7366RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_ceil) {
7367  NoHandleAllocation ha;
7368  ASSERT(args.length() == 1);
7369  isolate->counters()->math_ceil()->Increment();
7370
7371  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7372  return isolate->heap()->NumberFromDouble(ceiling(x));
7373}
7374
7375
7376RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_cos) {
7377  NoHandleAllocation ha;
7378  ASSERT(args.length() == 1);
7379  isolate->counters()->math_cos()->Increment();
7380
7381  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7382  return isolate->transcendental_cache()->Get(TranscendentalCache::COS, x);
7383}
7384
7385
7386RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_exp) {
7387  NoHandleAllocation ha;
7388  ASSERT(args.length() == 1);
7389  isolate->counters()->math_exp()->Increment();
7390
7391  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7392  return isolate->transcendental_cache()->Get(TranscendentalCache::EXP, x);
7393}
7394
7395
7396RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_floor) {
7397  NoHandleAllocation ha;
7398  ASSERT(args.length() == 1);
7399  isolate->counters()->math_floor()->Increment();
7400
7401  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7402  return isolate->heap()->NumberFromDouble(floor(x));
7403}
7404
7405
7406RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_log) {
7407  NoHandleAllocation ha;
7408  ASSERT(args.length() == 1);
7409  isolate->counters()->math_log()->Increment();
7410
7411  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7412  return isolate->transcendental_cache()->Get(TranscendentalCache::LOG, x);
7413}
7414
7415// Slow version of Math.pow.  We check for fast paths for special cases.
7416// Used if SSE2/VFP3 is not available.
7417RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow) {
7418  NoHandleAllocation ha;
7419  ASSERT(args.length() == 2);
7420  isolate->counters()->math_pow()->Increment();
7421
7422  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7423
7424  // If the second argument is a smi, it is much faster to call the
7425  // custom powi() function than the generic pow().
7426  if (args[1]->IsSmi()) {
7427    int y = args.smi_at(1);
7428    return isolate->heap()->NumberFromDouble(power_double_int(x, y));
7429  }
7430
7431  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7432  int y_int = static_cast<int>(y);
7433  double result;
7434  if (y == y_int) {
7435    result = power_double_int(x, y_int);  // Returns 1 if exponent is 0.
7436  } else  if (y == 0.5) {
7437    result = (isinf(x)) ? V8_INFINITY
7438                        : fast_sqrt(x + 0.0);  // Convert -0 to +0.
7439  } else if (y == -0.5) {
7440    result = (isinf(x)) ? 0
7441                        : 1.0 / fast_sqrt(x + 0.0);  // Convert -0 to +0.
7442  } else {
7443    result = power_double_double(x, y);
7444  }
7445  if (isnan(result)) return isolate->heap()->nan_value();
7446  return isolate->heap()->AllocateHeapNumber(result);
7447}
7448
7449// Fast version of Math.pow if we know that y is not an integer and y is not
7450// -0.5 or 0.5.  Used as slow case from full codegen.
7451RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow_cfunction) {
7452  NoHandleAllocation ha;
7453  ASSERT(args.length() == 2);
7454  isolate->counters()->math_pow()->Increment();
7455
7456  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7457  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7458  if (y == 0) {
7459    return Smi::FromInt(1);
7460  } else {
7461    double result = power_double_double(x, y);
7462    if (isnan(result)) return isolate->heap()->nan_value();
7463    return isolate->heap()->AllocateHeapNumber(result);
7464  }
7465}
7466
7467
7468RUNTIME_FUNCTION(MaybeObject*, Runtime_RoundNumber) {
7469  NoHandleAllocation ha;
7470  ASSERT(args.length() == 1);
7471  isolate->counters()->math_round()->Increment();
7472
7473  if (!args[0]->IsHeapNumber()) {
7474    // Must be smi. Return the argument unchanged for all the other types
7475    // to make fuzz-natives test happy.
7476    return args[0];
7477  }
7478
7479  HeapNumber* number = reinterpret_cast<HeapNumber*>(args[0]);
7480
7481  double value = number->value();
7482  int exponent = number->get_exponent();
7483  int sign = number->get_sign();
7484
7485  if (exponent < -1) {
7486    // Number in range ]-0.5..0.5[. These always round to +/-zero.
7487    if (sign) return isolate->heap()->minus_zero_value();
7488    return Smi::FromInt(0);
7489  }
7490
7491  // We compare with kSmiValueSize - 2 because (2^30 - 0.1) has exponent 29 and
7492  // should be rounded to 2^30, which is not smi (for 31-bit smis, similar
7493  // argument holds for 32-bit smis).
7494  if (!sign && exponent < kSmiValueSize - 2) {
7495    return Smi::FromInt(static_cast<int>(value + 0.5));
7496  }
7497
7498  // If the magnitude is big enough, there's no place for fraction part. If we
7499  // try to add 0.5 to this number, 1.0 will be added instead.
7500  if (exponent >= 52) {
7501    return number;
7502  }
7503
7504  if (sign && value >= -0.5) return isolate->heap()->minus_zero_value();
7505
7506  // Do not call NumberFromDouble() to avoid extra checks.
7507  return isolate->heap()->AllocateHeapNumber(floor(value + 0.5));
7508}
7509
7510
7511RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sin) {
7512  NoHandleAllocation ha;
7513  ASSERT(args.length() == 1);
7514  isolate->counters()->math_sin()->Increment();
7515
7516  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7517  return isolate->transcendental_cache()->Get(TranscendentalCache::SIN, x);
7518}
7519
7520
7521RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sqrt) {
7522  NoHandleAllocation ha;
7523  ASSERT(args.length() == 1);
7524  isolate->counters()->math_sqrt()->Increment();
7525
7526  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7527  return isolate->heap()->AllocateHeapNumber(fast_sqrt(x));
7528}
7529
7530
7531RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_tan) {
7532  NoHandleAllocation ha;
7533  ASSERT(args.length() == 1);
7534  isolate->counters()->math_tan()->Increment();
7535
7536  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7537  return isolate->transcendental_cache()->Get(TranscendentalCache::TAN, x);
7538}
7539
7540
7541RUNTIME_FUNCTION(MaybeObject*, Runtime_DateMakeDay) {
7542  NoHandleAllocation ha;
7543  ASSERT(args.length() == 2);
7544
7545  CONVERT_SMI_ARG_CHECKED(year, 0);
7546  CONVERT_SMI_ARG_CHECKED(month, 1);
7547
7548  return Smi::FromInt(isolate->date_cache()->DaysFromYearMonth(year, month));
7549}
7550
7551
7552RUNTIME_FUNCTION(MaybeObject*, Runtime_DateSetValue) {
7553  HandleScope scope(isolate);
7554  ASSERT(args.length() == 3);
7555
7556  CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 0);
7557  CONVERT_DOUBLE_ARG_CHECKED(time, 1);
7558  CONVERT_SMI_ARG_CHECKED(is_utc, 2);
7559
7560  DateCache* date_cache = isolate->date_cache();
7561
7562  Object* value = NULL;
7563  bool is_value_nan = false;
7564  if (isnan(time)) {
7565    value = isolate->heap()->nan_value();
7566    is_value_nan = true;
7567  } else if (!is_utc &&
7568             (time < -DateCache::kMaxTimeBeforeUTCInMs ||
7569              time > DateCache::kMaxTimeBeforeUTCInMs)) {
7570    value = isolate->heap()->nan_value();
7571    is_value_nan = true;
7572  } else {
7573    time = is_utc ? time : date_cache->ToUTC(static_cast<int64_t>(time));
7574    if (time < -DateCache::kMaxTimeInMs ||
7575        time > DateCache::kMaxTimeInMs) {
7576      value = isolate->heap()->nan_value();
7577      is_value_nan = true;
7578    } else  {
7579      MaybeObject* maybe_result =
7580          isolate->heap()->AllocateHeapNumber(DoubleToInteger(time));
7581      if (!maybe_result->ToObject(&value)) return maybe_result;
7582    }
7583  }
7584  date->SetValue(value, is_value_nan);
7585  return value;
7586}
7587
7588
7589RUNTIME_FUNCTION(MaybeObject*, Runtime_NewArgumentsFast) {
7590  HandleScope scope(isolate);
7591  ASSERT(args.length() == 3);
7592
7593  Handle<JSFunction> callee = args.at<JSFunction>(0);
7594  Object** parameters = reinterpret_cast<Object**>(args[1]);
7595  const int argument_count = Smi::cast(args[2])->value();
7596
7597  Handle<JSObject> result =
7598      isolate->factory()->NewArgumentsObject(callee, argument_count);
7599  // Allocate the elements if needed.
7600  int parameter_count = callee->shared()->formal_parameter_count();
7601  if (argument_count > 0) {
7602    if (parameter_count > 0) {
7603      int mapped_count = Min(argument_count, parameter_count);
7604      Handle<FixedArray> parameter_map =
7605          isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
7606      parameter_map->set_map(
7607          isolate->heap()->non_strict_arguments_elements_map());
7608
7609      Handle<Map> old_map(result->map());
7610      Handle<Map> new_map =
7611          isolate->factory()->CopyMapDropTransitions(old_map);
7612      new_map->set_elements_kind(NON_STRICT_ARGUMENTS_ELEMENTS);
7613
7614      result->set_map(*new_map);
7615      result->set_elements(*parameter_map);
7616
7617      // Store the context and the arguments array at the beginning of the
7618      // parameter map.
7619      Handle<Context> context(isolate->context());
7620      Handle<FixedArray> arguments =
7621          isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
7622      parameter_map->set(0, *context);
7623      parameter_map->set(1, *arguments);
7624
7625      // Loop over the actual parameters backwards.
7626      int index = argument_count - 1;
7627      while (index >= mapped_count) {
7628        // These go directly in the arguments array and have no
7629        // corresponding slot in the parameter map.
7630        arguments->set(index, *(parameters - index - 1));
7631        --index;
7632      }
7633
7634      Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
7635      while (index >= 0) {
7636        // Detect duplicate names to the right in the parameter list.
7637        Handle<String> name(scope_info->ParameterName(index));
7638        int context_local_count = scope_info->ContextLocalCount();
7639        bool duplicate = false;
7640        for (int j = index + 1; j < parameter_count; ++j) {
7641          if (scope_info->ParameterName(j) == *name) {
7642            duplicate = true;
7643            break;
7644          }
7645        }
7646
7647        if (duplicate) {
7648          // This goes directly in the arguments array with a hole in the
7649          // parameter map.
7650          arguments->set(index, *(parameters - index - 1));
7651          parameter_map->set_the_hole(index + 2);
7652        } else {
7653          // The context index goes in the parameter map with a hole in the
7654          // arguments array.
7655          int context_index = -1;
7656          for (int j = 0; j < context_local_count; ++j) {
7657            if (scope_info->ContextLocalName(j) == *name) {
7658              context_index = j;
7659              break;
7660            }
7661          }
7662          ASSERT(context_index >= 0);
7663          arguments->set_the_hole(index);
7664          parameter_map->set(index + 2, Smi::FromInt(
7665              Context::MIN_CONTEXT_SLOTS + context_index));
7666        }
7667
7668        --index;
7669      }
7670    } else {
7671      // If there is no aliasing, the arguments object elements are not
7672      // special in any way.
7673      Handle<FixedArray> elements =
7674          isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
7675      result->set_elements(*elements);
7676      for (int i = 0; i < argument_count; ++i) {
7677        elements->set(i, *(parameters - i - 1));
7678      }
7679    }
7680  }
7681  return *result;
7682}
7683
7684
7685RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStrictArgumentsFast) {
7686  NoHandleAllocation ha;
7687  ASSERT(args.length() == 3);
7688
7689  JSFunction* callee = JSFunction::cast(args[0]);
7690  Object** parameters = reinterpret_cast<Object**>(args[1]);
7691  const int length = args.smi_at(2);
7692
7693  Object* result;
7694  { MaybeObject* maybe_result =
7695        isolate->heap()->AllocateArgumentsObject(callee, length);
7696    if (!maybe_result->ToObject(&result)) return maybe_result;
7697  }
7698  // Allocate the elements if needed.
7699  if (length > 0) {
7700    // Allocate the fixed array.
7701    Object* obj;
7702    { MaybeObject* maybe_obj = isolate->heap()->AllocateRawFixedArray(length);
7703      if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7704    }
7705
7706    AssertNoAllocation no_gc;
7707    FixedArray* array = reinterpret_cast<FixedArray*>(obj);
7708    array->set_map_no_write_barrier(isolate->heap()->fixed_array_map());
7709    array->set_length(length);
7710
7711    WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
7712    for (int i = 0; i < length; i++) {
7713      array->set(i, *--parameters, mode);
7714    }
7715    JSObject::cast(result)->set_elements(FixedArray::cast(obj));
7716  }
7717  return result;
7718}
7719
7720
7721RUNTIME_FUNCTION(MaybeObject*, Runtime_NewClosure) {
7722  HandleScope scope(isolate);
7723  ASSERT(args.length() == 3);
7724  CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
7725  CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 1);
7726  CONVERT_BOOLEAN_ARG_CHECKED(pretenure, 2);
7727
7728  // The caller ensures that we pretenure closures that are assigned
7729  // directly to properties.
7730  PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
7731  Handle<JSFunction> result =
7732      isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
7733                                                            context,
7734                                                            pretenure_flag);
7735  return *result;
7736}
7737
7738
7739// Find the arguments of the JavaScript function invocation that called
7740// into C++ code. Collect these in a newly allocated array of handles (possibly
7741// prefixed by a number of empty handles).
7742static SmartArrayPointer<Handle<Object> > GetCallerArguments(
7743    int prefix_argc,
7744    int* total_argc) {
7745  // Find frame containing arguments passed to the caller.
7746  JavaScriptFrameIterator it;
7747  JavaScriptFrame* frame = it.frame();
7748  List<JSFunction*> functions(2);
7749  frame->GetFunctions(&functions);
7750  if (functions.length() > 1) {
7751    int inlined_jsframe_index = functions.length() - 1;
7752    JSFunction* inlined_function = functions[inlined_jsframe_index];
7753    Vector<SlotRef> args_slots =
7754        SlotRef::ComputeSlotMappingForArguments(
7755            frame,
7756            inlined_jsframe_index,
7757            inlined_function->shared()->formal_parameter_count());
7758
7759    int args_count = args_slots.length();
7760
7761    *total_argc = prefix_argc + args_count;
7762    SmartArrayPointer<Handle<Object> > param_data(
7763        NewArray<Handle<Object> >(*total_argc));
7764    for (int i = 0; i < args_count; i++) {
7765      Handle<Object> val = args_slots[i].GetValue();
7766      param_data[prefix_argc + i] = val;
7767    }
7768
7769    args_slots.Dispose();
7770
7771    return param_data;
7772  } else {
7773    it.AdvanceToArgumentsFrame();
7774    frame = it.frame();
7775    int args_count = frame->ComputeParametersCount();
7776
7777    *total_argc = prefix_argc + args_count;
7778    SmartArrayPointer<Handle<Object> > param_data(
7779        NewArray<Handle<Object> >(*total_argc));
7780    for (int i = 0; i < args_count; i++) {
7781      Handle<Object> val = Handle<Object>(frame->GetParameter(i));
7782      param_data[prefix_argc + i] = val;
7783    }
7784    return param_data;
7785  }
7786}
7787
7788
7789RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionBindArguments) {
7790  HandleScope scope(isolate);
7791  ASSERT(args.length() == 4);
7792  CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0);
7793  RUNTIME_ASSERT(args[3]->IsNumber());
7794  Handle<Object> bindee = args.at<Object>(1);
7795
7796  // TODO(lrn): Create bound function in C++ code from premade shared info.
7797  bound_function->shared()->set_bound(true);
7798  // Get all arguments of calling function (Function.prototype.bind).
7799  int argc = 0;
7800  SmartArrayPointer<Handle<Object> > arguments = GetCallerArguments(0, &argc);
7801  // Don't count the this-arg.
7802  if (argc > 0) {
7803    ASSERT(*arguments[0] == args[2]);
7804    argc--;
7805  } else {
7806    ASSERT(args[2]->IsUndefined());
7807  }
7808  // Initialize array of bindings (function, this, and any existing arguments
7809  // if the function was already bound).
7810  Handle<FixedArray> new_bindings;
7811  int i;
7812  if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) {
7813    Handle<FixedArray> old_bindings(
7814        JSFunction::cast(*bindee)->function_bindings());
7815    new_bindings =
7816        isolate->factory()->NewFixedArray(old_bindings->length() + argc);
7817    bindee = Handle<Object>(old_bindings->get(JSFunction::kBoundFunctionIndex));
7818    i = 0;
7819    for (int n = old_bindings->length(); i < n; i++) {
7820      new_bindings->set(i, old_bindings->get(i));
7821    }
7822  } else {
7823    int array_size = JSFunction::kBoundArgumentsStartIndex + argc;
7824    new_bindings = isolate->factory()->NewFixedArray(array_size);
7825    new_bindings->set(JSFunction::kBoundFunctionIndex, *bindee);
7826    new_bindings->set(JSFunction::kBoundThisIndex, args[2]);
7827    i = 2;
7828  }
7829  // Copy arguments, skipping the first which is "this_arg".
7830  for (int j = 0; j < argc; j++, i++) {
7831    new_bindings->set(i, *arguments[j + 1]);
7832  }
7833  new_bindings->set_map_no_write_barrier(
7834      isolate->heap()->fixed_cow_array_map());
7835  bound_function->set_function_bindings(*new_bindings);
7836
7837  // Update length.
7838  Handle<String> length_symbol = isolate->factory()->length_symbol();
7839  Handle<Object> new_length(args.at<Object>(3));
7840  PropertyAttributes attr =
7841      static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY);
7842  ForceSetProperty(bound_function, length_symbol, new_length, attr);
7843  return *bound_function;
7844}
7845
7846
7847RUNTIME_FUNCTION(MaybeObject*, Runtime_BoundFunctionGetBindings) {
7848  HandleScope handles(isolate);
7849  ASSERT(args.length() == 1);
7850  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0);
7851  if (callable->IsJSFunction()) {
7852    Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
7853    if (function->shared()->bound()) {
7854      Handle<FixedArray> bindings(function->function_bindings());
7855      ASSERT(bindings->map() == isolate->heap()->fixed_cow_array_map());
7856      return *isolate->factory()->NewJSArrayWithElements(bindings);
7857    }
7858  }
7859  return isolate->heap()->undefined_value();
7860}
7861
7862
7863RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObjectFromBound) {
7864  HandleScope scope(isolate);
7865  ASSERT(args.length() == 1);
7866  // First argument is a function to use as a constructor.
7867  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
7868  RUNTIME_ASSERT(function->shared()->bound());
7869
7870  // The argument is a bound function. Extract its bound arguments
7871  // and callable.
7872  Handle<FixedArray> bound_args =
7873      Handle<FixedArray>(FixedArray::cast(function->function_bindings()));
7874  int bound_argc = bound_args->length() - JSFunction::kBoundArgumentsStartIndex;
7875  Handle<Object> bound_function(
7876      JSReceiver::cast(bound_args->get(JSFunction::kBoundFunctionIndex)));
7877  ASSERT(!bound_function->IsJSFunction() ||
7878         !Handle<JSFunction>::cast(bound_function)->shared()->bound());
7879
7880  int total_argc = 0;
7881  SmartArrayPointer<Handle<Object> > param_data =
7882      GetCallerArguments(bound_argc, &total_argc);
7883  for (int i = 0; i < bound_argc; i++) {
7884    param_data[i] = Handle<Object>(bound_args->get(
7885        JSFunction::kBoundArgumentsStartIndex + i));
7886  }
7887
7888  if (!bound_function->IsJSFunction()) {
7889    bool exception_thrown;
7890    bound_function = Execution::TryGetConstructorDelegate(bound_function,
7891                                                          &exception_thrown);
7892    if (exception_thrown) return Failure::Exception();
7893  }
7894  ASSERT(bound_function->IsJSFunction());
7895
7896  bool exception = false;
7897  Handle<Object> result =
7898      Execution::New(Handle<JSFunction>::cast(bound_function),
7899                     total_argc, *param_data, &exception);
7900  if (exception) {
7901    return Failure::Exception();
7902  }
7903  ASSERT(!result.is_null());
7904  return *result;
7905}
7906
7907
7908static void TrySettingInlineConstructStub(Isolate* isolate,
7909                                          Handle<JSFunction> function) {
7910  Handle<Object> prototype = isolate->factory()->null_value();
7911  if (function->has_instance_prototype()) {
7912    prototype = Handle<Object>(function->instance_prototype(), isolate);
7913  }
7914  if (function->shared()->CanGenerateInlineConstructor(*prototype)) {
7915    ConstructStubCompiler compiler(isolate);
7916    Handle<Code> code = compiler.CompileConstructStub(function);
7917    function->shared()->set_construct_stub(*code);
7918  }
7919}
7920
7921
7922RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObject) {
7923  HandleScope scope(isolate);
7924  ASSERT(args.length() == 1);
7925
7926  Handle<Object> constructor = args.at<Object>(0);
7927
7928  // If the constructor isn't a proper function we throw a type error.
7929  if (!constructor->IsJSFunction()) {
7930    Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
7931    Handle<Object> type_error =
7932        isolate->factory()->NewTypeError("not_constructor", arguments);
7933    return isolate->Throw(*type_error);
7934  }
7935
7936  Handle<JSFunction> function = Handle<JSFunction>::cast(constructor);
7937
7938  // If function should not have prototype, construction is not allowed. In this
7939  // case generated code bailouts here, since function has no initial_map.
7940  if (!function->should_have_prototype() && !function->shared()->bound()) {
7941    Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
7942    Handle<Object> type_error =
7943        isolate->factory()->NewTypeError("not_constructor", arguments);
7944    return isolate->Throw(*type_error);
7945  }
7946
7947#ifdef ENABLE_DEBUGGER_SUPPORT
7948  Debug* debug = isolate->debug();
7949  // Handle stepping into constructors if step into is active.
7950  if (debug->StepInActive()) {
7951    debug->HandleStepIn(function, Handle<Object>::null(), 0, true);
7952  }
7953#endif
7954
7955  if (function->has_initial_map()) {
7956    if (function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
7957      // The 'Function' function ignores the receiver object when
7958      // called using 'new' and creates a new JSFunction object that
7959      // is returned.  The receiver object is only used for error
7960      // reporting if an error occurs when constructing the new
7961      // JSFunction. FACTORY->NewJSObject() should not be used to
7962      // allocate JSFunctions since it does not properly initialize
7963      // the shared part of the function. Since the receiver is
7964      // ignored anyway, we use the global object as the receiver
7965      // instead of a new JSFunction object. This way, errors are
7966      // reported the same way whether or not 'Function' is called
7967      // using 'new'.
7968      return isolate->context()->global();
7969    }
7970  }
7971
7972  // The function should be compiled for the optimization hints to be
7973  // available. We cannot use EnsureCompiled because that forces a
7974  // compilation through the shared function info which makes it
7975  // impossible for us to optimize.
7976  if (!function->is_compiled()) {
7977    JSFunction::CompileLazy(function, CLEAR_EXCEPTION);
7978  }
7979
7980  Handle<SharedFunctionInfo> shared(function->shared(), isolate);
7981  if (!function->has_initial_map() &&
7982      shared->IsInobjectSlackTrackingInProgress()) {
7983    // The tracking is already in progress for another function. We can only
7984    // track one initial_map at a time, so we force the completion before the
7985    // function is called as a constructor for the first time.
7986    shared->CompleteInobjectSlackTracking();
7987  }
7988
7989  bool first_allocation = !shared->live_objects_may_exist();
7990  Handle<JSObject> result = isolate->factory()->NewJSObject(function);
7991  RETURN_IF_EMPTY_HANDLE(isolate, result);
7992  // Delay setting the stub if inobject slack tracking is in progress.
7993  if (first_allocation && !shared->IsInobjectSlackTrackingInProgress()) {
7994    TrySettingInlineConstructStub(isolate, function);
7995  }
7996
7997  isolate->counters()->constructed_objects()->Increment();
7998  isolate->counters()->constructed_objects_runtime()->Increment();
7999
8000  return *result;
8001}
8002
8003
8004RUNTIME_FUNCTION(MaybeObject*, Runtime_FinalizeInstanceSize) {
8005  HandleScope scope(isolate);
8006  ASSERT(args.length() == 1);
8007
8008  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8009  function->shared()->CompleteInobjectSlackTracking();
8010  TrySettingInlineConstructStub(isolate, function);
8011
8012  return isolate->heap()->undefined_value();
8013}
8014
8015
8016RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyCompile) {
8017  HandleScope scope(isolate);
8018  ASSERT(args.length() == 1);
8019
8020  Handle<JSFunction> function = args.at<JSFunction>(0);
8021#ifdef DEBUG
8022  if (FLAG_trace_lazy && !function->shared()->is_compiled()) {
8023    PrintF("[lazy: ");
8024    function->PrintName();
8025    PrintF("]\n");
8026  }
8027#endif
8028
8029  // Compile the target function.
8030  ASSERT(!function->is_compiled());
8031  if (!JSFunction::CompileLazy(function, KEEP_EXCEPTION)) {
8032    return Failure::Exception();
8033  }
8034
8035  // All done. Return the compiled code.
8036  ASSERT(function->is_compiled());
8037  return function->code();
8038}
8039
8040
8041RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyRecompile) {
8042  HandleScope scope(isolate);
8043  ASSERT(args.length() == 1);
8044  Handle<JSFunction> function = args.at<JSFunction>(0);
8045
8046  // If the function is not compiled ignore the lazy
8047  // recompilation. This can happen if the debugger is activated and
8048  // the function is returned to the not compiled state.
8049  if (!function->shared()->is_compiled()) {
8050    function->ReplaceCode(function->shared()->code());
8051    return function->code();
8052  }
8053
8054  // If the function is not optimizable or debugger is active continue using the
8055  // code from the full compiler.
8056  if (!function->shared()->code()->optimizable() ||
8057      isolate->DebuggerHasBreakPoints()) {
8058    if (FLAG_trace_opt) {
8059      PrintF("[failed to optimize ");
8060      function->PrintName();
8061      PrintF(": is code optimizable: %s, is debugger enabled: %s]\n",
8062          function->shared()->code()->optimizable() ? "T" : "F",
8063          isolate->DebuggerHasBreakPoints() ? "T" : "F");
8064    }
8065    function->ReplaceCode(function->shared()->code());
8066    return function->code();
8067  }
8068  function->shared()->code()->set_profiler_ticks(0);
8069  if (JSFunction::CompileOptimized(function,
8070                                   AstNode::kNoNumber,
8071                                   CLEAR_EXCEPTION)) {
8072    return function->code();
8073  }
8074  if (FLAG_trace_opt) {
8075    PrintF("[failed to optimize ");
8076    function->PrintName();
8077    PrintF(": optimized compilation failed]\n");
8078  }
8079  function->ReplaceCode(function->shared()->code());
8080  return function->code();
8081}
8082
8083
8084class ActivationsFinder : public ThreadVisitor {
8085 public:
8086  explicit ActivationsFinder(JSFunction* function)
8087      : function_(function), has_activations_(false) {}
8088
8089  void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
8090    if (has_activations_) return;
8091
8092    for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
8093      JavaScriptFrame* frame = it.frame();
8094      if (frame->is_optimized() && frame->function() == function_) {
8095        has_activations_ = true;
8096        return;
8097      }
8098    }
8099  }
8100
8101  bool has_activations() { return has_activations_; }
8102
8103 private:
8104  JSFunction* function_;
8105  bool has_activations_;
8106};
8107
8108
8109static void MaterializeArgumentsObjectInFrame(Isolate* isolate,
8110                                              JavaScriptFrame* frame) {
8111  Handle<JSFunction> function(JSFunction::cast(frame->function()), isolate);
8112  Handle<Object> arguments;
8113  for (int i = frame->ComputeExpressionsCount() - 1; i >= 0; --i) {
8114    if (frame->GetExpression(i) == isolate->heap()->arguments_marker()) {
8115      if (arguments.is_null()) {
8116        // FunctionGetArguments can't throw an exception, so cast away the
8117        // doubt with an assert.
8118        arguments = Handle<Object>(
8119            Accessors::FunctionGetArguments(*function,
8120                                            NULL)->ToObjectUnchecked());
8121        ASSERT(*arguments != isolate->heap()->null_value());
8122        ASSERT(*arguments != isolate->heap()->undefined_value());
8123      }
8124      frame->SetExpression(i, *arguments);
8125    }
8126  }
8127}
8128
8129
8130RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyDeoptimized) {
8131  HandleScope scope(isolate);
8132  ASSERT(args.length() == 1);
8133  RUNTIME_ASSERT(args[0]->IsSmi());
8134  Deoptimizer::BailoutType type =
8135      static_cast<Deoptimizer::BailoutType>(args.smi_at(0));
8136  Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8137  ASSERT(isolate->heap()->IsAllocationAllowed());
8138  int jsframes = deoptimizer->jsframe_count();
8139
8140  deoptimizer->MaterializeHeapNumbers();
8141  delete deoptimizer;
8142
8143  JavaScriptFrameIterator it(isolate);
8144  for (int i = 0; i < jsframes - 1; i++) {
8145    MaterializeArgumentsObjectInFrame(isolate, it.frame());
8146    it.Advance();
8147  }
8148
8149  JavaScriptFrame* frame = it.frame();
8150  RUNTIME_ASSERT(frame->function()->IsJSFunction());
8151  Handle<JSFunction> function(JSFunction::cast(frame->function()), isolate);
8152  MaterializeArgumentsObjectInFrame(isolate, frame);
8153
8154  if (type == Deoptimizer::EAGER) {
8155    RUNTIME_ASSERT(function->IsOptimized());
8156  }
8157
8158  // Avoid doing too much work when running with --always-opt and keep
8159  // the optimized code around.
8160  if (FLAG_always_opt || type == Deoptimizer::LAZY) {
8161    return isolate->heap()->undefined_value();
8162  }
8163
8164  // Find other optimized activations of the function.
8165  bool has_other_activations = false;
8166  while (!it.done()) {
8167    JavaScriptFrame* frame = it.frame();
8168    if (frame->is_optimized() && frame->function() == *function) {
8169      has_other_activations = true;
8170      break;
8171    }
8172    it.Advance();
8173  }
8174
8175  if (!has_other_activations) {
8176    ActivationsFinder activations_finder(*function);
8177    isolate->thread_manager()->IterateArchivedThreads(&activations_finder);
8178    has_other_activations = activations_finder.has_activations();
8179  }
8180
8181  if (!has_other_activations) {
8182    if (FLAG_trace_deopt) {
8183      PrintF("[removing optimized code for: ");
8184      function->PrintName();
8185      PrintF("]\n");
8186    }
8187    function->ReplaceCode(function->shared()->code());
8188  } else {
8189    Deoptimizer::DeoptimizeFunction(*function);
8190  }
8191  return isolate->heap()->undefined_value();
8192}
8193
8194
8195RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyOSR) {
8196  Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8197  delete deoptimizer;
8198  return isolate->heap()->undefined_value();
8199}
8200
8201
8202RUNTIME_FUNCTION(MaybeObject*, Runtime_DeoptimizeFunction) {
8203  HandleScope scope(isolate);
8204  ASSERT(args.length() == 1);
8205  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8206  if (!function->IsOptimized()) return isolate->heap()->undefined_value();
8207
8208  Deoptimizer::DeoptimizeFunction(*function);
8209
8210  return isolate->heap()->undefined_value();
8211}
8212
8213
8214RUNTIME_FUNCTION(MaybeObject*, Runtime_RunningInSimulator) {
8215#if defined(USE_SIMULATOR)
8216  return isolate->heap()->true_value();
8217#else
8218  return isolate->heap()->false_value();
8219#endif
8220}
8221
8222
8223RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) {
8224  HandleScope scope(isolate);
8225  RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
8226  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8227
8228  if (!function->IsOptimizable()) return isolate->heap()->undefined_value();
8229  function->MarkForLazyRecompilation();
8230
8231  Code* unoptimized = function->shared()->code();
8232  if (args.length() == 2 &&
8233      unoptimized->kind() == Code::FUNCTION) {
8234    CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
8235    CHECK(type->IsEqualTo(CStrVector("osr")));
8236    isolate->runtime_profiler()->AttemptOnStackReplacement(*function);
8237    unoptimized->set_allow_osr_at_loop_nesting_level(
8238        Code::kMaxLoopNestingMarker);
8239  }
8240
8241  return isolate->heap()->undefined_value();
8242}
8243
8244
8245RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) {
8246  HandleScope scope(isolate);
8247  ASSERT(args.length() == 1);
8248  // The least significant bit (after untagging) indicates whether the
8249  // function is currently optimized, regardless of reason.
8250  if (!V8::UseCrankshaft()) {
8251    return Smi::FromInt(4);  // 4 == "never".
8252  }
8253  if (FLAG_always_opt) {
8254    return Smi::FromInt(3);  // 3 == "always".
8255  }
8256  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8257  return function->IsOptimized() ? Smi::FromInt(1)   // 1 == "yes".
8258                                 : Smi::FromInt(2);  // 2 == "no".
8259}
8260
8261
8262RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationCount) {
8263  HandleScope scope(isolate);
8264  ASSERT(args.length() == 1);
8265  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8266  return Smi::FromInt(function->shared()->opt_count());
8267}
8268
8269
8270RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
8271  HandleScope scope(isolate);
8272  ASSERT(args.length() == 1);
8273  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8274
8275  // We're not prepared to handle a function with arguments object.
8276  ASSERT(!function->shared()->uses_arguments());
8277
8278  // We have hit a back edge in an unoptimized frame for a function that was
8279  // selected for on-stack replacement.  Find the unoptimized code object.
8280  Handle<Code> unoptimized(function->shared()->code(), isolate);
8281  // Keep track of whether we've succeeded in optimizing.
8282  bool succeeded = unoptimized->optimizable();
8283  if (succeeded) {
8284    // If we are trying to do OSR when there are already optimized
8285    // activations of the function, it means (a) the function is directly or
8286    // indirectly recursive and (b) an optimized invocation has been
8287    // deoptimized so that we are currently in an unoptimized activation.
8288    // Check for optimized activations of this function.
8289    JavaScriptFrameIterator it(isolate);
8290    while (succeeded && !it.done()) {
8291      JavaScriptFrame* frame = it.frame();
8292      succeeded = !frame->is_optimized() || frame->function() != *function;
8293      it.Advance();
8294    }
8295  }
8296
8297  int ast_id = AstNode::kNoNumber;
8298  if (succeeded) {
8299    // The top JS function is this one, the PC is somewhere in the
8300    // unoptimized code.
8301    JavaScriptFrameIterator it(isolate);
8302    JavaScriptFrame* frame = it.frame();
8303    ASSERT(frame->function() == *function);
8304    ASSERT(frame->LookupCode() == *unoptimized);
8305    ASSERT(unoptimized->contains(frame->pc()));
8306
8307    // Use linear search of the unoptimized code's stack check table to find
8308    // the AST id matching the PC.
8309    Address start = unoptimized->instruction_start();
8310    unsigned target_pc_offset = static_cast<unsigned>(frame->pc() - start);
8311    Address table_cursor = start + unoptimized->stack_check_table_offset();
8312    uint32_t table_length = Memory::uint32_at(table_cursor);
8313    table_cursor += kIntSize;
8314    for (unsigned i = 0; i < table_length; ++i) {
8315      // Table entries are (AST id, pc offset) pairs.
8316      uint32_t pc_offset = Memory::uint32_at(table_cursor + kIntSize);
8317      if (pc_offset == target_pc_offset) {
8318        ast_id = static_cast<int>(Memory::uint32_at(table_cursor));
8319        break;
8320      }
8321      table_cursor += 2 * kIntSize;
8322    }
8323    ASSERT(ast_id != AstNode::kNoNumber);
8324    if (FLAG_trace_osr) {
8325      PrintF("[replacing on-stack at AST id %d in ", ast_id);
8326      function->PrintName();
8327      PrintF("]\n");
8328    }
8329
8330    // Try to compile the optimized code.  A true return value from
8331    // CompileOptimized means that compilation succeeded, not necessarily
8332    // that optimization succeeded.
8333    if (JSFunction::CompileOptimized(function, ast_id, CLEAR_EXCEPTION) &&
8334        function->IsOptimized()) {
8335      DeoptimizationInputData* data = DeoptimizationInputData::cast(
8336          function->code()->deoptimization_data());
8337      if (data->OsrPcOffset()->value() >= 0) {
8338        if (FLAG_trace_osr) {
8339          PrintF("[on-stack replacement offset %d in optimized code]\n",
8340               data->OsrPcOffset()->value());
8341        }
8342        ASSERT(data->OsrAstId()->value() == ast_id);
8343      } else {
8344        // We may never generate the desired OSR entry if we emit an
8345        // early deoptimize.
8346        succeeded = false;
8347      }
8348    } else {
8349      succeeded = false;
8350    }
8351  }
8352
8353  // Revert to the original stack checks in the original unoptimized code.
8354  if (FLAG_trace_osr) {
8355    PrintF("[restoring original stack checks in ");
8356    function->PrintName();
8357    PrintF("]\n");
8358  }
8359  Handle<Code> check_code;
8360#if defined(V8_TARGET_ARCH_IA32) || \
8361    defined(V8_TARGET_ARCH_ARM) || \
8362    defined(V8_TARGET_ARCH_MIPS)
8363  if (FLAG_count_based_interrupts) {
8364    InterruptStub interrupt_stub;
8365    check_code = interrupt_stub.GetCode();
8366  } else  // NOLINT
8367#endif
8368  {  // NOLINT
8369    StackCheckStub check_stub;
8370    check_code = check_stub.GetCode();
8371  }
8372  Handle<Code> replacement_code = isolate->builtins()->OnStackReplacement();
8373  Deoptimizer::RevertStackCheckCode(*unoptimized,
8374                                    *check_code,
8375                                    *replacement_code);
8376
8377  // Allow OSR only at nesting level zero again.
8378  unoptimized->set_allow_osr_at_loop_nesting_level(0);
8379
8380  // If the optimization attempt succeeded, return the AST id tagged as a
8381  // smi. This tells the builtin that we need to translate the unoptimized
8382  // frame to an optimized one.
8383  if (succeeded) {
8384    ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION);
8385    return Smi::FromInt(ast_id);
8386  } else {
8387    if (function->IsMarkedForLazyRecompilation()) {
8388      function->ReplaceCode(function->shared()->code());
8389    }
8390    return Smi::FromInt(-1);
8391  }
8392}
8393
8394
8395RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckIsBootstrapping) {
8396  RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8397  return isolate->heap()->undefined_value();
8398}
8399
8400
8401RUNTIME_FUNCTION(MaybeObject*, Runtime_GetRootNaN) {
8402  RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8403  return isolate->heap()->nan_value();
8404}
8405
8406
8407RUNTIME_FUNCTION(MaybeObject*, Runtime_Call) {
8408  HandleScope scope(isolate);
8409  ASSERT(args.length() >= 2);
8410  int argc = args.length() - 2;
8411  CONVERT_ARG_CHECKED(JSReceiver, fun, argc + 1);
8412  Object* receiver = args[0];
8413
8414  // If there are too many arguments, allocate argv via malloc.
8415  const int argv_small_size = 10;
8416  Handle<Object> argv_small_buffer[argv_small_size];
8417  SmartArrayPointer<Handle<Object> > argv_large_buffer;
8418  Handle<Object>* argv = argv_small_buffer;
8419  if (argc > argv_small_size) {
8420    argv = new Handle<Object>[argc];
8421    if (argv == NULL) return isolate->StackOverflow();
8422    argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8423  }
8424
8425  for (int i = 0; i < argc; ++i) {
8426     MaybeObject* maybe = args[1 + i];
8427     Object* object;
8428     if (!maybe->To<Object>(&object)) return maybe;
8429     argv[i] = Handle<Object>(object);
8430  }
8431
8432  bool threw;
8433  Handle<JSReceiver> hfun(fun);
8434  Handle<Object> hreceiver(receiver);
8435  Handle<Object> result =
8436      Execution::Call(hfun, hreceiver, argc, argv, &threw, true);
8437
8438  if (threw) return Failure::Exception();
8439  return *result;
8440}
8441
8442
8443RUNTIME_FUNCTION(MaybeObject*, Runtime_Apply) {
8444  HandleScope scope(isolate);
8445  ASSERT(args.length() == 5);
8446  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, fun, 0);
8447  Handle<Object> receiver = args.at<Object>(1);
8448  CONVERT_ARG_HANDLE_CHECKED(JSObject, arguments, 2);
8449  CONVERT_SMI_ARG_CHECKED(offset, 3);
8450  CONVERT_SMI_ARG_CHECKED(argc, 4);
8451  ASSERT(offset >= 0);
8452  ASSERT(argc >= 0);
8453
8454  // If there are too many arguments, allocate argv via malloc.
8455  const int argv_small_size = 10;
8456  Handle<Object> argv_small_buffer[argv_small_size];
8457  SmartArrayPointer<Handle<Object> > argv_large_buffer;
8458  Handle<Object>* argv = argv_small_buffer;
8459  if (argc > argv_small_size) {
8460    argv = new Handle<Object>[argc];
8461    if (argv == NULL) return isolate->StackOverflow();
8462    argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8463  }
8464
8465  for (int i = 0; i < argc; ++i) {
8466    argv[i] = Object::GetElement(arguments, offset + i);
8467  }
8468
8469  bool threw;
8470  Handle<Object> result =
8471      Execution::Call(fun, receiver, argc, argv, &threw, true);
8472
8473  if (threw) return Failure::Exception();
8474  return *result;
8475}
8476
8477
8478RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionDelegate) {
8479  HandleScope scope(isolate);
8480  ASSERT(args.length() == 1);
8481  RUNTIME_ASSERT(!args[0]->IsJSFunction());
8482  return *Execution::GetFunctionDelegate(args.at<Object>(0));
8483}
8484
8485
8486RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) {
8487  HandleScope scope(isolate);
8488  ASSERT(args.length() == 1);
8489  RUNTIME_ASSERT(!args[0]->IsJSFunction());
8490  return *Execution::GetConstructorDelegate(args.at<Object>(0));
8491}
8492
8493
8494RUNTIME_FUNCTION(MaybeObject*, Runtime_NewFunctionContext) {
8495  NoHandleAllocation ha;
8496  ASSERT(args.length() == 1);
8497
8498  CONVERT_ARG_CHECKED(JSFunction, function, 0);
8499  int length = function->shared()->scope_info()->ContextLength();
8500  Object* result;
8501  { MaybeObject* maybe_result =
8502        isolate->heap()->AllocateFunctionContext(length, function);
8503    if (!maybe_result->ToObject(&result)) return maybe_result;
8504  }
8505
8506  isolate->set_context(Context::cast(result));
8507
8508  return result;  // non-failure
8509}
8510
8511
8512RUNTIME_FUNCTION(MaybeObject*, Runtime_PushWithContext) {
8513  NoHandleAllocation ha;
8514  ASSERT(args.length() == 2);
8515  JSObject* extension_object;
8516  if (args[0]->IsJSObject()) {
8517    extension_object = JSObject::cast(args[0]);
8518  } else {
8519    // Convert the object to a proper JavaScript object.
8520    MaybeObject* maybe_js_object = args[0]->ToObject();
8521    if (!maybe_js_object->To(&extension_object)) {
8522      if (Failure::cast(maybe_js_object)->IsInternalError()) {
8523        HandleScope scope(isolate);
8524        Handle<Object> handle = args.at<Object>(0);
8525        Handle<Object> result =
8526            isolate->factory()->NewTypeError("with_expression",
8527                                             HandleVector(&handle, 1));
8528        return isolate->Throw(*result);
8529      } else {
8530        return maybe_js_object;
8531      }
8532    }
8533  }
8534
8535  JSFunction* function;
8536  if (args[1]->IsSmi()) {
8537    // A smi sentinel indicates a context nested inside global code rather
8538    // than some function.  There is a canonical empty function that can be
8539    // gotten from the global context.
8540    function = isolate->context()->global_context()->closure();
8541  } else {
8542    function = JSFunction::cast(args[1]);
8543  }
8544
8545  Context* context;
8546  MaybeObject* maybe_context =
8547      isolate->heap()->AllocateWithContext(function,
8548                                           isolate->context(),
8549                                           extension_object);
8550  if (!maybe_context->To(&context)) return maybe_context;
8551  isolate->set_context(context);
8552  return context;
8553}
8554
8555
8556RUNTIME_FUNCTION(MaybeObject*, Runtime_PushCatchContext) {
8557  NoHandleAllocation ha;
8558  ASSERT(args.length() == 3);
8559  String* name = String::cast(args[0]);
8560  Object* thrown_object = args[1];
8561  JSFunction* function;
8562  if (args[2]->IsSmi()) {
8563    // A smi sentinel indicates a context nested inside global code rather
8564    // than some function.  There is a canonical empty function that can be
8565    // gotten from the global context.
8566    function = isolate->context()->global_context()->closure();
8567  } else {
8568    function = JSFunction::cast(args[2]);
8569  }
8570  Context* context;
8571  MaybeObject* maybe_context =
8572      isolate->heap()->AllocateCatchContext(function,
8573                                            isolate->context(),
8574                                            name,
8575                                            thrown_object);
8576  if (!maybe_context->To(&context)) return maybe_context;
8577  isolate->set_context(context);
8578  return context;
8579}
8580
8581
8582RUNTIME_FUNCTION(MaybeObject*, Runtime_PushBlockContext) {
8583  NoHandleAllocation ha;
8584  ASSERT(args.length() == 2);
8585  ScopeInfo* scope_info = ScopeInfo::cast(args[0]);
8586  JSFunction* function;
8587  if (args[1]->IsSmi()) {
8588    // A smi sentinel indicates a context nested inside global code rather
8589    // than some function.  There is a canonical empty function that can be
8590    // gotten from the global context.
8591    function = isolate->context()->global_context()->closure();
8592  } else {
8593    function = JSFunction::cast(args[1]);
8594  }
8595  Context* context;
8596  MaybeObject* maybe_context =
8597      isolate->heap()->AllocateBlockContext(function,
8598                                            isolate->context(),
8599                                            scope_info);
8600  if (!maybe_context->To(&context)) return maybe_context;
8601  isolate->set_context(context);
8602  return context;
8603}
8604
8605
8606RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteContextSlot) {
8607  HandleScope scope(isolate);
8608  ASSERT(args.length() == 2);
8609
8610  CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
8611  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
8612
8613  int index;
8614  PropertyAttributes attributes;
8615  ContextLookupFlags flags = FOLLOW_CHAINS;
8616  BindingFlags binding_flags;
8617  Handle<Object> holder = context->Lookup(name,
8618                                          flags,
8619                                          &index,
8620                                          &attributes,
8621                                          &binding_flags);
8622
8623  // If the slot was not found the result is true.
8624  if (holder.is_null()) {
8625    return isolate->heap()->true_value();
8626  }
8627
8628  // If the slot was found in a context, it should be DONT_DELETE.
8629  if (holder->IsContext()) {
8630    return isolate->heap()->false_value();
8631  }
8632
8633  // The slot was found in a JSObject, either a context extension object,
8634  // the global object, or the subject of a with.  Try to delete it
8635  // (respecting DONT_DELETE).
8636  Handle<JSObject> object = Handle<JSObject>::cast(holder);
8637  return object->DeleteProperty(*name, JSReceiver::NORMAL_DELETION);
8638}
8639
8640
8641// A mechanism to return a pair of Object pointers in registers (if possible).
8642// How this is achieved is calling convention-dependent.
8643// All currently supported x86 compiles uses calling conventions that are cdecl
8644// variants where a 64-bit value is returned in two 32-bit registers
8645// (edx:eax on ia32, r1:r0 on ARM).
8646// In AMD-64 calling convention a struct of two pointers is returned in rdx:rax.
8647// In Win64 calling convention, a struct of two pointers is returned in memory,
8648// allocated by the caller, and passed as a pointer in a hidden first parameter.
8649#ifdef V8_HOST_ARCH_64_BIT
8650struct ObjectPair {
8651  MaybeObject* x;
8652  MaybeObject* y;
8653};
8654
8655static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
8656  ObjectPair result = {x, y};
8657  // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
8658  // In Win64 they are assigned to a hidden first argument.
8659  return result;
8660}
8661#else
8662typedef uint64_t ObjectPair;
8663static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
8664  return reinterpret_cast<uint32_t>(x) |
8665      (reinterpret_cast<ObjectPair>(y) << 32);
8666}
8667#endif
8668
8669
8670static inline MaybeObject* Unhole(Heap* heap,
8671                                  MaybeObject* x,
8672                                  PropertyAttributes attributes) {
8673  ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
8674  USE(attributes);
8675  return x->IsTheHole() ? heap->undefined_value() : x;
8676}
8677
8678
8679static Object* ComputeReceiverForNonGlobal(Isolate* isolate,
8680                                           JSObject* holder) {
8681  ASSERT(!holder->IsGlobalObject());
8682  Context* top = isolate->context();
8683  // Get the context extension function.
8684  JSFunction* context_extension_function =
8685      top->global_context()->context_extension_function();
8686  // If the holder isn't a context extension object, we just return it
8687  // as the receiver. This allows arguments objects to be used as
8688  // receivers, but only if they are put in the context scope chain
8689  // explicitly via a with-statement.
8690  Object* constructor = holder->map()->constructor();
8691  if (constructor != context_extension_function) return holder;
8692  // Fall back to using the global object as the implicit receiver if
8693  // the property turns out to be a local variable allocated in a
8694  // context extension object - introduced via eval. Implicit global
8695  // receivers are indicated with the hole value.
8696  return isolate->heap()->the_hole_value();
8697}
8698
8699
8700static ObjectPair LoadContextSlotHelper(Arguments args,
8701                                        Isolate* isolate,
8702                                        bool throw_error) {
8703  HandleScope scope(isolate);
8704  ASSERT_EQ(2, args.length());
8705
8706  if (!args[0]->IsContext() || !args[1]->IsString()) {
8707    return MakePair(isolate->ThrowIllegalOperation(), NULL);
8708  }
8709  Handle<Context> context = args.at<Context>(0);
8710  Handle<String> name = args.at<String>(1);
8711
8712  int index;
8713  PropertyAttributes attributes;
8714  ContextLookupFlags flags = FOLLOW_CHAINS;
8715  BindingFlags binding_flags;
8716  Handle<Object> holder = context->Lookup(name,
8717                                          flags,
8718                                          &index,
8719                                          &attributes,
8720                                          &binding_flags);
8721
8722  // If the index is non-negative, the slot has been found in a context.
8723  if (index >= 0) {
8724    ASSERT(holder->IsContext());
8725    // If the "property" we were looking for is a local variable, the
8726    // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
8727    //
8728    // Use the hole as the receiver to signal that the receiver is implicit
8729    // and that the global receiver should be used (as distinguished from an
8730    // explicit receiver that happens to be a global object).
8731    Handle<Object> receiver = isolate->factory()->the_hole_value();
8732    Object* value = Context::cast(*holder)->get(index);
8733    // Check for uninitialized bindings.
8734    switch (binding_flags) {
8735      case MUTABLE_CHECK_INITIALIZED:
8736      case IMMUTABLE_CHECK_INITIALIZED_HARMONY:
8737        if (value->IsTheHole()) {
8738          Handle<Object> reference_error =
8739              isolate->factory()->NewReferenceError("not_defined",
8740                                                    HandleVector(&name, 1));
8741          return MakePair(isolate->Throw(*reference_error), NULL);
8742        }
8743        // FALLTHROUGH
8744      case MUTABLE_IS_INITIALIZED:
8745      case IMMUTABLE_IS_INITIALIZED:
8746      case IMMUTABLE_IS_INITIALIZED_HARMONY:
8747        ASSERT(!value->IsTheHole());
8748        return MakePair(value, *receiver);
8749      case IMMUTABLE_CHECK_INITIALIZED:
8750        return MakePair(Unhole(isolate->heap(), value, attributes), *receiver);
8751      case MISSING_BINDING:
8752        UNREACHABLE();
8753        return MakePair(NULL, NULL);
8754    }
8755  }
8756
8757  // Otherwise, if the slot was found the holder is a context extension
8758  // object, subject of a with, or a global object.  We read the named
8759  // property from it.
8760  if (!holder.is_null()) {
8761    Handle<JSObject> object = Handle<JSObject>::cast(holder);
8762    ASSERT(object->HasProperty(*name));
8763    // GetProperty below can cause GC.
8764    Handle<Object> receiver_handle(object->IsGlobalObject()
8765        ? GlobalObject::cast(*object)->global_receiver()
8766        : ComputeReceiverForNonGlobal(isolate, *object));
8767
8768    // No need to unhole the value here.  This is taken care of by the
8769    // GetProperty function.
8770    MaybeObject* value = object->GetProperty(*name);
8771    return MakePair(value, *receiver_handle);
8772  }
8773
8774  if (throw_error) {
8775    // The property doesn't exist - throw exception.
8776    Handle<Object> reference_error =
8777        isolate->factory()->NewReferenceError("not_defined",
8778                                              HandleVector(&name, 1));
8779    return MakePair(isolate->Throw(*reference_error), NULL);
8780  } else {
8781    // The property doesn't exist - return undefined.
8782    return MakePair(isolate->heap()->undefined_value(),
8783                    isolate->heap()->undefined_value());
8784  }
8785}
8786
8787
8788RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlot) {
8789  return LoadContextSlotHelper(args, isolate, true);
8790}
8791
8792
8793RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlotNoReferenceError) {
8794  return LoadContextSlotHelper(args, isolate, false);
8795}
8796
8797
8798RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreContextSlot) {
8799  HandleScope scope(isolate);
8800  ASSERT(args.length() == 4);
8801
8802  Handle<Object> value(args[0], isolate);
8803  CONVERT_ARG_HANDLE_CHECKED(Context, context, 1);
8804  CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
8805  CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
8806  StrictModeFlag strict_mode = (language_mode == CLASSIC_MODE)
8807      ? kNonStrictMode : kStrictMode;
8808
8809  int index;
8810  PropertyAttributes attributes;
8811  ContextLookupFlags flags = FOLLOW_CHAINS;
8812  BindingFlags binding_flags;
8813  Handle<Object> holder = context->Lookup(name,
8814                                          flags,
8815                                          &index,
8816                                          &attributes,
8817                                          &binding_flags);
8818
8819  if (index >= 0) {
8820    // The property was found in a context slot.
8821    Handle<Context> context = Handle<Context>::cast(holder);
8822    if (binding_flags == MUTABLE_CHECK_INITIALIZED &&
8823        context->get(index)->IsTheHole()) {
8824      Handle<Object> error =
8825          isolate->factory()->NewReferenceError("not_defined",
8826                                                HandleVector(&name, 1));
8827      return isolate->Throw(*error);
8828    }
8829    // Ignore if read_only variable.
8830    if ((attributes & READ_ONLY) == 0) {
8831      // Context is a fixed array and set cannot fail.
8832      context->set(index, *value);
8833    } else if (strict_mode == kStrictMode) {
8834      // Setting read only property in strict mode.
8835      Handle<Object> error =
8836          isolate->factory()->NewTypeError("strict_cannot_assign",
8837                                           HandleVector(&name, 1));
8838      return isolate->Throw(*error);
8839    }
8840    return *value;
8841  }
8842
8843  // Slow case: The property is not in a context slot.  It is either in a
8844  // context extension object, a property of the subject of a with, or a
8845  // property of the global object.
8846  Handle<JSObject> object;
8847
8848  if (!holder.is_null()) {
8849    // The property exists on the holder.
8850    object = Handle<JSObject>::cast(holder);
8851  } else {
8852    // The property was not found.
8853    ASSERT(attributes == ABSENT);
8854
8855    if (strict_mode == kStrictMode) {
8856      // Throw in strict mode (assignment to undefined variable).
8857      Handle<Object> error =
8858          isolate->factory()->NewReferenceError(
8859              "not_defined", HandleVector(&name, 1));
8860      return isolate->Throw(*error);
8861    }
8862    // In non-strict mode, the property is added to the global object.
8863    attributes = NONE;
8864    object = Handle<JSObject>(isolate->context()->global());
8865  }
8866
8867  // Set the property if it's not read only or doesn't yet exist.
8868  if ((attributes & READ_ONLY) == 0 ||
8869      (object->GetLocalPropertyAttribute(*name) == ABSENT)) {
8870    RETURN_IF_EMPTY_HANDLE(
8871        isolate,
8872        JSReceiver::SetProperty(object, name, value, NONE, strict_mode));
8873  } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) {
8874    // Setting read only property in strict mode.
8875    Handle<Object> error =
8876      isolate->factory()->NewTypeError(
8877          "strict_cannot_assign", HandleVector(&name, 1));
8878    return isolate->Throw(*error);
8879  }
8880  return *value;
8881}
8882
8883
8884RUNTIME_FUNCTION(MaybeObject*, Runtime_Throw) {
8885  HandleScope scope(isolate);
8886  ASSERT(args.length() == 1);
8887
8888  return isolate->Throw(args[0]);
8889}
8890
8891
8892RUNTIME_FUNCTION(MaybeObject*, Runtime_ReThrow) {
8893  HandleScope scope(isolate);
8894  ASSERT(args.length() == 1);
8895
8896  return isolate->ReThrow(args[0]);
8897}
8898
8899
8900RUNTIME_FUNCTION(MaybeObject*, Runtime_PromoteScheduledException) {
8901  ASSERT_EQ(0, args.length());
8902  return isolate->PromoteScheduledException();
8903}
8904
8905
8906RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowReferenceError) {
8907  HandleScope scope(isolate);
8908  ASSERT(args.length() == 1);
8909
8910  Handle<Object> name(args[0], isolate);
8911  Handle<Object> reference_error =
8912    isolate->factory()->NewReferenceError("not_defined",
8913                                          HandleVector(&name, 1));
8914  return isolate->Throw(*reference_error);
8915}
8916
8917
8918RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) {
8919  ASSERT(args.length() == 0);
8920
8921  // First check if this is a real stack overflow.
8922  if (isolate->stack_guard()->IsStackOverflow()) {
8923    NoHandleAllocation na;
8924    return isolate->StackOverflow();
8925  }
8926
8927  return Execution::HandleStackGuardInterrupt(isolate);
8928}
8929
8930
8931RUNTIME_FUNCTION(MaybeObject*, Runtime_Interrupt) {
8932  ASSERT(args.length() == 0);
8933  return Execution::HandleStackGuardInterrupt(isolate);
8934}
8935
8936
8937static int StackSize() {
8938  int n = 0;
8939  for (JavaScriptFrameIterator it; !it.done(); it.Advance()) n++;
8940  return n;
8941}
8942
8943
8944static void PrintTransition(Object* result) {
8945  // indentation
8946  { const int nmax = 80;
8947    int n = StackSize();
8948    if (n <= nmax)
8949      PrintF("%4d:%*s", n, n, "");
8950    else
8951      PrintF("%4d:%*s", n, nmax, "...");
8952  }
8953
8954  if (result == NULL) {
8955    JavaScriptFrame::PrintTop(stdout, true, false);
8956    PrintF(" {\n");
8957  } else {
8958    // function result
8959    PrintF("} -> ");
8960    result->ShortPrint();
8961    PrintF("\n");
8962  }
8963}
8964
8965
8966RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceEnter) {
8967  ASSERT(args.length() == 0);
8968  NoHandleAllocation ha;
8969  PrintTransition(NULL);
8970  return isolate->heap()->undefined_value();
8971}
8972
8973
8974RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceExit) {
8975  NoHandleAllocation ha;
8976  PrintTransition(args[0]);
8977  return args[0];  // return TOS
8978}
8979
8980
8981RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrint) {
8982  NoHandleAllocation ha;
8983  ASSERT(args.length() == 1);
8984
8985#ifdef DEBUG
8986  if (args[0]->IsString()) {
8987    // If we have a string, assume it's a code "marker"
8988    // and print some interesting cpu debugging info.
8989    JavaScriptFrameIterator it(isolate);
8990    JavaScriptFrame* frame = it.frame();
8991    PrintF("fp = %p, sp = %p, caller_sp = %p: ",
8992           frame->fp(), frame->sp(), frame->caller_sp());
8993  } else {
8994    PrintF("DebugPrint: ");
8995  }
8996  args[0]->Print();
8997  if (args[0]->IsHeapObject()) {
8998    PrintF("\n");
8999    HeapObject::cast(args[0])->map()->Print();
9000  }
9001#else
9002  // ShortPrint is available in release mode. Print is not.
9003  args[0]->ShortPrint();
9004#endif
9005  PrintF("\n");
9006  Flush();
9007
9008  return args[0];  // return TOS
9009}
9010
9011
9012RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugTrace) {
9013  ASSERT(args.length() == 0);
9014  NoHandleAllocation ha;
9015  isolate->PrintStack();
9016  return isolate->heap()->undefined_value();
9017}
9018
9019
9020RUNTIME_FUNCTION(MaybeObject*, Runtime_DateCurrentTime) {
9021  NoHandleAllocation ha;
9022  ASSERT(args.length() == 0);
9023
9024  // According to ECMA-262, section 15.9.1, page 117, the precision of
9025  // the number in a Date object representing a particular instant in
9026  // time is milliseconds. Therefore, we floor the result of getting
9027  // the OS time.
9028  double millis = floor(OS::TimeCurrentMillis());
9029  return isolate->heap()->NumberFromDouble(millis);
9030}
9031
9032
9033RUNTIME_FUNCTION(MaybeObject*, Runtime_DateParseString) {
9034  HandleScope scope(isolate);
9035  ASSERT(args.length() == 2);
9036
9037  CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
9038  FlattenString(str);
9039
9040  CONVERT_ARG_HANDLE_CHECKED(JSArray, output, 1);
9041
9042  MaybeObject* maybe_result_array =
9043      output->EnsureCanContainHeapObjectElements();
9044  if (maybe_result_array->IsFailure()) return maybe_result_array;
9045  RUNTIME_ASSERT(output->HasFastElements());
9046
9047  AssertNoAllocation no_allocation;
9048
9049  FixedArray* output_array = FixedArray::cast(output->elements());
9050  RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
9051  bool result;
9052  String::FlatContent str_content = str->GetFlatContent();
9053  if (str_content.IsAscii()) {
9054    result = DateParser::Parse(str_content.ToAsciiVector(),
9055                               output_array,
9056                               isolate->unicode_cache());
9057  } else {
9058    ASSERT(str_content.IsTwoByte());
9059    result = DateParser::Parse(str_content.ToUC16Vector(),
9060                               output_array,
9061                               isolate->unicode_cache());
9062  }
9063
9064  if (result) {
9065    return *output;
9066  } else {
9067    return isolate->heap()->null_value();
9068  }
9069}
9070
9071
9072RUNTIME_FUNCTION(MaybeObject*, Runtime_DateLocalTimezone) {
9073  NoHandleAllocation ha;
9074  ASSERT(args.length() == 1);
9075
9076  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
9077  int64_t time = isolate->date_cache()->EquivalentTime(static_cast<int64_t>(x));
9078  const char* zone = OS::LocalTimezone(static_cast<double>(time));
9079  return isolate->heap()->AllocateStringFromUtf8(CStrVector(zone));
9080}
9081
9082
9083RUNTIME_FUNCTION(MaybeObject*, Runtime_DateToUTC) {
9084  NoHandleAllocation ha;
9085  ASSERT(args.length() == 1);
9086
9087  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
9088  int64_t time = isolate->date_cache()->ToUTC(static_cast<int64_t>(x));
9089
9090  return isolate->heap()->NumberFromDouble(static_cast<double>(time));
9091}
9092
9093
9094RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalReceiver) {
9095  ASSERT(args.length() == 1);
9096  Object* global = args[0];
9097  if (!global->IsJSGlobalObject()) return isolate->heap()->null_value();
9098  return JSGlobalObject::cast(global)->global_receiver();
9099}
9100
9101
9102RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) {
9103  HandleScope scope(isolate);
9104  ASSERT_EQ(1, args.length());
9105  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9106
9107  source = Handle<String>(source->TryFlattenGetString());
9108  // Optimized fast case where we only have ASCII characters.
9109  Handle<Object> result;
9110  if (source->IsSeqAsciiString()) {
9111    result = JsonParser<true>::Parse(source);
9112  } else {
9113    result = JsonParser<false>::Parse(source);
9114  }
9115  if (result.is_null()) {
9116    // Syntax error or stack overflow in scanner.
9117    ASSERT(isolate->has_pending_exception());
9118    return Failure::Exception();
9119  }
9120  return *result;
9121}
9122
9123
9124bool CodeGenerationFromStringsAllowed(Isolate* isolate,
9125                                      Handle<Context> context) {
9126  ASSERT(context->allow_code_gen_from_strings()->IsFalse());
9127  // Check with callback if set.
9128  AllowCodeGenerationFromStringsCallback callback =
9129      isolate->allow_code_gen_callback();
9130  if (callback == NULL) {
9131    // No callback set and code generation disallowed.
9132    return false;
9133  } else {
9134    // Callback set. Let it decide if code generation is allowed.
9135    VMState state(isolate, EXTERNAL);
9136    return callback(v8::Utils::ToLocal(context));
9137  }
9138}
9139
9140
9141RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
9142  HandleScope scope(isolate);
9143  ASSERT_EQ(1, args.length());
9144  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9145
9146  // Extract global context.
9147  Handle<Context> context(isolate->context()->global_context());
9148
9149  // Check if global context allows code generation from
9150  // strings. Throw an exception if it doesn't.
9151  if (context->allow_code_gen_from_strings()->IsFalse() &&
9152      !CodeGenerationFromStringsAllowed(isolate, context)) {
9153    return isolate->Throw(*isolate->factory()->NewError(
9154        "code_gen_from_strings", HandleVector<Object>(NULL, 0)));
9155  }
9156
9157  // Compile source string in the global context.
9158  Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
9159      source, context, true, CLASSIC_MODE, RelocInfo::kNoPosition);
9160  if (shared.is_null()) return Failure::Exception();
9161  Handle<JSFunction> fun =
9162      isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
9163                                                            context,
9164                                                            NOT_TENURED);
9165  return *fun;
9166}
9167
9168
9169static ObjectPair CompileGlobalEval(Isolate* isolate,
9170                                    Handle<String> source,
9171                                    Handle<Object> receiver,
9172                                    LanguageMode language_mode,
9173                                    int scope_position) {
9174  Handle<Context> context = Handle<Context>(isolate->context());
9175  Handle<Context> global_context = Handle<Context>(context->global_context());
9176
9177  // Check if global context allows code generation from
9178  // strings. Throw an exception if it doesn't.
9179  if (global_context->allow_code_gen_from_strings()->IsFalse() &&
9180      !CodeGenerationFromStringsAllowed(isolate, global_context)) {
9181    isolate->Throw(*isolate->factory()->NewError(
9182        "code_gen_from_strings", HandleVector<Object>(NULL, 0)));
9183    return MakePair(Failure::Exception(), NULL);
9184  }
9185
9186  // Deal with a normal eval call with a string argument. Compile it
9187  // and return the compiled function bound in the local context.
9188  Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
9189      source,
9190      Handle<Context>(isolate->context()),
9191      context->IsGlobalContext(),
9192      language_mode,
9193      scope_position);
9194  if (shared.is_null()) return MakePair(Failure::Exception(), NULL);
9195  Handle<JSFunction> compiled =
9196      isolate->factory()->NewFunctionFromSharedFunctionInfo(
9197          shared, context, NOT_TENURED);
9198  return MakePair(*compiled, *receiver);
9199}
9200
9201
9202RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
9203  ASSERT(args.length() == 5);
9204
9205  HandleScope scope(isolate);
9206  Handle<Object> callee = args.at<Object>(0);
9207
9208  // If "eval" didn't refer to the original GlobalEval, it's not a
9209  // direct call to eval.
9210  // (And even if it is, but the first argument isn't a string, just let
9211  // execution default to an indirect call to eval, which will also return
9212  // the first argument without doing anything).
9213  if (*callee != isolate->global_context()->global_eval_fun() ||
9214      !args[1]->IsString()) {
9215    return MakePair(*callee, isolate->heap()->the_hole_value());
9216  }
9217
9218  CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
9219  ASSERT(args[4]->IsSmi());
9220  return CompileGlobalEval(isolate,
9221                           args.at<String>(1),
9222                           args.at<Object>(2),
9223                           language_mode,
9224                           args.smi_at(4));
9225}
9226
9227
9228RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNewFunctionAttributes) {
9229  // This utility adjusts the property attributes for newly created Function
9230  // object ("new Function(...)") by changing the map.
9231  // All it does is changing the prototype property to enumerable
9232  // as specified in ECMA262, 15.3.5.2.
9233  HandleScope scope(isolate);
9234  ASSERT(args.length() == 1);
9235  CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
9236
9237  Handle<Map> map = func->shared()->is_classic_mode()
9238      ? isolate->function_instance_map()
9239      : isolate->strict_mode_function_instance_map();
9240
9241  ASSERT(func->map()->instance_type() == map->instance_type());
9242  ASSERT(func->map()->instance_size() == map->instance_size());
9243  func->set_map(*map);
9244  return *func;
9245}
9246
9247
9248RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInNewSpace) {
9249  // Allocate a block of memory in NewSpace (filled with a filler).
9250  // Use as fallback for allocation in generated code when NewSpace
9251  // is full.
9252  ASSERT(args.length() == 1);
9253  CONVERT_ARG_HANDLE_CHECKED(Smi, size_smi, 0);
9254  int size = size_smi->value();
9255  RUNTIME_ASSERT(IsAligned(size, kPointerSize));
9256  RUNTIME_ASSERT(size > 0);
9257  Heap* heap = isolate->heap();
9258  const int kMinFreeNewSpaceAfterGC = heap->InitialSemiSpaceSize() * 3/4;
9259  RUNTIME_ASSERT(size <= kMinFreeNewSpaceAfterGC);
9260  Object* allocation;
9261  { MaybeObject* maybe_allocation = heap->new_space()->AllocateRaw(size);
9262    if (maybe_allocation->ToObject(&allocation)) {
9263      heap->CreateFillerObjectAt(HeapObject::cast(allocation)->address(), size);
9264    }
9265    return maybe_allocation;
9266  }
9267}
9268
9269
9270// Push an object unto an array of objects if it is not already in the
9271// array.  Returns true if the element was pushed on the stack and
9272// false otherwise.
9273RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) {
9274  ASSERT(args.length() == 2);
9275  CONVERT_ARG_CHECKED(JSArray, array, 0);
9276  CONVERT_ARG_CHECKED(JSObject, element, 1);
9277  RUNTIME_ASSERT(array->HasFastElements() || array->HasFastSmiOnlyElements());
9278  int length = Smi::cast(array->length())->value();
9279  FixedArray* elements = FixedArray::cast(array->elements());
9280  for (int i = 0; i < length; i++) {
9281    if (elements->get(i) == element) return isolate->heap()->false_value();
9282  }
9283  Object* obj;
9284  // Strict not needed. Used for cycle detection in Array join implementation.
9285  { MaybeObject* maybe_obj =
9286        array->SetFastElement(length, element, kNonStrictMode, true);
9287    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9288  }
9289  return isolate->heap()->true_value();
9290}
9291
9292
9293/**
9294 * A simple visitor visits every element of Array's.
9295 * The backend storage can be a fixed array for fast elements case,
9296 * or a dictionary for sparse array. Since Dictionary is a subtype
9297 * of FixedArray, the class can be used by both fast and slow cases.
9298 * The second parameter of the constructor, fast_elements, specifies
9299 * whether the storage is a FixedArray or Dictionary.
9300 *
9301 * An index limit is used to deal with the situation that a result array
9302 * length overflows 32-bit non-negative integer.
9303 */
9304class ArrayConcatVisitor {
9305 public:
9306  ArrayConcatVisitor(Isolate* isolate,
9307                     Handle<FixedArray> storage,
9308                     bool fast_elements) :
9309      isolate_(isolate),
9310      storage_(Handle<FixedArray>::cast(
9311          isolate->global_handles()->Create(*storage))),
9312      index_offset_(0u),
9313      fast_elements_(fast_elements) { }
9314
9315  ~ArrayConcatVisitor() {
9316    clear_storage();
9317  }
9318
9319  void visit(uint32_t i, Handle<Object> elm) {
9320    if (i >= JSObject::kMaxElementCount - index_offset_) return;
9321    uint32_t index = index_offset_ + i;
9322
9323    if (fast_elements_) {
9324      if (index < static_cast<uint32_t>(storage_->length())) {
9325        storage_->set(index, *elm);
9326        return;
9327      }
9328      // Our initial estimate of length was foiled, possibly by
9329      // getters on the arrays increasing the length of later arrays
9330      // during iteration.
9331      // This shouldn't happen in anything but pathological cases.
9332      SetDictionaryMode(index);
9333      // Fall-through to dictionary mode.
9334    }
9335    ASSERT(!fast_elements_);
9336    Handle<SeededNumberDictionary> dict(
9337        SeededNumberDictionary::cast(*storage_));
9338    Handle<SeededNumberDictionary> result =
9339        isolate_->factory()->DictionaryAtNumberPut(dict, index, elm);
9340    if (!result.is_identical_to(dict)) {
9341      // Dictionary needed to grow.
9342      clear_storage();
9343      set_storage(*result);
9344    }
9345}
9346
9347  void increase_index_offset(uint32_t delta) {
9348    if (JSObject::kMaxElementCount - index_offset_ < delta) {
9349      index_offset_ = JSObject::kMaxElementCount;
9350    } else {
9351      index_offset_ += delta;
9352    }
9353  }
9354
9355  Handle<JSArray> ToArray() {
9356    Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
9357    Handle<Object> length =
9358        isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
9359    Handle<Map> map;
9360    if (fast_elements_) {
9361      map = isolate_->factory()->GetElementsTransitionMap(array,
9362                                                          FAST_ELEMENTS);
9363    } else {
9364      map = isolate_->factory()->GetElementsTransitionMap(array,
9365                                                          DICTIONARY_ELEMENTS);
9366    }
9367    array->set_map(*map);
9368    array->set_length(*length);
9369    array->set_elements(*storage_);
9370    return array;
9371  }
9372
9373 private:
9374  // Convert storage to dictionary mode.
9375  void SetDictionaryMode(uint32_t index) {
9376    ASSERT(fast_elements_);
9377    Handle<FixedArray> current_storage(*storage_);
9378    Handle<SeededNumberDictionary> slow_storage(
9379        isolate_->factory()->NewSeededNumberDictionary(
9380            current_storage->length()));
9381    uint32_t current_length = static_cast<uint32_t>(current_storage->length());
9382    for (uint32_t i = 0; i < current_length; i++) {
9383      HandleScope loop_scope;
9384      Handle<Object> element(current_storage->get(i));
9385      if (!element->IsTheHole()) {
9386        Handle<SeededNumberDictionary> new_storage =
9387          isolate_->factory()->DictionaryAtNumberPut(slow_storage, i, element);
9388        if (!new_storage.is_identical_to(slow_storage)) {
9389          slow_storage = loop_scope.CloseAndEscape(new_storage);
9390        }
9391      }
9392    }
9393    clear_storage();
9394    set_storage(*slow_storage);
9395    fast_elements_ = false;
9396  }
9397
9398  inline void clear_storage() {
9399    isolate_->global_handles()->Destroy(
9400        Handle<Object>::cast(storage_).location());
9401  }
9402
9403  inline void set_storage(FixedArray* storage) {
9404    storage_ = Handle<FixedArray>::cast(
9405        isolate_->global_handles()->Create(storage));
9406  }
9407
9408  Isolate* isolate_;
9409  Handle<FixedArray> storage_;  // Always a global handle.
9410  // Index after last seen index. Always less than or equal to
9411  // JSObject::kMaxElementCount.
9412  uint32_t index_offset_;
9413  bool fast_elements_;
9414};
9415
9416
9417static uint32_t EstimateElementCount(Handle<JSArray> array) {
9418  uint32_t length = static_cast<uint32_t>(array->length()->Number());
9419  int element_count = 0;
9420  switch (array->GetElementsKind()) {
9421    case FAST_SMI_ONLY_ELEMENTS:
9422    case FAST_ELEMENTS: {
9423      // Fast elements can't have lengths that are not representable by
9424      // a 32-bit signed integer.
9425      ASSERT(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
9426      int fast_length = static_cast<int>(length);
9427      Handle<FixedArray> elements(FixedArray::cast(array->elements()));
9428      for (int i = 0; i < fast_length; i++) {
9429        if (!elements->get(i)->IsTheHole()) element_count++;
9430      }
9431      break;
9432    }
9433    case FAST_DOUBLE_ELEMENTS:
9434      // TODO(1810): Decide if it's worthwhile to implement this.
9435      UNREACHABLE();
9436      break;
9437    case DICTIONARY_ELEMENTS: {
9438      Handle<SeededNumberDictionary> dictionary(
9439          SeededNumberDictionary::cast(array->elements()));
9440      int capacity = dictionary->Capacity();
9441      for (int i = 0; i < capacity; i++) {
9442        Handle<Object> key(dictionary->KeyAt(i));
9443        if (dictionary->IsKey(*key)) {
9444          element_count++;
9445        }
9446      }
9447      break;
9448    }
9449    case NON_STRICT_ARGUMENTS_ELEMENTS:
9450    case EXTERNAL_BYTE_ELEMENTS:
9451    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
9452    case EXTERNAL_SHORT_ELEMENTS:
9453    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
9454    case EXTERNAL_INT_ELEMENTS:
9455    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
9456    case EXTERNAL_FLOAT_ELEMENTS:
9457    case EXTERNAL_DOUBLE_ELEMENTS:
9458    case EXTERNAL_PIXEL_ELEMENTS:
9459      // External arrays are always dense.
9460      return length;
9461  }
9462  // As an estimate, we assume that the prototype doesn't contain any
9463  // inherited elements.
9464  return element_count;
9465}
9466
9467
9468
9469template<class ExternalArrayClass, class ElementType>
9470static void IterateExternalArrayElements(Isolate* isolate,
9471                                         Handle<JSObject> receiver,
9472                                         bool elements_are_ints,
9473                                         bool elements_are_guaranteed_smis,
9474                                         ArrayConcatVisitor* visitor) {
9475  Handle<ExternalArrayClass> array(
9476      ExternalArrayClass::cast(receiver->elements()));
9477  uint32_t len = static_cast<uint32_t>(array->length());
9478
9479  ASSERT(visitor != NULL);
9480  if (elements_are_ints) {
9481    if (elements_are_guaranteed_smis) {
9482      for (uint32_t j = 0; j < len; j++) {
9483        HandleScope loop_scope;
9484        Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get_scalar(j))));
9485        visitor->visit(j, e);
9486      }
9487    } else {
9488      for (uint32_t j = 0; j < len; j++) {
9489        HandleScope loop_scope;
9490        int64_t val = static_cast<int64_t>(array->get_scalar(j));
9491        if (Smi::IsValid(static_cast<intptr_t>(val))) {
9492          Handle<Smi> e(Smi::FromInt(static_cast<int>(val)));
9493          visitor->visit(j, e);
9494        } else {
9495          Handle<Object> e =
9496              isolate->factory()->NewNumber(static_cast<ElementType>(val));
9497          visitor->visit(j, e);
9498        }
9499      }
9500    }
9501  } else {
9502    for (uint32_t j = 0; j < len; j++) {
9503      HandleScope loop_scope(isolate);
9504      Handle<Object> e = isolate->factory()->NewNumber(array->get_scalar(j));
9505      visitor->visit(j, e);
9506    }
9507  }
9508}
9509
9510
9511// Used for sorting indices in a List<uint32_t>.
9512static int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
9513  uint32_t a = *ap;
9514  uint32_t b = *bp;
9515  return (a == b) ? 0 : (a < b) ? -1 : 1;
9516}
9517
9518
9519static void CollectElementIndices(Handle<JSObject> object,
9520                                  uint32_t range,
9521                                  List<uint32_t>* indices) {
9522  ElementsKind kind = object->GetElementsKind();
9523  switch (kind) {
9524    case FAST_SMI_ONLY_ELEMENTS:
9525    case FAST_ELEMENTS: {
9526      Handle<FixedArray> elements(FixedArray::cast(object->elements()));
9527      uint32_t length = static_cast<uint32_t>(elements->length());
9528      if (range < length) length = range;
9529      for (uint32_t i = 0; i < length; i++) {
9530        if (!elements->get(i)->IsTheHole()) {
9531          indices->Add(i);
9532        }
9533      }
9534      break;
9535    }
9536    case FAST_DOUBLE_ELEMENTS: {
9537      // TODO(1810): Decide if it's worthwhile to implement this.
9538      UNREACHABLE();
9539      break;
9540    }
9541    case DICTIONARY_ELEMENTS: {
9542      Handle<SeededNumberDictionary> dict(
9543          SeededNumberDictionary::cast(object->elements()));
9544      uint32_t capacity = dict->Capacity();
9545      for (uint32_t j = 0; j < capacity; j++) {
9546        HandleScope loop_scope;
9547        Handle<Object> k(dict->KeyAt(j));
9548        if (dict->IsKey(*k)) {
9549          ASSERT(k->IsNumber());
9550          uint32_t index = static_cast<uint32_t>(k->Number());
9551          if (index < range) {
9552            indices->Add(index);
9553          }
9554        }
9555      }
9556      break;
9557    }
9558    default: {
9559      int dense_elements_length;
9560      switch (kind) {
9561        case EXTERNAL_PIXEL_ELEMENTS: {
9562          dense_elements_length =
9563              ExternalPixelArray::cast(object->elements())->length();
9564          break;
9565        }
9566        case EXTERNAL_BYTE_ELEMENTS: {
9567          dense_elements_length =
9568              ExternalByteArray::cast(object->elements())->length();
9569          break;
9570        }
9571        case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
9572          dense_elements_length =
9573              ExternalUnsignedByteArray::cast(object->elements())->length();
9574          break;
9575        }
9576        case EXTERNAL_SHORT_ELEMENTS: {
9577          dense_elements_length =
9578              ExternalShortArray::cast(object->elements())->length();
9579          break;
9580        }
9581        case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
9582          dense_elements_length =
9583              ExternalUnsignedShortArray::cast(object->elements())->length();
9584          break;
9585        }
9586        case EXTERNAL_INT_ELEMENTS: {
9587          dense_elements_length =
9588              ExternalIntArray::cast(object->elements())->length();
9589          break;
9590        }
9591        case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
9592          dense_elements_length =
9593              ExternalUnsignedIntArray::cast(object->elements())->length();
9594          break;
9595        }
9596        case EXTERNAL_FLOAT_ELEMENTS: {
9597          dense_elements_length =
9598              ExternalFloatArray::cast(object->elements())->length();
9599          break;
9600        }
9601        case EXTERNAL_DOUBLE_ELEMENTS: {
9602          dense_elements_length =
9603              ExternalDoubleArray::cast(object->elements())->length();
9604          break;
9605        }
9606        default:
9607          UNREACHABLE();
9608          dense_elements_length = 0;
9609          break;
9610      }
9611      uint32_t length = static_cast<uint32_t>(dense_elements_length);
9612      if (range <= length) {
9613        length = range;
9614        // We will add all indices, so we might as well clear it first
9615        // and avoid duplicates.
9616        indices->Clear();
9617      }
9618      for (uint32_t i = 0; i < length; i++) {
9619        indices->Add(i);
9620      }
9621      if (length == range) return;  // All indices accounted for already.
9622      break;
9623    }
9624  }
9625
9626  Handle<Object> prototype(object->GetPrototype());
9627  if (prototype->IsJSObject()) {
9628    // The prototype will usually have no inherited element indices,
9629    // but we have to check.
9630    CollectElementIndices(Handle<JSObject>::cast(prototype), range, indices);
9631  }
9632}
9633
9634
9635/**
9636 * A helper function that visits elements of a JSArray in numerical
9637 * order.
9638 *
9639 * The visitor argument called for each existing element in the array
9640 * with the element index and the element's value.
9641 * Afterwards it increments the base-index of the visitor by the array
9642 * length.
9643 * Returns false if any access threw an exception, otherwise true.
9644 */
9645static bool IterateElements(Isolate* isolate,
9646                            Handle<JSArray> receiver,
9647                            ArrayConcatVisitor* visitor) {
9648  uint32_t length = static_cast<uint32_t>(receiver->length()->Number());
9649  switch (receiver->GetElementsKind()) {
9650    case FAST_SMI_ONLY_ELEMENTS:
9651    case FAST_ELEMENTS: {
9652      // Run through the elements FixedArray and use HasElement and GetElement
9653      // to check the prototype for missing elements.
9654      Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
9655      int fast_length = static_cast<int>(length);
9656      ASSERT(fast_length <= elements->length());
9657      for (int j = 0; j < fast_length; j++) {
9658        HandleScope loop_scope(isolate);
9659        Handle<Object> element_value(elements->get(j), isolate);
9660        if (!element_value->IsTheHole()) {
9661          visitor->visit(j, element_value);
9662        } else if (receiver->HasElement(j)) {
9663          // Call GetElement on receiver, not its prototype, or getters won't
9664          // have the correct receiver.
9665          element_value = Object::GetElement(receiver, j);
9666          RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
9667          visitor->visit(j, element_value);
9668        }
9669      }
9670      break;
9671    }
9672    case FAST_DOUBLE_ELEMENTS: {
9673      // TODO(1810): Decide if it's worthwhile to implement this.
9674      UNREACHABLE();
9675      break;
9676    }
9677    case DICTIONARY_ELEMENTS: {
9678      Handle<SeededNumberDictionary> dict(receiver->element_dictionary());
9679      List<uint32_t> indices(dict->Capacity() / 2);
9680      // Collect all indices in the object and the prototypes less
9681      // than length. This might introduce duplicates in the indices list.
9682      CollectElementIndices(receiver, length, &indices);
9683      indices.Sort(&compareUInt32);
9684      int j = 0;
9685      int n = indices.length();
9686      while (j < n) {
9687        HandleScope loop_scope;
9688        uint32_t index = indices[j];
9689        Handle<Object> element = Object::GetElement(receiver, index);
9690        RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element, false);
9691        visitor->visit(index, element);
9692        // Skip to next different index (i.e., omit duplicates).
9693        do {
9694          j++;
9695        } while (j < n && indices[j] == index);
9696      }
9697      break;
9698    }
9699    case EXTERNAL_PIXEL_ELEMENTS: {
9700      Handle<ExternalPixelArray> pixels(ExternalPixelArray::cast(
9701          receiver->elements()));
9702      for (uint32_t j = 0; j < length; j++) {
9703        Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)));
9704        visitor->visit(j, e);
9705      }
9706      break;
9707    }
9708    case EXTERNAL_BYTE_ELEMENTS: {
9709      IterateExternalArrayElements<ExternalByteArray, int8_t>(
9710          isolate, receiver, true, true, visitor);
9711      break;
9712    }
9713    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
9714      IterateExternalArrayElements<ExternalUnsignedByteArray, uint8_t>(
9715          isolate, receiver, true, true, visitor);
9716      break;
9717    }
9718    case EXTERNAL_SHORT_ELEMENTS: {
9719      IterateExternalArrayElements<ExternalShortArray, int16_t>(
9720          isolate, receiver, true, true, visitor);
9721      break;
9722    }
9723    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
9724      IterateExternalArrayElements<ExternalUnsignedShortArray, uint16_t>(
9725          isolate, receiver, true, true, visitor);
9726      break;
9727    }
9728    case EXTERNAL_INT_ELEMENTS: {
9729      IterateExternalArrayElements<ExternalIntArray, int32_t>(
9730          isolate, receiver, true, false, visitor);
9731      break;
9732    }
9733    case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
9734      IterateExternalArrayElements<ExternalUnsignedIntArray, uint32_t>(
9735          isolate, receiver, true, false, visitor);
9736      break;
9737    }
9738    case EXTERNAL_FLOAT_ELEMENTS: {
9739      IterateExternalArrayElements<ExternalFloatArray, float>(
9740          isolate, receiver, false, false, visitor);
9741      break;
9742    }
9743    case EXTERNAL_DOUBLE_ELEMENTS: {
9744      IterateExternalArrayElements<ExternalDoubleArray, double>(
9745          isolate, receiver, false, false, visitor);
9746      break;
9747    }
9748    default:
9749      UNREACHABLE();
9750      break;
9751  }
9752  visitor->increase_index_offset(length);
9753  return true;
9754}
9755
9756
9757/**
9758 * Array::concat implementation.
9759 * See ECMAScript 262, 15.4.4.4.
9760 * TODO(581): Fix non-compliance for very large concatenations and update to
9761 * following the ECMAScript 5 specification.
9762 */
9763RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) {
9764  ASSERT(args.length() == 1);
9765  HandleScope handle_scope(isolate);
9766
9767  CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 0);
9768  int argument_count = static_cast<int>(arguments->length()->Number());
9769  RUNTIME_ASSERT(arguments->HasFastElements());
9770  Handle<FixedArray> elements(FixedArray::cast(arguments->elements()));
9771
9772  // Pass 1: estimate the length and number of elements of the result.
9773  // The actual length can be larger if any of the arguments have getters
9774  // that mutate other arguments (but will otherwise be precise).
9775  // The number of elements is precise if there are no inherited elements.
9776
9777  uint32_t estimate_result_length = 0;
9778  uint32_t estimate_nof_elements = 0;
9779  {
9780    for (int i = 0; i < argument_count; i++) {
9781      HandleScope loop_scope;
9782      Handle<Object> obj(elements->get(i));
9783      uint32_t length_estimate;
9784      uint32_t element_estimate;
9785      if (obj->IsJSArray()) {
9786        Handle<JSArray> array(Handle<JSArray>::cast(obj));
9787        // TODO(1810): Find out if it's worthwhile to properly support
9788        // arbitrary ElementsKinds. For now, pessimistically transition to
9789        // FAST_ELEMENTS.
9790        if (array->HasFastDoubleElements()) {
9791          array = Handle<JSArray>::cast(
9792              JSObject::TransitionElementsKind(array, FAST_ELEMENTS));
9793        }
9794        length_estimate =
9795            static_cast<uint32_t>(array->length()->Number());
9796        element_estimate =
9797            EstimateElementCount(array);
9798      } else {
9799        length_estimate = 1;
9800        element_estimate = 1;
9801      }
9802      // Avoid overflows by capping at kMaxElementCount.
9803      if (JSObject::kMaxElementCount - estimate_result_length <
9804          length_estimate) {
9805        estimate_result_length = JSObject::kMaxElementCount;
9806      } else {
9807        estimate_result_length += length_estimate;
9808      }
9809      if (JSObject::kMaxElementCount - estimate_nof_elements <
9810          element_estimate) {
9811        estimate_nof_elements = JSObject::kMaxElementCount;
9812      } else {
9813        estimate_nof_elements += element_estimate;
9814      }
9815    }
9816  }
9817
9818  // If estimated number of elements is more than half of length, a
9819  // fixed array (fast case) is more time and space-efficient than a
9820  // dictionary.
9821  bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length;
9822
9823  Handle<FixedArray> storage;
9824  if (fast_case) {
9825    // The backing storage array must have non-existing elements to
9826    // preserve holes across concat operations.
9827    storage = isolate->factory()->NewFixedArrayWithHoles(
9828        estimate_result_length);
9829  } else {
9830    // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
9831    uint32_t at_least_space_for = estimate_nof_elements +
9832                                  (estimate_nof_elements >> 2);
9833    storage = Handle<FixedArray>::cast(
9834        isolate->factory()->NewSeededNumberDictionary(at_least_space_for));
9835  }
9836
9837  ArrayConcatVisitor visitor(isolate, storage, fast_case);
9838
9839  for (int i = 0; i < argument_count; i++) {
9840    Handle<Object> obj(elements->get(i));
9841    if (obj->IsJSArray()) {
9842      Handle<JSArray> array = Handle<JSArray>::cast(obj);
9843      if (!IterateElements(isolate, array, &visitor)) {
9844        return Failure::Exception();
9845      }
9846    } else {
9847      visitor.visit(0, obj);
9848      visitor.increase_index_offset(1);
9849    }
9850  }
9851
9852  return *visitor.ToArray();
9853}
9854
9855
9856// This will not allocate (flatten the string), but it may run
9857// very slowly for very deeply nested ConsStrings.  For debugging use only.
9858RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalPrint) {
9859  NoHandleAllocation ha;
9860  ASSERT(args.length() == 1);
9861
9862  CONVERT_ARG_CHECKED(String, string, 0);
9863  StringInputBuffer buffer(string);
9864  while (buffer.has_more()) {
9865    uint16_t character = buffer.GetNext();
9866    PrintF("%c", character);
9867  }
9868  return string;
9869}
9870
9871// Moves all own elements of an object, that are below a limit, to positions
9872// starting at zero. All undefined values are placed after non-undefined values,
9873// and are followed by non-existing element. Does not change the length
9874// property.
9875// Returns the number of non-undefined elements collected.
9876RUNTIME_FUNCTION(MaybeObject*, Runtime_RemoveArrayHoles) {
9877  ASSERT(args.length() == 2);
9878  CONVERT_ARG_CHECKED(JSObject, object, 0);
9879  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
9880  return object->PrepareElementsForSort(limit);
9881}
9882
9883
9884// Move contents of argument 0 (an array) to argument 1 (an array)
9885RUNTIME_FUNCTION(MaybeObject*, Runtime_MoveArrayContents) {
9886  ASSERT(args.length() == 2);
9887  CONVERT_ARG_CHECKED(JSArray, from, 0);
9888  CONVERT_ARG_CHECKED(JSArray, to, 1);
9889  FixedArrayBase* new_elements = from->elements();
9890  MaybeObject* maybe_new_map;
9891  ElementsKind elements_kind;
9892  if (new_elements->map() == isolate->heap()->fixed_array_map() ||
9893      new_elements->map() == isolate->heap()->fixed_cow_array_map()) {
9894    elements_kind = FAST_ELEMENTS;
9895  } else if (new_elements->map() ==
9896             isolate->heap()->fixed_double_array_map()) {
9897    elements_kind = FAST_DOUBLE_ELEMENTS;
9898  } else {
9899    elements_kind = DICTIONARY_ELEMENTS;
9900  }
9901  maybe_new_map = to->GetElementsTransitionMap(isolate, elements_kind);
9902  Object* new_map;
9903  if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
9904  to->set_map(Map::cast(new_map));
9905  to->set_elements(new_elements);
9906  to->set_length(from->length());
9907  Object* obj;
9908  { MaybeObject* maybe_obj = from->ResetElements();
9909    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9910  }
9911  from->set_length(Smi::FromInt(0));
9912  return to;
9913}
9914
9915
9916// How many elements does this object/array have?
9917RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) {
9918  ASSERT(args.length() == 1);
9919  CONVERT_ARG_CHECKED(JSObject, object, 0);
9920  HeapObject* elements = object->elements();
9921  if (elements->IsDictionary()) {
9922    int result = SeededNumberDictionary::cast(elements)->NumberOfElements();
9923    return Smi::FromInt(result);
9924  } else if (object->IsJSArray()) {
9925    return JSArray::cast(object)->length();
9926  } else {
9927    return Smi::FromInt(FixedArray::cast(elements)->length());
9928  }
9929}
9930
9931
9932// Returns an array that tells you where in the [0, length) interval an array
9933// might have elements.  Can either return keys (positive integers) or
9934// intervals (pair of a negative integer (-start-1) followed by a
9935// positive (length)) or undefined values.
9936// Intervals can span over some keys that are not in the object.
9937RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
9938  ASSERT(args.length() == 2);
9939  HandleScope scope(isolate);
9940  CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
9941  CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
9942  if (array->elements()->IsDictionary()) {
9943    // Create an array and get all the keys into it, then remove all the
9944    // keys that are not integers in the range 0 to length-1.
9945    bool threw = false;
9946    Handle<FixedArray> keys =
9947        GetKeysInFixedArrayFor(array, INCLUDE_PROTOS, &threw);
9948    if (threw) return Failure::Exception();
9949
9950    int keys_length = keys->length();
9951    for (int i = 0; i < keys_length; i++) {
9952      Object* key = keys->get(i);
9953      uint32_t index = 0;
9954      if (!key->ToArrayIndex(&index) || index >= length) {
9955        // Zap invalid keys.
9956        keys->set_undefined(i);
9957      }
9958    }
9959    return *isolate->factory()->NewJSArrayWithElements(keys);
9960  } else {
9961    ASSERT(array->HasFastElements() ||
9962           array->HasFastSmiOnlyElements() ||
9963           array->HasFastDoubleElements());
9964    Handle<FixedArray> single_interval = isolate->factory()->NewFixedArray(2);
9965    // -1 means start of array.
9966    single_interval->set(0, Smi::FromInt(-1));
9967    FixedArrayBase* elements = FixedArrayBase::cast(array->elements());
9968    uint32_t actual_length =
9969        static_cast<uint32_t>(elements->length());
9970    uint32_t min_length = actual_length < length ? actual_length : length;
9971    Handle<Object> length_object =
9972        isolate->factory()->NewNumber(static_cast<double>(min_length));
9973    single_interval->set(1, *length_object);
9974    return *isolate->factory()->NewJSArrayWithElements(single_interval);
9975  }
9976}
9977
9978
9979RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) {
9980  ASSERT(args.length() == 3);
9981  CONVERT_ARG_CHECKED(JSObject, obj, 0);
9982  CONVERT_ARG_CHECKED(String, name, 1);
9983  CONVERT_SMI_ARG_CHECKED(flag, 2);
9984  AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
9985  return obj->LookupAccessor(name, component);
9986}
9987
9988
9989#ifdef ENABLE_DEBUGGER_SUPPORT
9990RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugBreak) {
9991  ASSERT(args.length() == 0);
9992  return Execution::DebugBreakHelper();
9993}
9994
9995
9996// Helper functions for wrapping and unwrapping stack frame ids.
9997static Smi* WrapFrameId(StackFrame::Id id) {
9998  ASSERT(IsAligned(OffsetFrom(id), static_cast<intptr_t>(4)));
9999  return Smi::FromInt(id >> 2);
10000}
10001
10002
10003static StackFrame::Id UnwrapFrameId(int wrapped) {
10004  return static_cast<StackFrame::Id>(wrapped << 2);
10005}
10006
10007
10008// Adds a JavaScript function as a debug event listener.
10009// args[0]: debug event listener function to set or null or undefined for
10010//          clearing the event listener function
10011// args[1]: object supplied during callback
10012RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDebugEventListener) {
10013  ASSERT(args.length() == 2);
10014  RUNTIME_ASSERT(args[0]->IsJSFunction() ||
10015                 args[0]->IsUndefined() ||
10016                 args[0]->IsNull());
10017  Handle<Object> callback = args.at<Object>(0);
10018  Handle<Object> data = args.at<Object>(1);
10019  isolate->debugger()->SetEventListener(callback, data);
10020
10021  return isolate->heap()->undefined_value();
10022}
10023
10024
10025RUNTIME_FUNCTION(MaybeObject*, Runtime_Break) {
10026  ASSERT(args.length() == 0);
10027  isolate->stack_guard()->DebugBreak();
10028  return isolate->heap()->undefined_value();
10029}
10030
10031
10032static MaybeObject* DebugLookupResultValue(Heap* heap,
10033                                           Object* receiver,
10034                                           String* name,
10035                                           LookupResult* result,
10036                                           bool* caught_exception) {
10037  Object* value;
10038  switch (result->type()) {
10039    case NORMAL:
10040      value = result->holder()->GetNormalizedProperty(result);
10041      if (value->IsTheHole()) {
10042        return heap->undefined_value();
10043      }
10044      return value;
10045    case FIELD:
10046      value =
10047          JSObject::cast(
10048              result->holder())->FastPropertyAt(result->GetFieldIndex());
10049      if (value->IsTheHole()) {
10050        return heap->undefined_value();
10051      }
10052      return value;
10053    case CONSTANT_FUNCTION:
10054      return result->GetConstantFunction();
10055    case CALLBACKS: {
10056      Object* structure = result->GetCallbackObject();
10057      if (structure->IsForeign() || structure->IsAccessorInfo()) {
10058        MaybeObject* maybe_value = result->holder()->GetPropertyWithCallback(
10059            receiver, structure, name);
10060        if (!maybe_value->ToObject(&value)) {
10061          if (maybe_value->IsRetryAfterGC()) return maybe_value;
10062          ASSERT(maybe_value->IsException());
10063          maybe_value = heap->isolate()->pending_exception();
10064          heap->isolate()->clear_pending_exception();
10065          if (caught_exception != NULL) {
10066            *caught_exception = true;
10067          }
10068          return maybe_value;
10069        }
10070        return value;
10071      } else {
10072        return heap->undefined_value();
10073      }
10074    }
10075    case INTERCEPTOR:
10076    case MAP_TRANSITION:
10077    case ELEMENTS_TRANSITION:
10078    case CONSTANT_TRANSITION:
10079    case NULL_DESCRIPTOR:
10080      return heap->undefined_value();
10081    case HANDLER:
10082      UNREACHABLE();
10083      return heap->undefined_value();
10084  }
10085  UNREACHABLE();  // keep the compiler happy
10086  return heap->undefined_value();
10087}
10088
10089
10090// Get debugger related details for an object property.
10091// args[0]: object holding property
10092// args[1]: name of the property
10093//
10094// The array returned contains the following information:
10095// 0: Property value
10096// 1: Property details
10097// 2: Property value is exception
10098// 3: Getter function if defined
10099// 4: Setter function if defined
10100// Items 2-4 are only filled if the property has either a getter or a setter
10101// defined through __defineGetter__ and/or __defineSetter__.
10102RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) {
10103  HandleScope scope(isolate);
10104
10105  ASSERT(args.length() == 2);
10106
10107  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10108  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
10109
10110  // Make sure to set the current context to the context before the debugger was
10111  // entered (if the debugger is entered). The reason for switching context here
10112  // is that for some property lookups (accessors and interceptors) callbacks
10113  // into the embedding application can occour, and the embedding application
10114  // could have the assumption that its own global context is the current
10115  // context and not some internal debugger context.
10116  SaveContext save(isolate);
10117  if (isolate->debug()->InDebugger()) {
10118    isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
10119  }
10120
10121  // Skip the global proxy as it has no properties and always delegates to the
10122  // real global object.
10123  if (obj->IsJSGlobalProxy()) {
10124    obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
10125  }
10126
10127
10128  // Check if the name is trivially convertible to an index and get the element
10129  // if so.
10130  uint32_t index;
10131  if (name->AsArrayIndex(&index)) {
10132    Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
10133    Object* element_or_char;
10134    { MaybeObject* maybe_element_or_char =
10135          Runtime::GetElementOrCharAt(isolate, obj, index);
10136      if (!maybe_element_or_char->ToObject(&element_or_char)) {
10137        return maybe_element_or_char;
10138      }
10139    }
10140    details->set(0, element_or_char);
10141    details->set(1, PropertyDetails(NONE, NORMAL).AsSmi());
10142    return *isolate->factory()->NewJSArrayWithElements(details);
10143  }
10144
10145  // Find the number of objects making up this.
10146  int length = LocalPrototypeChainLength(*obj);
10147
10148  // Try local lookup on each of the objects.
10149  Handle<JSObject> jsproto = obj;
10150  for (int i = 0; i < length; i++) {
10151    LookupResult result(isolate);
10152    jsproto->LocalLookup(*name, &result);
10153    if (result.IsProperty()) {
10154      // LookupResult is not GC safe as it holds raw object pointers.
10155      // GC can happen later in this code so put the required fields into
10156      // local variables using handles when required for later use.
10157      PropertyType result_type = result.type();
10158      Handle<Object> result_callback_obj;
10159      if (result_type == CALLBACKS) {
10160        result_callback_obj = Handle<Object>(result.GetCallbackObject(),
10161                                             isolate);
10162      }
10163      Smi* property_details = result.GetPropertyDetails().AsSmi();
10164      // DebugLookupResultValue can cause GC so details from LookupResult needs
10165      // to be copied to handles before this.
10166      bool caught_exception = false;
10167      Object* raw_value;
10168      { MaybeObject* maybe_raw_value =
10169            DebugLookupResultValue(isolate->heap(), *obj, *name,
10170                                   &result, &caught_exception);
10171        if (!maybe_raw_value->ToObject(&raw_value)) return maybe_raw_value;
10172      }
10173      Handle<Object> value(raw_value, isolate);
10174
10175      // If the callback object is a fixed array then it contains JavaScript
10176      // getter and/or setter.
10177      bool hasJavaScriptAccessors = result_type == CALLBACKS &&
10178                                    result_callback_obj->IsAccessorPair();
10179      Handle<FixedArray> details =
10180          isolate->factory()->NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
10181      details->set(0, *value);
10182      details->set(1, property_details);
10183      if (hasJavaScriptAccessors) {
10184        AccessorPair* accessors = AccessorPair::cast(*result_callback_obj);
10185        details->set(2, isolate->heap()->ToBoolean(caught_exception));
10186        details->set(3, accessors->GetComponent(ACCESSOR_GETTER));
10187        details->set(4, accessors->GetComponent(ACCESSOR_SETTER));
10188      }
10189
10190      return *isolate->factory()->NewJSArrayWithElements(details);
10191    }
10192    if (i < length - 1) {
10193      jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
10194    }
10195  }
10196
10197  return isolate->heap()->undefined_value();
10198}
10199
10200
10201RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetProperty) {
10202  HandleScope scope(isolate);
10203
10204  ASSERT(args.length() == 2);
10205
10206  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10207  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
10208
10209  LookupResult result(isolate);
10210  obj->Lookup(*name, &result);
10211  if (result.IsProperty()) {
10212    return DebugLookupResultValue(isolate->heap(), *obj, *name, &result, NULL);
10213  }
10214  return isolate->heap()->undefined_value();
10215}
10216
10217
10218// Return the property type calculated from the property details.
10219// args[0]: smi with property details.
10220RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyTypeFromDetails) {
10221  ASSERT(args.length() == 1);
10222  CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
10223  return Smi::FromInt(static_cast<int>(details.type()));
10224}
10225
10226
10227// Return the property attribute calculated from the property details.
10228// args[0]: smi with property details.
10229RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyAttributesFromDetails) {
10230  ASSERT(args.length() == 1);
10231  CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
10232  return Smi::FromInt(static_cast<int>(details.attributes()));
10233}
10234
10235
10236// Return the property insertion index calculated from the property details.
10237// args[0]: smi with property details.
10238RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyIndexFromDetails) {
10239  ASSERT(args.length() == 1);
10240  CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
10241  return Smi::FromInt(details.index());
10242}
10243
10244
10245// Return property value from named interceptor.
10246// args[0]: object
10247// args[1]: property name
10248RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugNamedInterceptorPropertyValue) {
10249  HandleScope scope(isolate);
10250  ASSERT(args.length() == 2);
10251  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10252  RUNTIME_ASSERT(obj->HasNamedInterceptor());
10253  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
10254
10255  PropertyAttributes attributes;
10256  return obj->GetPropertyWithInterceptor(*obj, *name, &attributes);
10257}
10258
10259
10260// Return element value from indexed interceptor.
10261// args[0]: object
10262// args[1]: index
10263RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugIndexedInterceptorElementValue) {
10264  HandleScope scope(isolate);
10265  ASSERT(args.length() == 2);
10266  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10267  RUNTIME_ASSERT(obj->HasIndexedInterceptor());
10268  CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
10269
10270  return obj->GetElementWithInterceptor(*obj, index);
10271}
10272
10273
10274RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckExecutionState) {
10275  ASSERT(args.length() >= 1);
10276  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
10277  // Check that the break id is valid.
10278  if (isolate->debug()->break_id() == 0 ||
10279      break_id != isolate->debug()->break_id()) {
10280    return isolate->Throw(
10281        isolate->heap()->illegal_execution_state_symbol());
10282  }
10283
10284  return isolate->heap()->true_value();
10285}
10286
10287
10288RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) {
10289  HandleScope scope(isolate);
10290  ASSERT(args.length() == 1);
10291
10292  // Check arguments.
10293  Object* result;
10294  { MaybeObject* maybe_result = Runtime_CheckExecutionState(
10295      RUNTIME_ARGUMENTS(isolate, args));
10296    if (!maybe_result->ToObject(&result)) return maybe_result;
10297  }
10298
10299  // Count all frames which are relevant to debugging stack trace.
10300  int n = 0;
10301  StackFrame::Id id = isolate->debug()->break_frame_id();
10302  if (id == StackFrame::NO_ID) {
10303    // If there is no JavaScript stack frame count is 0.
10304    return Smi::FromInt(0);
10305  }
10306
10307  for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) {
10308    n += it.frame()->GetInlineCount();
10309  }
10310  return Smi::FromInt(n);
10311}
10312
10313
10314class FrameInspector {
10315 public:
10316  FrameInspector(JavaScriptFrame* frame,
10317                 int inlined_jsframe_index,
10318                 Isolate* isolate)
10319      : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
10320    // Calculate the deoptimized frame.
10321    if (frame->is_optimized()) {
10322      deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
10323          frame, inlined_jsframe_index, isolate);
10324    }
10325    has_adapted_arguments_ = frame_->has_adapted_arguments();
10326    is_bottommost_ = inlined_jsframe_index == 0;
10327    is_optimized_ = frame_->is_optimized();
10328  }
10329
10330  ~FrameInspector() {
10331    // Get rid of the calculated deoptimized frame if any.
10332    if (deoptimized_frame_ != NULL) {
10333      Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_,
10334                                                  isolate_);
10335    }
10336  }
10337
10338  int GetParametersCount() {
10339    return is_optimized_
10340        ? deoptimized_frame_->parameters_count()
10341        : frame_->ComputeParametersCount();
10342  }
10343  int expression_count() { return deoptimized_frame_->expression_count(); }
10344  Object* GetFunction() {
10345    return is_optimized_
10346        ? deoptimized_frame_->GetFunction()
10347        : frame_->function();
10348  }
10349  Object* GetParameter(int index) {
10350    return is_optimized_
10351        ? deoptimized_frame_->GetParameter(index)
10352        : frame_->GetParameter(index);
10353  }
10354  Object* GetExpression(int index) {
10355    return is_optimized_
10356        ? deoptimized_frame_->GetExpression(index)
10357        : frame_->GetExpression(index);
10358  }
10359  int GetSourcePosition() {
10360    return is_optimized_
10361        ? deoptimized_frame_->GetSourcePosition()
10362        : frame_->LookupCode()->SourcePosition(frame_->pc());
10363  }
10364  bool IsConstructor() {
10365    return is_optimized_ && !is_bottommost_
10366        ? deoptimized_frame_->HasConstructStub()
10367        : frame_->IsConstructor();
10368  }
10369
10370  // To inspect all the provided arguments the frame might need to be
10371  // replaced with the arguments frame.
10372  void SetArgumentsFrame(JavaScriptFrame* frame) {
10373    ASSERT(has_adapted_arguments_);
10374    frame_ = frame;
10375    is_optimized_ = frame_->is_optimized();
10376    ASSERT(!is_optimized_);
10377  }
10378
10379 private:
10380  JavaScriptFrame* frame_;
10381  DeoptimizedFrameInfo* deoptimized_frame_;
10382  Isolate* isolate_;
10383  bool is_optimized_;
10384  bool is_bottommost_;
10385  bool has_adapted_arguments_;
10386
10387  DISALLOW_COPY_AND_ASSIGN(FrameInspector);
10388};
10389
10390
10391static const int kFrameDetailsFrameIdIndex = 0;
10392static const int kFrameDetailsReceiverIndex = 1;
10393static const int kFrameDetailsFunctionIndex = 2;
10394static const int kFrameDetailsArgumentCountIndex = 3;
10395static const int kFrameDetailsLocalCountIndex = 4;
10396static const int kFrameDetailsSourcePositionIndex = 5;
10397static const int kFrameDetailsConstructCallIndex = 6;
10398static const int kFrameDetailsAtReturnIndex = 7;
10399static const int kFrameDetailsFlagsIndex = 8;
10400static const int kFrameDetailsFirstDynamicIndex = 9;
10401
10402
10403static SaveContext* FindSavedContextForFrame(Isolate* isolate,
10404                                             JavaScriptFrame* frame) {
10405  SaveContext* save = isolate->save_context();
10406  while (save != NULL && !save->IsBelowFrame(frame)) {
10407    save = save->prev();
10408  }
10409  ASSERT(save != NULL);
10410  return save;
10411}
10412
10413
10414// Return an array with frame details
10415// args[0]: number: break id
10416// args[1]: number: frame index
10417//
10418// The array returned contains the following information:
10419// 0: Frame id
10420// 1: Receiver
10421// 2: Function
10422// 3: Argument count
10423// 4: Local count
10424// 5: Source position
10425// 6: Constructor call
10426// 7: Is at return
10427// 8: Flags
10428// Arguments name, value
10429// Locals name, value
10430// Return value if any
10431RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
10432  HandleScope scope(isolate);
10433  ASSERT(args.length() == 2);
10434
10435  // Check arguments.
10436  Object* check;
10437  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
10438      RUNTIME_ARGUMENTS(isolate, args));
10439    if (!maybe_check->ToObject(&check)) return maybe_check;
10440  }
10441  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
10442  Heap* heap = isolate->heap();
10443
10444  // Find the relevant frame with the requested index.
10445  StackFrame::Id id = isolate->debug()->break_frame_id();
10446  if (id == StackFrame::NO_ID) {
10447    // If there are no JavaScript stack frames return undefined.
10448    return heap->undefined_value();
10449  }
10450
10451  int count = 0;
10452  JavaScriptFrameIterator it(isolate, id);
10453  for (; !it.done(); it.Advance()) {
10454    if (index < count + it.frame()->GetInlineCount()) break;
10455    count += it.frame()->GetInlineCount();
10456  }
10457  if (it.done()) return heap->undefined_value();
10458
10459  bool is_optimized = it.frame()->is_optimized();
10460
10461  int inlined_jsframe_index = 0;  // Inlined frame index in optimized frame.
10462  if (is_optimized) {
10463    inlined_jsframe_index =
10464        it.frame()->GetInlineCount() - (index - count) - 1;
10465  }
10466  FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate);
10467
10468  // Traverse the saved contexts chain to find the active context for the
10469  // selected frame.
10470  SaveContext* save = FindSavedContextForFrame(isolate, it.frame());
10471
10472  // Get the frame id.
10473  Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate);
10474
10475  // Find source position in unoptimized code.
10476  int position = frame_inspector.GetSourcePosition();
10477
10478  // Check for constructor frame.
10479  bool constructor = frame_inspector.IsConstructor();
10480
10481  // Get scope info and read from it for local variable information.
10482  Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
10483  Handle<SharedFunctionInfo> shared(function->shared());
10484  Handle<ScopeInfo> scope_info(shared->scope_info());
10485  ASSERT(*scope_info != ScopeInfo::Empty());
10486
10487  // Get the locals names and values into a temporary array.
10488  //
10489  // TODO(1240907): Hide compiler-introduced stack variables
10490  // (e.g. .result)?  For users of the debugger, they will probably be
10491  // confusing.
10492  Handle<FixedArray> locals =
10493      isolate->factory()->NewFixedArray(scope_info->LocalCount() * 2);
10494
10495  // Fill in the values of the locals.
10496  int i = 0;
10497  for (; i < scope_info->StackLocalCount(); ++i) {
10498    // Use the value from the stack.
10499    locals->set(i * 2, scope_info->LocalName(i));
10500    locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
10501  }
10502  if (i < scope_info->LocalCount()) {
10503    // Get the context containing declarations.
10504    Handle<Context> context(
10505        Context::cast(it.frame()->context())->declaration_context());
10506    for (; i < scope_info->LocalCount(); ++i) {
10507      Handle<String> name(scope_info->LocalName(i));
10508      VariableMode mode;
10509      InitializationFlag init_flag;
10510      locals->set(i * 2, *name);
10511      locals->set(i * 2 + 1, context->get(
10512          scope_info->ContextSlotIndex(*name, &mode, &init_flag)));
10513    }
10514  }
10515
10516  // Check whether this frame is positioned at return. If not top
10517  // frame or if the frame is optimized it cannot be at a return.
10518  bool at_return = false;
10519  if (!is_optimized && index == 0) {
10520    at_return = isolate->debug()->IsBreakAtReturn(it.frame());
10521  }
10522
10523  // If positioned just before return find the value to be returned and add it
10524  // to the frame information.
10525  Handle<Object> return_value = isolate->factory()->undefined_value();
10526  if (at_return) {
10527    StackFrameIterator it2(isolate);
10528    Address internal_frame_sp = NULL;
10529    while (!it2.done()) {
10530      if (it2.frame()->is_internal()) {
10531        internal_frame_sp = it2.frame()->sp();
10532      } else {
10533        if (it2.frame()->is_java_script()) {
10534          if (it2.frame()->id() == it.frame()->id()) {
10535            // The internal frame just before the JavaScript frame contains the
10536            // value to return on top. A debug break at return will create an
10537            // internal frame to store the return value (eax/rax/r0) before
10538            // entering the debug break exit frame.
10539            if (internal_frame_sp != NULL) {
10540              return_value =
10541                  Handle<Object>(Memory::Object_at(internal_frame_sp),
10542                                 isolate);
10543              break;
10544            }
10545          }
10546        }
10547
10548        // Indicate that the previous frame was not an internal frame.
10549        internal_frame_sp = NULL;
10550      }
10551      it2.Advance();
10552    }
10553  }
10554
10555  // Now advance to the arguments adapter frame (if any). It contains all
10556  // the provided parameters whereas the function frame always have the number
10557  // of arguments matching the functions parameters. The rest of the
10558  // information (except for what is collected above) is the same.
10559  if ((inlined_jsframe_index == 0) && it.frame()->has_adapted_arguments()) {
10560    it.AdvanceToArgumentsFrame();
10561    frame_inspector.SetArgumentsFrame(it.frame());
10562  }
10563
10564  // Find the number of arguments to fill. At least fill the number of
10565  // parameters for the function and fill more if more parameters are provided.
10566  int argument_count = scope_info->ParameterCount();
10567  if (argument_count < frame_inspector.GetParametersCount()) {
10568    argument_count = frame_inspector.GetParametersCount();
10569  }
10570
10571  // Calculate the size of the result.
10572  int details_size = kFrameDetailsFirstDynamicIndex +
10573                     2 * (argument_count + scope_info->LocalCount()) +
10574                     (at_return ? 1 : 0);
10575  Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
10576
10577  // Add the frame id.
10578  details->set(kFrameDetailsFrameIdIndex, *frame_id);
10579
10580  // Add the function (same as in function frame).
10581  details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
10582
10583  // Add the arguments count.
10584  details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
10585
10586  // Add the locals count
10587  details->set(kFrameDetailsLocalCountIndex,
10588               Smi::FromInt(scope_info->LocalCount()));
10589
10590  // Add the source position.
10591  if (position != RelocInfo::kNoPosition) {
10592    details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
10593  } else {
10594    details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
10595  }
10596
10597  // Add the constructor information.
10598  details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
10599
10600  // Add the at return information.
10601  details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
10602
10603  // Add flags to indicate information on whether this frame is
10604  //   bit 0: invoked in the debugger context.
10605  //   bit 1: optimized frame.
10606  //   bit 2: inlined in optimized frame
10607  int flags = 0;
10608  if (*save->context() == *isolate->debug()->debug_context()) {
10609    flags |= 1 << 0;
10610  }
10611  if (is_optimized) {
10612    flags |= 1 << 1;
10613    flags |= inlined_jsframe_index << 2;
10614  }
10615  details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
10616
10617  // Fill the dynamic part.
10618  int details_index = kFrameDetailsFirstDynamicIndex;
10619
10620  // Add arguments name and value.
10621  for (int i = 0; i < argument_count; i++) {
10622    // Name of the argument.
10623    if (i < scope_info->ParameterCount()) {
10624      details->set(details_index++, scope_info->ParameterName(i));
10625    } else {
10626      details->set(details_index++, heap->undefined_value());
10627    }
10628
10629    // Parameter value.
10630    if (i < frame_inspector.GetParametersCount()) {
10631      // Get the value from the stack.
10632      details->set(details_index++, frame_inspector.GetParameter(i));
10633    } else {
10634      details->set(details_index++, heap->undefined_value());
10635    }
10636  }
10637
10638  // Add locals name and value from the temporary copy from the function frame.
10639  for (int i = 0; i < scope_info->LocalCount() * 2; i++) {
10640    details->set(details_index++, locals->get(i));
10641  }
10642
10643  // Add the value being returned.
10644  if (at_return) {
10645    details->set(details_index++, *return_value);
10646  }
10647
10648  // Add the receiver (same as in function frame).
10649  // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
10650  // THE FRAME ITERATOR TO WRAP THE RECEIVER.
10651  Handle<Object> receiver(it.frame()->receiver(), isolate);
10652  if (!receiver->IsJSObject() &&
10653      shared->is_classic_mode() &&
10654      !shared->native()) {
10655    // If the receiver is not a JSObject and the function is not a
10656    // builtin or strict-mode we have hit an optimization where a
10657    // value object is not converted into a wrapped JS objects. To
10658    // hide this optimization from the debugger, we wrap the receiver
10659    // by creating correct wrapper object based on the calling frame's
10660    // global context.
10661    it.Advance();
10662    Handle<Context> calling_frames_global_context(
10663        Context::cast(Context::cast(it.frame()->context())->global_context()));
10664    receiver =
10665        isolate->factory()->ToObject(receiver, calling_frames_global_context);
10666  }
10667  details->set(kFrameDetailsReceiverIndex, *receiver);
10668
10669  ASSERT_EQ(details_size, details_index);
10670  return *isolate->factory()->NewJSArrayWithElements(details);
10671}
10672
10673
10674// Copy all the context locals into an object used to materialize a scope.
10675static bool CopyContextLocalsToScopeObject(
10676    Isolate* isolate,
10677    Handle<ScopeInfo> scope_info,
10678    Handle<Context> context,
10679    Handle<JSObject> scope_object) {
10680  // Fill all context locals to the context extension.
10681  for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
10682    VariableMode mode;
10683    InitializationFlag init_flag;
10684    int context_index = scope_info->ContextSlotIndex(
10685        scope_info->ContextLocalName(i), &mode, &init_flag);
10686
10687    RETURN_IF_EMPTY_HANDLE_VALUE(
10688        isolate,
10689        SetProperty(scope_object,
10690                    Handle<String>(scope_info->ContextLocalName(i)),
10691                    Handle<Object>(context->get(context_index), isolate),
10692                    NONE,
10693                    kNonStrictMode),
10694        false);
10695  }
10696
10697  return true;
10698}
10699
10700
10701// Create a plain JSObject which materializes the local scope for the specified
10702// frame.
10703static Handle<JSObject> MaterializeLocalScopeWithFrameInspector(
10704    Isolate* isolate,
10705    JavaScriptFrame* frame,
10706    FrameInspector* frame_inspector) {
10707  Handle<JSFunction> function(JSFunction::cast(frame_inspector->GetFunction()));
10708  Handle<SharedFunctionInfo> shared(function->shared());
10709  Handle<ScopeInfo> scope_info(shared->scope_info());
10710
10711  // Allocate and initialize a JSObject with all the arguments, stack locals
10712  // heap locals and extension properties of the debugged function.
10713  Handle<JSObject> local_scope =
10714      isolate->factory()->NewJSObject(isolate->object_function());
10715
10716  // First fill all parameters.
10717  for (int i = 0; i < scope_info->ParameterCount(); ++i) {
10718    Handle<Object> value(
10719        i < frame_inspector->GetParametersCount() ?
10720        frame_inspector->GetParameter(i) : isolate->heap()->undefined_value());
10721
10722    RETURN_IF_EMPTY_HANDLE_VALUE(
10723        isolate,
10724        SetProperty(local_scope,
10725                    Handle<String>(scope_info->ParameterName(i)),
10726                    value,
10727                    NONE,
10728                    kNonStrictMode),
10729        Handle<JSObject>());
10730  }
10731
10732  // Second fill all stack locals.
10733  for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
10734    RETURN_IF_EMPTY_HANDLE_VALUE(
10735        isolate,
10736        SetProperty(local_scope,
10737                    Handle<String>(scope_info->StackLocalName(i)),
10738                    Handle<Object>(frame_inspector->GetExpression(i)),
10739                    NONE,
10740                    kNonStrictMode),
10741        Handle<JSObject>());
10742  }
10743
10744  if (scope_info->HasContext()) {
10745    // Third fill all context locals.
10746    Handle<Context> frame_context(Context::cast(frame->context()));
10747    Handle<Context> function_context(frame_context->declaration_context());
10748    if (!CopyContextLocalsToScopeObject(
10749            isolate, scope_info, function_context, local_scope)) {
10750      return Handle<JSObject>();
10751    }
10752
10753    // Finally copy any properties from the function context extension.
10754    // These will be variables introduced by eval.
10755    if (function_context->closure() == *function) {
10756      if (function_context->has_extension() &&
10757          !function_context->IsGlobalContext()) {
10758        Handle<JSObject> ext(JSObject::cast(function_context->extension()));
10759        bool threw = false;
10760        Handle<FixedArray> keys =
10761            GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
10762        if (threw) return Handle<JSObject>();
10763
10764        for (int i = 0; i < keys->length(); i++) {
10765          // Names of variables introduced by eval are strings.
10766          ASSERT(keys->get(i)->IsString());
10767          Handle<String> key(String::cast(keys->get(i)));
10768          RETURN_IF_EMPTY_HANDLE_VALUE(
10769              isolate,
10770              SetProperty(local_scope,
10771                          key,
10772                          GetProperty(ext, key),
10773                          NONE,
10774                          kNonStrictMode),
10775              Handle<JSObject>());
10776        }
10777      }
10778    }
10779  }
10780
10781  return local_scope;
10782}
10783
10784
10785static Handle<JSObject> MaterializeLocalScope(
10786    Isolate* isolate,
10787    JavaScriptFrame* frame,
10788    int inlined_jsframe_index) {
10789  FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
10790  return MaterializeLocalScopeWithFrameInspector(isolate,
10791                                                 frame,
10792                                                 &frame_inspector);
10793}
10794
10795
10796// Create a plain JSObject which materializes the closure content for the
10797// context.
10798static Handle<JSObject> MaterializeClosure(Isolate* isolate,
10799                                           Handle<Context> context) {
10800  ASSERT(context->IsFunctionContext());
10801
10802  Handle<SharedFunctionInfo> shared(context->closure()->shared());
10803  Handle<ScopeInfo> scope_info(shared->scope_info());
10804
10805  // Allocate and initialize a JSObject with all the content of this function
10806  // closure.
10807  Handle<JSObject> closure_scope =
10808      isolate->factory()->NewJSObject(isolate->object_function());
10809
10810  // Fill all context locals to the context extension.
10811  if (!CopyContextLocalsToScopeObject(
10812          isolate, scope_info, context, closure_scope)) {
10813    return Handle<JSObject>();
10814  }
10815
10816  // Finally copy any properties from the function context extension. This will
10817  // be variables introduced by eval.
10818  if (context->has_extension()) {
10819    Handle<JSObject> ext(JSObject::cast(context->extension()));
10820    bool threw = false;
10821    Handle<FixedArray> keys =
10822        GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
10823    if (threw) return Handle<JSObject>();
10824
10825    for (int i = 0; i < keys->length(); i++) {
10826      // Names of variables introduced by eval are strings.
10827      ASSERT(keys->get(i)->IsString());
10828      Handle<String> key(String::cast(keys->get(i)));
10829       RETURN_IF_EMPTY_HANDLE_VALUE(
10830          isolate,
10831          SetProperty(closure_scope,
10832                      key,
10833                      GetProperty(ext, key),
10834                      NONE,
10835                      kNonStrictMode),
10836          Handle<JSObject>());
10837    }
10838  }
10839
10840  return closure_scope;
10841}
10842
10843
10844// Create a plain JSObject which materializes the scope for the specified
10845// catch context.
10846static Handle<JSObject> MaterializeCatchScope(Isolate* isolate,
10847                                              Handle<Context> context) {
10848  ASSERT(context->IsCatchContext());
10849  Handle<String> name(String::cast(context->extension()));
10850  Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX));
10851  Handle<JSObject> catch_scope =
10852      isolate->factory()->NewJSObject(isolate->object_function());
10853  RETURN_IF_EMPTY_HANDLE_VALUE(
10854      isolate,
10855      SetProperty(catch_scope, name, thrown_object, NONE, kNonStrictMode),
10856      Handle<JSObject>());
10857  return catch_scope;
10858}
10859
10860
10861// Create a plain JSObject which materializes the block scope for the specified
10862// block context.
10863static Handle<JSObject> MaterializeBlockScope(
10864    Isolate* isolate,
10865    Handle<Context> context) {
10866  ASSERT(context->IsBlockContext());
10867  Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
10868
10869  // Allocate and initialize a JSObject with all the arguments, stack locals
10870  // heap locals and extension properties of the debugged function.
10871  Handle<JSObject> block_scope =
10872      isolate->factory()->NewJSObject(isolate->object_function());
10873
10874  // Fill all context locals.
10875  if (!CopyContextLocalsToScopeObject(
10876          isolate, scope_info, context, block_scope)) {
10877    return Handle<JSObject>();
10878  }
10879
10880  return block_scope;
10881}
10882
10883
10884// Create a plain JSObject which materializes the module scope for the specified
10885// module context.
10886static Handle<JSObject> MaterializeModuleScope(
10887    Isolate* isolate,
10888    Handle<Context> context) {
10889  ASSERT(context->IsModuleContext());
10890  Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
10891
10892  // Allocate and initialize a JSObject with all the members of the debugged
10893  // module.
10894  Handle<JSObject> module_scope =
10895      isolate->factory()->NewJSObject(isolate->object_function());
10896
10897  // Fill all context locals.
10898  if (!CopyContextLocalsToScopeObject(
10899          isolate, scope_info, context, module_scope)) {
10900    return Handle<JSObject>();
10901  }
10902
10903  return module_scope;
10904}
10905
10906
10907// Iterate over the actual scopes visible from a stack frame. The iteration
10908// proceeds from the innermost visible nested scope outwards. All scopes are
10909// backed by an actual context except the local scope, which is inserted
10910// "artificially" in the context chain.
10911class ScopeIterator {
10912 public:
10913  enum ScopeType {
10914    ScopeTypeGlobal = 0,
10915    ScopeTypeLocal,
10916    ScopeTypeWith,
10917    ScopeTypeClosure,
10918    ScopeTypeCatch,
10919    ScopeTypeBlock,
10920    ScopeTypeModule
10921  };
10922
10923  ScopeIterator(Isolate* isolate,
10924                JavaScriptFrame* frame,
10925                int inlined_jsframe_index)
10926    : isolate_(isolate),
10927      frame_(frame),
10928      inlined_jsframe_index_(inlined_jsframe_index),
10929      function_(JSFunction::cast(frame->function())),
10930      context_(Context::cast(frame->context())),
10931      nested_scope_chain_(4) {
10932
10933    // Catch the case when the debugger stops in an internal function.
10934    Handle<SharedFunctionInfo> shared_info(function_->shared());
10935    Handle<ScopeInfo> scope_info(shared_info->scope_info());
10936    if (shared_info->script() == isolate->heap()->undefined_value()) {
10937      while (context_->closure() == *function_) {
10938        context_ = Handle<Context>(context_->previous(), isolate_);
10939      }
10940      return;
10941    }
10942
10943    // Get the debug info (create it if it does not exist).
10944    if (!isolate->debug()->EnsureDebugInfo(shared_info)) {
10945      // Return if ensuring debug info failed.
10946      return;
10947    }
10948    Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared_info);
10949
10950    // Find the break point where execution has stopped.
10951    BreakLocationIterator break_location_iterator(debug_info,
10952                                                  ALL_BREAK_LOCATIONS);
10953    break_location_iterator.FindBreakLocationFromAddress(frame->pc());
10954    if (break_location_iterator.IsExit()) {
10955      // We are within the return sequence. At the momemt it is not possible to
10956      // get a source position which is consistent with the current scope chain.
10957      // Thus all nested with, catch and block contexts are skipped and we only
10958      // provide the function scope.
10959      if (scope_info->HasContext()) {
10960        context_ = Handle<Context>(context_->declaration_context(), isolate_);
10961      } else {
10962        while (context_->closure() == *function_) {
10963          context_ = Handle<Context>(context_->previous(), isolate_);
10964        }
10965      }
10966      if (scope_info->Type() != EVAL_SCOPE) nested_scope_chain_.Add(scope_info);
10967    } else {
10968      // Reparse the code and analyze the scopes.
10969      ZoneScope zone_scope(isolate, DELETE_ON_EXIT);
10970      Handle<Script> script(Script::cast(shared_info->script()));
10971      Scope* scope = NULL;
10972
10973      // Check whether we are in global, eval or function code.
10974      Handle<ScopeInfo> scope_info(shared_info->scope_info());
10975      if (scope_info->Type() != FUNCTION_SCOPE) {
10976        // Global or eval code.
10977        CompilationInfo info(script);
10978        if (scope_info->Type() == GLOBAL_SCOPE) {
10979          info.MarkAsGlobal();
10980        } else {
10981          ASSERT(scope_info->Type() == EVAL_SCOPE);
10982          info.MarkAsEval();
10983          info.SetCallingContext(Handle<Context>(function_->context()));
10984        }
10985        if (ParserApi::Parse(&info, kNoParsingFlags) && Scope::Analyze(&info)) {
10986          scope = info.function()->scope();
10987        }
10988      } else {
10989        // Function code
10990        CompilationInfo info(shared_info);
10991        if (ParserApi::Parse(&info, kNoParsingFlags) && Scope::Analyze(&info)) {
10992          scope = info.function()->scope();
10993        }
10994      }
10995
10996      // Retrieve the scope chain for the current position.
10997      if (scope != NULL) {
10998        int source_position = shared_info->code()->SourcePosition(frame_->pc());
10999        scope->GetNestedScopeChain(&nested_scope_chain_, source_position);
11000      } else {
11001        // A failed reparse indicates that the preparser has diverged from the
11002        // parser or that the preparse data given to the initial parse has been
11003        // faulty. We fail in debug mode but in release mode we only provide the
11004        // information we get from the context chain but nothing about
11005        // completely stack allocated scopes or stack allocated locals.
11006        UNREACHABLE();
11007      }
11008    }
11009  }
11010
11011  // More scopes?
11012  bool Done() { return context_.is_null(); }
11013
11014  // Move to the next scope.
11015  void Next() {
11016    ScopeType scope_type = Type();
11017    if (scope_type == ScopeTypeGlobal) {
11018      // The global scope is always the last in the chain.
11019      ASSERT(context_->IsGlobalContext());
11020      context_ = Handle<Context>();
11021      return;
11022    }
11023    if (nested_scope_chain_.is_empty()) {
11024      context_ = Handle<Context>(context_->previous(), isolate_);
11025    } else {
11026      if (nested_scope_chain_.last()->HasContext()) {
11027        ASSERT(context_->previous() != NULL);
11028        context_ = Handle<Context>(context_->previous(), isolate_);
11029      }
11030      nested_scope_chain_.RemoveLast();
11031    }
11032  }
11033
11034  // Return the type of the current scope.
11035  ScopeType Type() {
11036    if (!nested_scope_chain_.is_empty()) {
11037      Handle<ScopeInfo> scope_info = nested_scope_chain_.last();
11038      switch (scope_info->Type()) {
11039        case FUNCTION_SCOPE:
11040          ASSERT(context_->IsFunctionContext() ||
11041                 !scope_info->HasContext());
11042          return ScopeTypeLocal;
11043        case MODULE_SCOPE:
11044          ASSERT(context_->IsModuleContext());
11045          return ScopeTypeModule;
11046        case GLOBAL_SCOPE:
11047          ASSERT(context_->IsGlobalContext());
11048          return ScopeTypeGlobal;
11049        case WITH_SCOPE:
11050          ASSERT(context_->IsWithContext());
11051          return ScopeTypeWith;
11052        case CATCH_SCOPE:
11053          ASSERT(context_->IsCatchContext());
11054          return ScopeTypeCatch;
11055        case BLOCK_SCOPE:
11056          ASSERT(!scope_info->HasContext() ||
11057                 context_->IsBlockContext());
11058          return ScopeTypeBlock;
11059        case EVAL_SCOPE:
11060          UNREACHABLE();
11061      }
11062    }
11063    if (context_->IsGlobalContext()) {
11064      ASSERT(context_->global()->IsGlobalObject());
11065      return ScopeTypeGlobal;
11066    }
11067    if (context_->IsFunctionContext()) {
11068      return ScopeTypeClosure;
11069    }
11070    if (context_->IsCatchContext()) {
11071      return ScopeTypeCatch;
11072    }
11073    if (context_->IsBlockContext()) {
11074      return ScopeTypeBlock;
11075    }
11076    if (context_->IsModuleContext()) {
11077      return ScopeTypeModule;
11078    }
11079    ASSERT(context_->IsWithContext());
11080    return ScopeTypeWith;
11081  }
11082
11083  // Return the JavaScript object with the content of the current scope.
11084  Handle<JSObject> ScopeObject() {
11085    switch (Type()) {
11086      case ScopeIterator::ScopeTypeGlobal:
11087        return Handle<JSObject>(CurrentContext()->global());
11088      case ScopeIterator::ScopeTypeLocal:
11089        // Materialize the content of the local scope into a JSObject.
11090        ASSERT(nested_scope_chain_.length() == 1);
11091        return MaterializeLocalScope(isolate_, frame_, inlined_jsframe_index_);
11092      case ScopeIterator::ScopeTypeWith:
11093        // Return the with object.
11094        return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
11095      case ScopeIterator::ScopeTypeCatch:
11096        return MaterializeCatchScope(isolate_, CurrentContext());
11097      case ScopeIterator::ScopeTypeClosure:
11098        // Materialize the content of the closure scope into a JSObject.
11099        return MaterializeClosure(isolate_, CurrentContext());
11100      case ScopeIterator::ScopeTypeBlock:
11101        return MaterializeBlockScope(isolate_, CurrentContext());
11102      case ScopeIterator::ScopeTypeModule:
11103        return MaterializeModuleScope(isolate_, CurrentContext());
11104    }
11105    UNREACHABLE();
11106    return Handle<JSObject>();
11107  }
11108
11109  Handle<ScopeInfo> CurrentScopeInfo() {
11110    if (!nested_scope_chain_.is_empty()) {
11111      return nested_scope_chain_.last();
11112    } else if (context_->IsBlockContext()) {
11113      return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension()));
11114    } else if (context_->IsFunctionContext()) {
11115      return Handle<ScopeInfo>(context_->closure()->shared()->scope_info());
11116    }
11117    return Handle<ScopeInfo>::null();
11118  }
11119
11120  // Return the context for this scope. For the local context there might not
11121  // be an actual context.
11122  Handle<Context> CurrentContext() {
11123    if (Type() == ScopeTypeGlobal ||
11124        nested_scope_chain_.is_empty()) {
11125      return context_;
11126    } else if (nested_scope_chain_.last()->HasContext()) {
11127      return context_;
11128    } else {
11129      return Handle<Context>();
11130    }
11131  }
11132
11133#ifdef DEBUG
11134  // Debug print of the content of the current scope.
11135  void DebugPrint() {
11136    switch (Type()) {
11137      case ScopeIterator::ScopeTypeGlobal:
11138        PrintF("Global:\n");
11139        CurrentContext()->Print();
11140        break;
11141
11142      case ScopeIterator::ScopeTypeLocal: {
11143        PrintF("Local:\n");
11144        function_->shared()->scope_info()->Print();
11145        if (!CurrentContext().is_null()) {
11146          CurrentContext()->Print();
11147          if (CurrentContext()->has_extension()) {
11148            Handle<Object> extension(CurrentContext()->extension());
11149            if (extension->IsJSContextExtensionObject()) {
11150              extension->Print();
11151            }
11152          }
11153        }
11154        break;
11155      }
11156
11157      case ScopeIterator::ScopeTypeWith:
11158        PrintF("With:\n");
11159        CurrentContext()->extension()->Print();
11160        break;
11161
11162      case ScopeIterator::ScopeTypeCatch:
11163        PrintF("Catch:\n");
11164        CurrentContext()->extension()->Print();
11165        CurrentContext()->get(Context::THROWN_OBJECT_INDEX)->Print();
11166        break;
11167
11168      case ScopeIterator::ScopeTypeClosure:
11169        PrintF("Closure:\n");
11170        CurrentContext()->Print();
11171        if (CurrentContext()->has_extension()) {
11172          Handle<Object> extension(CurrentContext()->extension());
11173          if (extension->IsJSContextExtensionObject()) {
11174            extension->Print();
11175          }
11176        }
11177        break;
11178
11179      default:
11180        UNREACHABLE();
11181    }
11182    PrintF("\n");
11183  }
11184#endif
11185
11186 private:
11187  Isolate* isolate_;
11188  JavaScriptFrame* frame_;
11189  int inlined_jsframe_index_;
11190  Handle<JSFunction> function_;
11191  Handle<Context> context_;
11192  List<Handle<ScopeInfo> > nested_scope_chain_;
11193
11194  DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
11195};
11196
11197
11198RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
11199  HandleScope scope(isolate);
11200  ASSERT(args.length() == 2);
11201
11202  // Check arguments.
11203  Object* check;
11204  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11205      RUNTIME_ARGUMENTS(isolate, args));
11206    if (!maybe_check->ToObject(&check)) return maybe_check;
11207  }
11208  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
11209
11210  // Get the frame where the debugging is performed.
11211  StackFrame::Id id = UnwrapFrameId(wrapped_id);
11212  JavaScriptFrameIterator it(isolate, id);
11213  JavaScriptFrame* frame = it.frame();
11214
11215  // Count the visible scopes.
11216  int n = 0;
11217  for (ScopeIterator it(isolate, frame, 0);
11218       !it.Done();
11219       it.Next()) {
11220    n++;
11221  }
11222
11223  return Smi::FromInt(n);
11224}
11225
11226
11227static const int kScopeDetailsTypeIndex = 0;
11228static const int kScopeDetailsObjectIndex = 1;
11229static const int kScopeDetailsSize = 2;
11230
11231// Return an array with scope details
11232// args[0]: number: break id
11233// args[1]: number: frame index
11234// args[2]: number: inlined frame index
11235// args[3]: number: scope index
11236//
11237// The array returned contains the following information:
11238// 0: Scope type
11239// 1: Scope object
11240RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
11241  HandleScope scope(isolate);
11242  ASSERT(args.length() == 4);
11243
11244  // Check arguments.
11245  Object* check;
11246  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11247      RUNTIME_ARGUMENTS(isolate, args));
11248    if (!maybe_check->ToObject(&check)) return maybe_check;
11249  }
11250  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
11251  CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
11252  CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
11253
11254  // Get the frame where the debugging is performed.
11255  StackFrame::Id id = UnwrapFrameId(wrapped_id);
11256  JavaScriptFrameIterator frame_it(isolate, id);
11257  JavaScriptFrame* frame = frame_it.frame();
11258
11259  // Find the requested scope.
11260  int n = 0;
11261  ScopeIterator it(isolate, frame, inlined_jsframe_index);
11262  for (; !it.Done() && n < index; it.Next()) {
11263    n++;
11264  }
11265  if (it.Done()) {
11266    return isolate->heap()->undefined_value();
11267  }
11268
11269  // Calculate the size of the result.
11270  int details_size = kScopeDetailsSize;
11271  Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
11272
11273  // Fill in scope details.
11274  details->set(kScopeDetailsTypeIndex, Smi::FromInt(it.Type()));
11275  Handle<JSObject> scope_object = it.ScopeObject();
11276  RETURN_IF_EMPTY_HANDLE(isolate, scope_object);
11277  details->set(kScopeDetailsObjectIndex, *scope_object);
11278
11279  return *isolate->factory()->NewJSArrayWithElements(details);
11280}
11281
11282
11283RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) {
11284  HandleScope scope(isolate);
11285  ASSERT(args.length() == 0);
11286
11287#ifdef DEBUG
11288  // Print the scopes for the top frame.
11289  StackFrameLocator locator;
11290  JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
11291  for (ScopeIterator it(isolate, frame, 0);
11292       !it.Done();
11293       it.Next()) {
11294    it.DebugPrint();
11295  }
11296#endif
11297  return isolate->heap()->undefined_value();
11298}
11299
11300
11301RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadCount) {
11302  HandleScope scope(isolate);
11303  ASSERT(args.length() == 1);
11304
11305  // Check arguments.
11306  Object* result;
11307  { MaybeObject* maybe_result = Runtime_CheckExecutionState(
11308      RUNTIME_ARGUMENTS(isolate, args));
11309    if (!maybe_result->ToObject(&result)) return maybe_result;
11310  }
11311
11312  // Count all archived V8 threads.
11313  int n = 0;
11314  for (ThreadState* thread =
11315          isolate->thread_manager()->FirstThreadStateInUse();
11316       thread != NULL;
11317       thread = thread->Next()) {
11318    n++;
11319  }
11320
11321  // Total number of threads is current thread and archived threads.
11322  return Smi::FromInt(n + 1);
11323}
11324
11325
11326static const int kThreadDetailsCurrentThreadIndex = 0;
11327static const int kThreadDetailsThreadIdIndex = 1;
11328static const int kThreadDetailsSize = 2;
11329
11330// Return an array with thread details
11331// args[0]: number: break id
11332// args[1]: number: thread index
11333//
11334// The array returned contains the following information:
11335// 0: Is current thread?
11336// 1: Thread id
11337RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadDetails) {
11338  HandleScope scope(isolate);
11339  ASSERT(args.length() == 2);
11340
11341  // Check arguments.
11342  Object* check;
11343  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11344      RUNTIME_ARGUMENTS(isolate, args));
11345    if (!maybe_check->ToObject(&check)) return maybe_check;
11346  }
11347  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
11348
11349  // Allocate array for result.
11350  Handle<FixedArray> details =
11351      isolate->factory()->NewFixedArray(kThreadDetailsSize);
11352
11353  // Thread index 0 is current thread.
11354  if (index == 0) {
11355    // Fill the details.
11356    details->set(kThreadDetailsCurrentThreadIndex,
11357                 isolate->heap()->true_value());
11358    details->set(kThreadDetailsThreadIdIndex,
11359                 Smi::FromInt(ThreadId::Current().ToInteger()));
11360  } else {
11361    // Find the thread with the requested index.
11362    int n = 1;
11363    ThreadState* thread =
11364        isolate->thread_manager()->FirstThreadStateInUse();
11365    while (index != n && thread != NULL) {
11366      thread = thread->Next();
11367      n++;
11368    }
11369    if (thread == NULL) {
11370      return isolate->heap()->undefined_value();
11371    }
11372
11373    // Fill the details.
11374    details->set(kThreadDetailsCurrentThreadIndex,
11375                 isolate->heap()->false_value());
11376    details->set(kThreadDetailsThreadIdIndex,
11377                 Smi::FromInt(thread->id().ToInteger()));
11378  }
11379
11380  // Convert to JS array and return.
11381  return *isolate->factory()->NewJSArrayWithElements(details);
11382}
11383
11384
11385// Sets the disable break state
11386// args[0]: disable break state
11387RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDisableBreak) {
11388  HandleScope scope(isolate);
11389  ASSERT(args.length() == 1);
11390  CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 0);
11391  isolate->debug()->set_disable_break(disable_break);
11392  return  isolate->heap()->undefined_value();
11393}
11394
11395
11396RUNTIME_FUNCTION(MaybeObject*, Runtime_GetBreakLocations) {
11397  HandleScope scope(isolate);
11398  ASSERT(args.length() == 1);
11399
11400  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
11401  Handle<SharedFunctionInfo> shared(fun->shared());
11402  // Find the number of break points
11403  Handle<Object> break_locations = Debug::GetSourceBreakLocations(shared);
11404  if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
11405  // Return array as JS array
11406  return *isolate->factory()->NewJSArrayWithElements(
11407      Handle<FixedArray>::cast(break_locations));
11408}
11409
11410
11411// Set a break point in a function
11412// args[0]: function
11413// args[1]: number: break source position (within the function source)
11414// args[2]: number: break point object
11415RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFunctionBreakPoint) {
11416  HandleScope scope(isolate);
11417  ASSERT(args.length() == 3);
11418  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
11419  Handle<SharedFunctionInfo> shared(fun->shared());
11420  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
11421  RUNTIME_ASSERT(source_position >= 0);
11422  Handle<Object> break_point_object_arg = args.at<Object>(2);
11423
11424  // Set break point.
11425  isolate->debug()->SetBreakPoint(shared, break_point_object_arg,
11426                                  &source_position);
11427
11428  return Smi::FromInt(source_position);
11429}
11430
11431
11432Object* Runtime::FindSharedFunctionInfoInScript(Isolate* isolate,
11433                                                Handle<Script> script,
11434                                                int position) {
11435  // Iterate the heap looking for SharedFunctionInfo generated from the
11436  // script. The inner most SharedFunctionInfo containing the source position
11437  // for the requested break point is found.
11438  // NOTE: This might require several heap iterations. If the SharedFunctionInfo
11439  // which is found is not compiled it is compiled and the heap is iterated
11440  // again as the compilation might create inner functions from the newly
11441  // compiled function and the actual requested break point might be in one of
11442  // these functions.
11443  bool done = false;
11444  // The current candidate for the source position:
11445  int target_start_position = RelocInfo::kNoPosition;
11446  Handle<SharedFunctionInfo> target;
11447  while (!done) {
11448    { // Extra scope for iterator and no-allocation.
11449      isolate->heap()->EnsureHeapIsIterable();
11450      AssertNoAllocation no_alloc_during_heap_iteration;
11451      HeapIterator iterator;
11452      for (HeapObject* obj = iterator.next();
11453           obj != NULL; obj = iterator.next()) {
11454        if (obj->IsSharedFunctionInfo()) {
11455          Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(obj));
11456          if (shared->script() == *script) {
11457            // If the SharedFunctionInfo found has the requested script data and
11458            // contains the source position it is a candidate.
11459            int start_position = shared->function_token_position();
11460            if (start_position == RelocInfo::kNoPosition) {
11461              start_position = shared->start_position();
11462            }
11463            if (start_position <= position &&
11464                position <= shared->end_position()) {
11465              // If there is no candidate or this function is within the current
11466              // candidate this is the new candidate.
11467              if (target.is_null()) {
11468                target_start_position = start_position;
11469                target = shared;
11470              } else {
11471                if (target_start_position == start_position &&
11472                    shared->end_position() == target->end_position()) {
11473                    // If a top-level function contain only one function
11474                    // declartion the source for the top-level and the
11475                    // function is the same. In that case prefer the non
11476                    // top-level function.
11477                  if (!shared->is_toplevel()) {
11478                    target_start_position = start_position;
11479                    target = shared;
11480                  }
11481                } else if (target_start_position <= start_position &&
11482                           shared->end_position() <= target->end_position()) {
11483                  // This containment check includes equality as a function
11484                  // inside a top-level function can share either start or end
11485                  // position with the top-level function.
11486                  target_start_position = start_position;
11487                  target = shared;
11488                }
11489              }
11490            }
11491          }
11492        }
11493      }  // End for loop.
11494    }  // End No allocation scope.
11495
11496    if (target.is_null()) {
11497      return isolate->heap()->undefined_value();
11498    }
11499
11500    // If the candidate found is compiled we are done. NOTE: when lazy
11501    // compilation of inner functions is introduced some additional checking
11502    // needs to be done here to compile inner functions.
11503    done = target->is_compiled();
11504    if (!done) {
11505      // If the candidate is not compiled compile it to reveal any inner
11506      // functions which might contain the requested source position.
11507      SharedFunctionInfo::CompileLazy(target, KEEP_EXCEPTION);
11508    }
11509  }  // End while loop.
11510
11511  return *target;
11512}
11513
11514
11515// Changes the state of a break point in a script and returns source position
11516// where break point was set. NOTE: Regarding performance see the NOTE for
11517// GetScriptFromScriptData.
11518// args[0]: script to set break point in
11519// args[1]: number: break source position (within the script source)
11520// args[2]: number: break point object
11521RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScriptBreakPoint) {
11522  HandleScope scope(isolate);
11523  ASSERT(args.length() == 3);
11524  CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
11525  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
11526  RUNTIME_ASSERT(source_position >= 0);
11527  Handle<Object> break_point_object_arg = args.at<Object>(2);
11528
11529  // Get the script from the script wrapper.
11530  RUNTIME_ASSERT(wrapper->value()->IsScript());
11531  Handle<Script> script(Script::cast(wrapper->value()));
11532
11533  Object* result = Runtime::FindSharedFunctionInfoInScript(
11534      isolate, script, source_position);
11535  if (!result->IsUndefined()) {
11536    Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
11537    // Find position within function. The script position might be before the
11538    // source position of the first function.
11539    int position;
11540    if (shared->start_position() > source_position) {
11541      position = 0;
11542    } else {
11543      position = source_position - shared->start_position();
11544    }
11545    isolate->debug()->SetBreakPoint(shared, break_point_object_arg, &position);
11546    position += shared->start_position();
11547    return Smi::FromInt(position);
11548  }
11549  return  isolate->heap()->undefined_value();
11550}
11551
11552
11553// Clear a break point
11554// args[0]: number: break point object
11555RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearBreakPoint) {
11556  HandleScope scope(isolate);
11557  ASSERT(args.length() == 1);
11558  Handle<Object> break_point_object_arg = args.at<Object>(0);
11559
11560  // Clear break point.
11561  isolate->debug()->ClearBreakPoint(break_point_object_arg);
11562
11563  return isolate->heap()->undefined_value();
11564}
11565
11566
11567// Change the state of break on exceptions.
11568// args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
11569// args[1]: Boolean indicating on/off.
11570RUNTIME_FUNCTION(MaybeObject*, Runtime_ChangeBreakOnException) {
11571  HandleScope scope(isolate);
11572  ASSERT(args.length() == 2);
11573  RUNTIME_ASSERT(args[0]->IsNumber());
11574  CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
11575
11576  // If the number doesn't match an enum value, the ChangeBreakOnException
11577  // function will default to affecting caught exceptions.
11578  ExceptionBreakType type =
11579      static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
11580  // Update break point state.
11581  isolate->debug()->ChangeBreakOnException(type, enable);
11582  return isolate->heap()->undefined_value();
11583}
11584
11585
11586// Returns the state of break on exceptions
11587// args[0]: boolean indicating uncaught exceptions
11588RUNTIME_FUNCTION(MaybeObject*, Runtime_IsBreakOnException) {
11589  HandleScope scope(isolate);
11590  ASSERT(args.length() == 1);
11591  RUNTIME_ASSERT(args[0]->IsNumber());
11592
11593  ExceptionBreakType type =
11594      static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
11595  bool result = isolate->debug()->IsBreakOnException(type);
11596  return Smi::FromInt(result);
11597}
11598
11599
11600// Prepare for stepping
11601// args[0]: break id for checking execution state
11602// args[1]: step action from the enumeration StepAction
11603// args[2]: number of times to perform the step, for step out it is the number
11604//          of frames to step down.
11605RUNTIME_FUNCTION(MaybeObject*, Runtime_PrepareStep) {
11606  HandleScope scope(isolate);
11607  ASSERT(args.length() == 3);
11608  // Check arguments.
11609  Object* check;
11610  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11611      RUNTIME_ARGUMENTS(isolate, args));
11612    if (!maybe_check->ToObject(&check)) return maybe_check;
11613  }
11614  if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
11615    return isolate->Throw(isolate->heap()->illegal_argument_symbol());
11616  }
11617
11618  // Get the step action and check validity.
11619  StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
11620  if (step_action != StepIn &&
11621      step_action != StepNext &&
11622      step_action != StepOut &&
11623      step_action != StepInMin &&
11624      step_action != StepMin) {
11625    return isolate->Throw(isolate->heap()->illegal_argument_symbol());
11626  }
11627
11628  // Get the number of steps.
11629  int step_count = NumberToInt32(args[2]);
11630  if (step_count < 1) {
11631    return isolate->Throw(isolate->heap()->illegal_argument_symbol());
11632  }
11633
11634  // Clear all current stepping setup.
11635  isolate->debug()->ClearStepping();
11636
11637  // Prepare step.
11638  isolate->debug()->PrepareStep(static_cast<StepAction>(step_action),
11639                                step_count);
11640  return isolate->heap()->undefined_value();
11641}
11642
11643
11644// Clear all stepping set by PrepareStep.
11645RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) {
11646  HandleScope scope(isolate);
11647  ASSERT(args.length() == 0);
11648  isolate->debug()->ClearStepping();
11649  return isolate->heap()->undefined_value();
11650}
11651
11652
11653// Creates a copy of the with context chain. The copy of the context chain is
11654// is linked to the function context supplied.
11655static Handle<Context> CopyNestedScopeContextChain(Isolate* isolate,
11656                                                   Handle<JSFunction> function,
11657                                                   Handle<Context> base,
11658                                                   JavaScriptFrame* frame,
11659                                                   int inlined_jsframe_index) {
11660  HandleScope scope(isolate);
11661  List<Handle<ScopeInfo> > scope_chain;
11662  List<Handle<Context> > context_chain;
11663
11664  ScopeIterator it(isolate, frame, inlined_jsframe_index);
11665  for (; it.Type() != ScopeIterator::ScopeTypeGlobal &&
11666         it.Type() != ScopeIterator::ScopeTypeLocal ; it.Next()) {
11667    ASSERT(!it.Done());
11668    scope_chain.Add(it.CurrentScopeInfo());
11669    context_chain.Add(it.CurrentContext());
11670  }
11671
11672  // At the end of the chain. Return the base context to link to.
11673  Handle<Context> context = base;
11674
11675  // Iteratively copy and or materialize the nested contexts.
11676  while (!scope_chain.is_empty()) {
11677    Handle<ScopeInfo> scope_info = scope_chain.RemoveLast();
11678    Handle<Context> current = context_chain.RemoveLast();
11679    ASSERT(!(scope_info->HasContext() & current.is_null()));
11680
11681    if (scope_info->Type() == CATCH_SCOPE) {
11682      Handle<String> name(String::cast(current->extension()));
11683      Handle<Object> thrown_object(current->get(Context::THROWN_OBJECT_INDEX));
11684      context =
11685          isolate->factory()->NewCatchContext(function,
11686                                              context,
11687                                              name,
11688                                              thrown_object);
11689    } else if (scope_info->Type() == BLOCK_SCOPE) {
11690      // Materialize the contents of the block scope into a JSObject.
11691      Handle<JSObject> block_scope_object =
11692          MaterializeBlockScope(isolate, current);
11693      if (block_scope_object.is_null()) {
11694        return Handle<Context>::null();
11695      }
11696      // Allocate a new function context for the debug evaluation and set the
11697      // extension object.
11698      Handle<Context> new_context =
11699          isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS,
11700                                                 function);
11701      new_context->set_extension(*block_scope_object);
11702      new_context->set_previous(*context);
11703      context = new_context;
11704    } else {
11705      ASSERT(scope_info->Type() == WITH_SCOPE);
11706      ASSERT(current->IsWithContext());
11707      Handle<JSObject> extension(JSObject::cast(current->extension()));
11708      context =
11709          isolate->factory()->NewWithContext(function, context, extension);
11710    }
11711  }
11712
11713  return scope.CloseAndEscape(context);
11714}
11715
11716
11717// Helper function to find or create the arguments object for
11718// Runtime_DebugEvaluate.
11719static Handle<Object> GetArgumentsObject(Isolate* isolate,
11720                                         JavaScriptFrame* frame,
11721                                         FrameInspector* frame_inspector,
11722                                         Handle<ScopeInfo> scope_info,
11723                                         Handle<Context> function_context) {
11724  // Try to find the value of 'arguments' to pass as parameter. If it is not
11725  // found (that is the debugged function does not reference 'arguments' and
11726  // does not support eval) then create an 'arguments' object.
11727  int index;
11728  if (scope_info->StackLocalCount() > 0) {
11729    index = scope_info->StackSlotIndex(isolate->heap()->arguments_symbol());
11730    if (index != -1) {
11731      return Handle<Object>(frame->GetExpression(index), isolate);
11732    }
11733  }
11734
11735  if (scope_info->HasHeapAllocatedLocals()) {
11736    VariableMode mode;
11737    InitializationFlag init_flag;
11738    index = scope_info->ContextSlotIndex(
11739        isolate->heap()->arguments_symbol(), &mode, &init_flag);
11740    if (index != -1) {
11741      return Handle<Object>(function_context->get(index), isolate);
11742    }
11743  }
11744
11745  Handle<JSFunction> function(JSFunction::cast(frame_inspector->GetFunction()));
11746  int length = frame_inspector->GetParametersCount();
11747  Handle<JSObject> arguments =
11748      isolate->factory()->NewArgumentsObject(function, length);
11749  Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
11750
11751  AssertNoAllocation no_gc;
11752  WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
11753  for (int i = 0; i < length; i++) {
11754    array->set(i, frame_inspector->GetParameter(i), mode);
11755  }
11756  arguments->set_elements(*array);
11757  return arguments;
11758}
11759
11760
11761static const char kSourceStr[] =
11762    "(function(arguments,__source__){return eval(__source__);})";
11763
11764
11765// Evaluate a piece of JavaScript in the context of a stack frame for
11766// debugging. This is accomplished by creating a new context which in its
11767// extension part has all the parameters and locals of the function on the
11768// stack frame. A function which calls eval with the code to evaluate is then
11769// compiled in this context and called in this context. As this context
11770// replaces the context of the function on the stack frame a new (empty)
11771// function is created as well to be used as the closure for the context.
11772// This function and the context acts as replacements for the function on the
11773// stack frame presenting the same view of the values of parameters and
11774// local variables as if the piece of JavaScript was evaluated at the point
11775// where the function on the stack frame is currently stopped.
11776RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
11777  HandleScope scope(isolate);
11778
11779  // Check the execution state and decode arguments frame and source to be
11780  // evaluated.
11781  ASSERT(args.length() == 6);
11782  Object* check_result;
11783  { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(
11784      RUNTIME_ARGUMENTS(isolate, args));
11785    if (!maybe_check_result->ToObject(&check_result)) {
11786      return maybe_check_result;
11787    }
11788  }
11789  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
11790  CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
11791  CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
11792  CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
11793  Handle<Object> additional_context(args[5]);
11794
11795  // Handle the processing of break.
11796  DisableBreak disable_break_save(disable_break);
11797
11798  // Get the frame where the debugging is performed.
11799  StackFrame::Id id = UnwrapFrameId(wrapped_id);
11800  JavaScriptFrameIterator it(isolate, id);
11801  JavaScriptFrame* frame = it.frame();
11802  FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
11803  Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
11804  Handle<ScopeInfo> scope_info(function->shared()->scope_info());
11805
11806  // Traverse the saved contexts chain to find the active context for the
11807  // selected frame.
11808  SaveContext* save = FindSavedContextForFrame(isolate, frame);
11809
11810  SaveContext savex(isolate);
11811  isolate->set_context(*(save->context()));
11812
11813  // Create the (empty) function replacing the function on the stack frame for
11814  // the purpose of evaluating in the context created below. It is important
11815  // that this function does not describe any parameters and local variables
11816  // in the context. If it does then this will cause problems with the lookup
11817  // in Context::Lookup, where context slots for parameters and local variables
11818  // are looked at before the extension object.
11819  Handle<JSFunction> go_between =
11820      isolate->factory()->NewFunction(isolate->factory()->empty_string(),
11821                                      isolate->factory()->undefined_value());
11822  go_between->set_context(function->context());
11823#ifdef DEBUG
11824  Handle<ScopeInfo> go_between_scope_info(go_between->shared()->scope_info());
11825  ASSERT(go_between_scope_info->ParameterCount() == 0);
11826  ASSERT(go_between_scope_info->ContextLocalCount() == 0);
11827#endif
11828
11829  // Materialize the content of the local scope into a JSObject.
11830  Handle<JSObject> local_scope = MaterializeLocalScopeWithFrameInspector(
11831      isolate, frame, &frame_inspector);
11832  RETURN_IF_EMPTY_HANDLE(isolate, local_scope);
11833
11834  // Allocate a new context for the debug evaluation and set the extension
11835  // object build.
11836  Handle<Context> context =
11837      isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS,
11838                                             go_between);
11839  context->set_extension(*local_scope);
11840  // Copy any with contexts present and chain them in front of this context.
11841  Handle<Context> frame_context(Context::cast(frame->context()));
11842  Handle<Context> function_context;
11843  // Get the function's context if it has one.
11844  if (scope_info->HasContext()) {
11845    function_context = Handle<Context>(frame_context->declaration_context());
11846  }
11847  context = CopyNestedScopeContextChain(isolate,
11848                                        go_between,
11849                                        context,
11850                                        frame,
11851                                        inlined_jsframe_index);
11852
11853  if (additional_context->IsJSObject()) {
11854    Handle<JSObject> extension = Handle<JSObject>::cast(additional_context);
11855    context =
11856        isolate->factory()->NewWithContext(go_between, context, extension);
11857  }
11858
11859  // Wrap the evaluation statement in a new function compiled in the newly
11860  // created context. The function has one parameter which has to be called
11861  // 'arguments'. This it to have access to what would have been 'arguments' in
11862  // the function being debugged.
11863  // function(arguments,__source__) {return eval(__source__);}
11864
11865  Handle<String> function_source =
11866      isolate->factory()->NewStringFromAscii(
11867          Vector<const char>(kSourceStr, sizeof(kSourceStr) - 1));
11868
11869  // Currently, the eval code will be executed in non-strict mode,
11870  // even in the strict code context.
11871  Handle<SharedFunctionInfo> shared =
11872      Compiler::CompileEval(function_source,
11873                            context,
11874                            context->IsGlobalContext(),
11875                            CLASSIC_MODE,
11876                            RelocInfo::kNoPosition);
11877  if (shared.is_null()) return Failure::Exception();
11878  Handle<JSFunction> compiled_function =
11879      isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context);
11880
11881  // Invoke the result of the compilation to get the evaluation function.
11882  bool has_pending_exception;
11883  Handle<Object> receiver(frame->receiver(), isolate);
11884  Handle<Object> evaluation_function =
11885      Execution::Call(compiled_function, receiver, 0, NULL,
11886                      &has_pending_exception);
11887  if (has_pending_exception) return Failure::Exception();
11888
11889  Handle<Object> arguments = GetArgumentsObject(isolate,
11890                                                frame,
11891                                                &frame_inspector,
11892                                                scope_info,
11893                                                function_context);
11894
11895  // Invoke the evaluation function and return the result.
11896  Handle<Object> argv[] = { arguments, source };
11897  Handle<Object> result =
11898      Execution::Call(Handle<JSFunction>::cast(evaluation_function),
11899                      receiver,
11900                      ARRAY_SIZE(argv),
11901                      argv,
11902                      &has_pending_exception);
11903  if (has_pending_exception) return Failure::Exception();
11904
11905  // Skip the global proxy as it has no properties and always delegates to the
11906  // real global object.
11907  if (result->IsJSGlobalProxy()) {
11908    result = Handle<JSObject>(JSObject::cast(result->GetPrototype()));
11909  }
11910
11911  return *result;
11912}
11913
11914
11915RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) {
11916  HandleScope scope(isolate);
11917
11918  // Check the execution state and decode arguments frame and source to be
11919  // evaluated.
11920  ASSERT(args.length() == 4);
11921  Object* check_result;
11922  { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(
11923      RUNTIME_ARGUMENTS(isolate, args));
11924    if (!maybe_check_result->ToObject(&check_result)) {
11925      return maybe_check_result;
11926    }
11927  }
11928  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
11929  CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
11930  Handle<Object> additional_context(args[3]);
11931
11932  // Handle the processing of break.
11933  DisableBreak disable_break_save(disable_break);
11934
11935  // Enter the top context from before the debugger was invoked.
11936  SaveContext save(isolate);
11937  SaveContext* top = &save;
11938  while (top != NULL && *top->context() == *isolate->debug()->debug_context()) {
11939    top = top->prev();
11940  }
11941  if (top != NULL) {
11942    isolate->set_context(*top->context());
11943  }
11944
11945  // Get the global context now set to the top context from before the
11946  // debugger was invoked.
11947  Handle<Context> context = isolate->global_context();
11948
11949  bool is_global = true;
11950
11951  if (additional_context->IsJSObject()) {
11952    // Create a new with context with the additional context information between
11953    // the context of the debugged function and the eval code to be executed.
11954    context = isolate->factory()->NewWithContext(
11955        Handle<JSFunction>(context->closure()),
11956        context,
11957        Handle<JSObject>::cast(additional_context));
11958    is_global = false;
11959  }
11960
11961  // Compile the source to be evaluated.
11962  // Currently, the eval code will be executed in non-strict mode,
11963  // even in the strict code context.
11964  Handle<SharedFunctionInfo> shared =
11965      Compiler::CompileEval(source,
11966                            context,
11967                            is_global,
11968                            CLASSIC_MODE,
11969                            RelocInfo::kNoPosition);
11970  if (shared.is_null()) return Failure::Exception();
11971  Handle<JSFunction> compiled_function =
11972      Handle<JSFunction>(
11973          isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
11974                                                                context));
11975
11976  // Invoke the result of the compilation to get the evaluation function.
11977  bool has_pending_exception;
11978  Handle<Object> receiver = isolate->global();
11979  Handle<Object> result =
11980    Execution::Call(compiled_function, receiver, 0, NULL,
11981                    &has_pending_exception);
11982  // Clear the oneshot breakpoints so that the debugger does not step further.
11983  isolate->debug()->ClearStepping();
11984  if (has_pending_exception) return Failure::Exception();
11985  return *result;
11986}
11987
11988
11989RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetLoadedScripts) {
11990  HandleScope scope(isolate);
11991  ASSERT(args.length() == 0);
11992
11993  // Fill the script objects.
11994  Handle<FixedArray> instances = isolate->debug()->GetLoadedScripts();
11995
11996  // Convert the script objects to proper JS objects.
11997  for (int i = 0; i < instances->length(); i++) {
11998    Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
11999    // Get the script wrapper in a local handle before calling GetScriptWrapper,
12000    // because using
12001    //   instances->set(i, *GetScriptWrapper(script))
12002    // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
12003    // already have dereferenced the instances handle.
12004    Handle<JSValue> wrapper = GetScriptWrapper(script);
12005    instances->set(i, *wrapper);
12006  }
12007
12008  // Return result as a JS array.
12009  Handle<JSObject> result =
12010      isolate->factory()->NewJSObject(isolate->array_function());
12011  isolate->factory()->SetContent(Handle<JSArray>::cast(result), instances);
12012  return *result;
12013}
12014
12015
12016// Helper function used by Runtime_DebugReferencedBy below.
12017static int DebugReferencedBy(HeapIterator* iterator,
12018                             JSObject* target,
12019                             Object* instance_filter, int max_references,
12020                             FixedArray* instances, int instances_size,
12021                             JSFunction* arguments_function) {
12022  NoHandleAllocation ha;
12023  AssertNoAllocation no_alloc;
12024
12025  // Iterate the heap.
12026  int count = 0;
12027  JSObject* last = NULL;
12028  HeapObject* heap_obj = NULL;
12029  while (((heap_obj = iterator->next()) != NULL) &&
12030         (max_references == 0 || count < max_references)) {
12031    // Only look at all JSObjects.
12032    if (heap_obj->IsJSObject()) {
12033      // Skip context extension objects and argument arrays as these are
12034      // checked in the context of functions using them.
12035      JSObject* obj = JSObject::cast(heap_obj);
12036      if (obj->IsJSContextExtensionObject() ||
12037          obj->map()->constructor() == arguments_function) {
12038        continue;
12039      }
12040
12041      // Check if the JS object has a reference to the object looked for.
12042      if (obj->ReferencesObject(target)) {
12043        // Check instance filter if supplied. This is normally used to avoid
12044        // references from mirror objects (see Runtime_IsInPrototypeChain).
12045        if (!instance_filter->IsUndefined()) {
12046          Object* V = obj;
12047          while (true) {
12048            Object* prototype = V->GetPrototype();
12049            if (prototype->IsNull()) {
12050              break;
12051            }
12052            if (instance_filter == prototype) {
12053              obj = NULL;  // Don't add this object.
12054              break;
12055            }
12056            V = prototype;
12057          }
12058        }
12059
12060        if (obj != NULL) {
12061          // Valid reference found add to instance array if supplied an update
12062          // count.
12063          if (instances != NULL && count < instances_size) {
12064            instances->set(count, obj);
12065          }
12066          last = obj;
12067          count++;
12068        }
12069      }
12070    }
12071  }
12072
12073  // Check for circular reference only. This can happen when the object is only
12074  // referenced from mirrors and has a circular reference in which case the
12075  // object is not really alive and would have been garbage collected if not
12076  // referenced from the mirror.
12077  if (count == 1 && last == target) {
12078    count = 0;
12079  }
12080
12081  // Return the number of referencing objects found.
12082  return count;
12083}
12084
12085
12086// Scan the heap for objects with direct references to an object
12087// args[0]: the object to find references to
12088// args[1]: constructor function for instances to exclude (Mirror)
12089// args[2]: the the maximum number of objects to return
12090RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugReferencedBy) {
12091  ASSERT(args.length() == 3);
12092
12093  // First perform a full GC in order to avoid references from dead objects.
12094  isolate->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
12095                                     "%DebugReferencedBy");
12096  // The heap iterator reserves the right to do a GC to make the heap iterable.
12097  // Due to the GC above we know it won't need to do that, but it seems cleaner
12098  // to get the heap iterator constructed before we start having unprotected
12099  // Object* locals that are not protected by handles.
12100
12101  // Check parameters.
12102  CONVERT_ARG_CHECKED(JSObject, target, 0);
12103  Object* instance_filter = args[1];
12104  RUNTIME_ASSERT(instance_filter->IsUndefined() ||
12105                 instance_filter->IsJSObject());
12106  CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
12107  RUNTIME_ASSERT(max_references >= 0);
12108
12109
12110  // Get the constructor function for context extension and arguments array.
12111  JSObject* arguments_boilerplate =
12112      isolate->context()->global_context()->arguments_boilerplate();
12113  JSFunction* arguments_function =
12114      JSFunction::cast(arguments_boilerplate->map()->constructor());
12115
12116  // Get the number of referencing objects.
12117  int count;
12118  HeapIterator heap_iterator;
12119  count = DebugReferencedBy(&heap_iterator,
12120                            target, instance_filter, max_references,
12121                            NULL, 0, arguments_function);
12122
12123  // Allocate an array to hold the result.
12124  Object* object;
12125  { MaybeObject* maybe_object = isolate->heap()->AllocateFixedArray(count);
12126    if (!maybe_object->ToObject(&object)) return maybe_object;
12127  }
12128  FixedArray* instances = FixedArray::cast(object);
12129
12130  // Fill the referencing objects.
12131  // AllocateFixedArray above does not make the heap non-iterable.
12132  ASSERT(HEAP->IsHeapIterable());
12133  HeapIterator heap_iterator2;
12134  count = DebugReferencedBy(&heap_iterator2,
12135                            target, instance_filter, max_references,
12136                            instances, count, arguments_function);
12137
12138  // Return result as JS array.
12139  Object* result;
12140  MaybeObject* maybe_result = isolate->heap()->AllocateJSObject(
12141      isolate->context()->global_context()->array_function());
12142  if (!maybe_result->ToObject(&result)) return maybe_result;
12143  return JSArray::cast(result)->SetContent(instances);
12144}
12145
12146
12147// Helper function used by Runtime_DebugConstructedBy below.
12148static int DebugConstructedBy(HeapIterator* iterator,
12149                              JSFunction* constructor,
12150                              int max_references,
12151                              FixedArray* instances,
12152                              int instances_size) {
12153  AssertNoAllocation no_alloc;
12154
12155  // Iterate the heap.
12156  int count = 0;
12157  HeapObject* heap_obj = NULL;
12158  while (((heap_obj = iterator->next()) != NULL) &&
12159         (max_references == 0 || count < max_references)) {
12160    // Only look at all JSObjects.
12161    if (heap_obj->IsJSObject()) {
12162      JSObject* obj = JSObject::cast(heap_obj);
12163      if (obj->map()->constructor() == constructor) {
12164        // Valid reference found add to instance array if supplied an update
12165        // count.
12166        if (instances != NULL && count < instances_size) {
12167          instances->set(count, obj);
12168        }
12169        count++;
12170      }
12171    }
12172  }
12173
12174  // Return the number of referencing objects found.
12175  return count;
12176}
12177
12178
12179// Scan the heap for objects constructed by a specific function.
12180// args[0]: the constructor to find instances of
12181// args[1]: the the maximum number of objects to return
12182RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugConstructedBy) {
12183  ASSERT(args.length() == 2);
12184
12185  // First perform a full GC in order to avoid dead objects.
12186  isolate->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
12187                                     "%DebugConstructedBy");
12188
12189  // Check parameters.
12190  CONVERT_ARG_CHECKED(JSFunction, constructor, 0);
12191  CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
12192  RUNTIME_ASSERT(max_references >= 0);
12193
12194  // Get the number of referencing objects.
12195  int count;
12196  HeapIterator heap_iterator;
12197  count = DebugConstructedBy(&heap_iterator,
12198                             constructor,
12199                             max_references,
12200                             NULL,
12201                             0);
12202
12203  // Allocate an array to hold the result.
12204  Object* object;
12205  { MaybeObject* maybe_object = isolate->heap()->AllocateFixedArray(count);
12206    if (!maybe_object->ToObject(&object)) return maybe_object;
12207  }
12208  FixedArray* instances = FixedArray::cast(object);
12209
12210  ASSERT(HEAP->IsHeapIterable());
12211  // Fill the referencing objects.
12212  HeapIterator heap_iterator2;
12213  count = DebugConstructedBy(&heap_iterator2,
12214                             constructor,
12215                             max_references,
12216                             instances,
12217                             count);
12218
12219  // Return result as JS array.
12220  Object* result;
12221  { MaybeObject* maybe_result = isolate->heap()->AllocateJSObject(
12222          isolate->context()->global_context()->array_function());
12223    if (!maybe_result->ToObject(&result)) return maybe_result;
12224  }
12225  return JSArray::cast(result)->SetContent(instances);
12226}
12227
12228
12229// Find the effective prototype object as returned by __proto__.
12230// args[0]: the object to find the prototype for.
12231RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPrototype) {
12232  ASSERT(args.length() == 1);
12233
12234  CONVERT_ARG_CHECKED(JSObject, obj, 0);
12235
12236  // Use the __proto__ accessor.
12237  return Accessors::ObjectPrototype.getter(obj, NULL);
12238}
12239
12240
12241// Patches script source (should be called upon BeforeCompile event).
12242RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugSetScriptSource) {
12243  HandleScope scope(isolate);
12244  ASSERT(args.length() == 2);
12245
12246  CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
12247  Handle<String> source(String::cast(args[1]));
12248
12249  RUNTIME_ASSERT(script_wrapper->value()->IsScript());
12250  Handle<Script> script(Script::cast(script_wrapper->value()));
12251
12252  int compilation_state = Smi::cast(script->compilation_state())->value();
12253  RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL);
12254  script->set_source(*source);
12255
12256  return isolate->heap()->undefined_value();
12257}
12258
12259
12260RUNTIME_FUNCTION(MaybeObject*, Runtime_SystemBreak) {
12261  ASSERT(args.length() == 0);
12262  CPU::DebugBreak();
12263  return isolate->heap()->undefined_value();
12264}
12265
12266
12267RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleFunction) {
12268#ifdef DEBUG
12269  HandleScope scope(isolate);
12270  ASSERT(args.length() == 1);
12271  // Get the function and make sure it is compiled.
12272  CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
12273  Handle<SharedFunctionInfo> shared(func->shared());
12274  if (!SharedFunctionInfo::EnsureCompiled(shared, KEEP_EXCEPTION)) {
12275    return Failure::Exception();
12276  }
12277  func->code()->PrintLn();
12278#endif  // DEBUG
12279  return isolate->heap()->undefined_value();
12280}
12281
12282
12283RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleConstructor) {
12284#ifdef DEBUG
12285  HandleScope scope(isolate);
12286  ASSERT(args.length() == 1);
12287  // Get the function and make sure it is compiled.
12288  CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
12289  Handle<SharedFunctionInfo> shared(func->shared());
12290  if (!SharedFunctionInfo::EnsureCompiled(shared, KEEP_EXCEPTION)) {
12291    return Failure::Exception();
12292  }
12293  shared->construct_stub()->PrintLn();
12294#endif  // DEBUG
12295  return isolate->heap()->undefined_value();
12296}
12297
12298
12299RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetInferredName) {
12300  NoHandleAllocation ha;
12301  ASSERT(args.length() == 1);
12302
12303  CONVERT_ARG_CHECKED(JSFunction, f, 0);
12304  return f->shared()->inferred_name();
12305}
12306
12307
12308static int FindSharedFunctionInfosForScript(HeapIterator* iterator,
12309                                            Script* script,
12310                                            FixedArray* buffer) {
12311  AssertNoAllocation no_allocations;
12312  int counter = 0;
12313  int buffer_size = buffer->length();
12314  for (HeapObject* obj = iterator->next();
12315       obj != NULL;
12316       obj = iterator->next()) {
12317    ASSERT(obj != NULL);
12318    if (!obj->IsSharedFunctionInfo()) {
12319      continue;
12320    }
12321    SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
12322    if (shared->script() != script) {
12323      continue;
12324    }
12325    if (counter < buffer_size) {
12326      buffer->set(counter, shared);
12327    }
12328    counter++;
12329  }
12330  return counter;
12331}
12332
12333// For a script finds all SharedFunctionInfo's in the heap that points
12334// to this script. Returns JSArray of SharedFunctionInfo wrapped
12335// in OpaqueReferences.
12336RUNTIME_FUNCTION(MaybeObject*,
12337                 Runtime_LiveEditFindSharedFunctionInfosForScript) {
12338  ASSERT(args.length() == 1);
12339  HandleScope scope(isolate);
12340  CONVERT_ARG_CHECKED(JSValue, script_value, 0);
12341
12342
12343  Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
12344
12345  const int kBufferSize = 32;
12346
12347  Handle<FixedArray> array;
12348  array = isolate->factory()->NewFixedArray(kBufferSize);
12349  int number;
12350  {
12351    isolate->heap()->EnsureHeapIsIterable();
12352    AssertNoAllocation no_allocations;
12353    HeapIterator heap_iterator;
12354    Script* scr = *script;
12355    FixedArray* arr = *array;
12356    number = FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
12357  }
12358  if (number > kBufferSize) {
12359    array = isolate->factory()->NewFixedArray(number);
12360    isolate->heap()->EnsureHeapIsIterable();
12361    AssertNoAllocation no_allocations;
12362    HeapIterator heap_iterator;
12363    Script* scr = *script;
12364    FixedArray* arr = *array;
12365    FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
12366  }
12367
12368  Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array);
12369  result->set_length(Smi::FromInt(number));
12370
12371  LiveEdit::WrapSharedFunctionInfos(result);
12372
12373  return *result;
12374}
12375
12376// For a script calculates compilation information about all its functions.
12377// The script source is explicitly specified by the second argument.
12378// The source of the actual script is not used, however it is important that
12379// all generated code keeps references to this particular instance of script.
12380// Returns a JSArray of compilation infos. The array is ordered so that
12381// each function with all its descendant is always stored in a continues range
12382// with the function itself going first. The root function is a script function.
12383RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditGatherCompileInfo) {
12384  ASSERT(args.length() == 2);
12385  HandleScope scope(isolate);
12386  CONVERT_ARG_CHECKED(JSValue, script, 0);
12387  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
12388  Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
12389
12390  JSArray* result =  LiveEdit::GatherCompileInfo(script_handle, source);
12391
12392  if (isolate->has_pending_exception()) {
12393    return Failure::Exception();
12394  }
12395
12396  return result;
12397}
12398
12399// Changes the source of the script to a new_source.
12400// If old_script_name is provided (i.e. is a String), also creates a copy of
12401// the script with its original source and sends notification to debugger.
12402RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceScript) {
12403  ASSERT(args.length() == 3);
12404  HandleScope scope(isolate);
12405  CONVERT_ARG_CHECKED(JSValue, original_script_value, 0);
12406  CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
12407  Handle<Object> old_script_name(args[2], isolate);
12408
12409  RUNTIME_ASSERT(original_script_value->value()->IsScript());
12410  Handle<Script> original_script(Script::cast(original_script_value->value()));
12411
12412  Object* old_script = LiveEdit::ChangeScriptSource(original_script,
12413                                                    new_source,
12414                                                    old_script_name);
12415
12416  if (old_script->IsScript()) {
12417    Handle<Script> script_handle(Script::cast(old_script));
12418    return *(GetScriptWrapper(script_handle));
12419  } else {
12420    return isolate->heap()->null_value();
12421  }
12422}
12423
12424
12425RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSourceUpdated) {
12426  ASSERT(args.length() == 1);
12427  HandleScope scope(isolate);
12428  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 0);
12429  return LiveEdit::FunctionSourceUpdated(shared_info);
12430}
12431
12432
12433// Replaces code of SharedFunctionInfo with a new one.
12434RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceFunctionCode) {
12435  ASSERT(args.length() == 2);
12436  HandleScope scope(isolate);
12437  CONVERT_ARG_HANDLE_CHECKED(JSArray, new_compile_info, 0);
12438  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 1);
12439
12440  return LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
12441}
12442
12443// Connects SharedFunctionInfo to another script.
12444RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSetScript) {
12445  ASSERT(args.length() == 2);
12446  HandleScope scope(isolate);
12447  Handle<Object> function_object(args[0], isolate);
12448  Handle<Object> script_object(args[1], isolate);
12449
12450  if (function_object->IsJSValue()) {
12451    Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
12452    if (script_object->IsJSValue()) {
12453      RUNTIME_ASSERT(JSValue::cast(*script_object)->value()->IsScript());
12454      Script* script = Script::cast(JSValue::cast(*script_object)->value());
12455      script_object = Handle<Object>(script, isolate);
12456    }
12457
12458    LiveEdit::SetFunctionScript(function_wrapper, script_object);
12459  } else {
12460    // Just ignore this. We may not have a SharedFunctionInfo for some functions
12461    // and we check it in this function.
12462  }
12463
12464  return isolate->heap()->undefined_value();
12465}
12466
12467
12468// In a code of a parent function replaces original function as embedded object
12469// with a substitution one.
12470RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceRefToNestedFunction) {
12471  ASSERT(args.length() == 3);
12472  HandleScope scope(isolate);
12473
12474  CONVERT_ARG_HANDLE_CHECKED(JSValue, parent_wrapper, 0);
12475  CONVERT_ARG_HANDLE_CHECKED(JSValue, orig_wrapper, 1);
12476  CONVERT_ARG_HANDLE_CHECKED(JSValue, subst_wrapper, 2);
12477
12478  LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper,
12479                                       subst_wrapper);
12480
12481  return isolate->heap()->undefined_value();
12482}
12483
12484
12485// Updates positions of a shared function info (first parameter) according
12486// to script source change. Text change is described in second parameter as
12487// array of groups of 3 numbers:
12488// (change_begin, change_end, change_end_new_position).
12489// Each group describes a change in text; groups are sorted by change_begin.
12490RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditPatchFunctionPositions) {
12491  ASSERT(args.length() == 2);
12492  HandleScope scope(isolate);
12493  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
12494  CONVERT_ARG_HANDLE_CHECKED(JSArray, position_change_array, 1);
12495
12496  return LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
12497}
12498
12499
12500// For array of SharedFunctionInfo's (each wrapped in JSValue)
12501// checks that none of them have activations on stacks (of any thread).
12502// Returns array of the same length with corresponding results of
12503// LiveEdit::FunctionPatchabilityStatus type.
12504RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCheckAndDropActivations) {
12505  ASSERT(args.length() == 2);
12506  HandleScope scope(isolate);
12507  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
12508  CONVERT_BOOLEAN_ARG_CHECKED(do_drop, 1);
12509
12510  return *LiveEdit::CheckAndDropActivations(shared_array, do_drop);
12511}
12512
12513// Compares 2 strings line-by-line, then token-wise and returns diff in form
12514// of JSArray of triplets (pos1, pos1_end, pos2_end) describing list
12515// of diff chunks.
12516RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCompareStrings) {
12517  ASSERT(args.length() == 2);
12518  HandleScope scope(isolate);
12519  CONVERT_ARG_HANDLE_CHECKED(String, s1, 0);
12520  CONVERT_ARG_HANDLE_CHECKED(String, s2, 1);
12521
12522  return *LiveEdit::CompareStrings(s1, s2);
12523}
12524
12525
12526// A testing entry. Returns statement position which is the closest to
12527// source_position.
12528RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionCodePositionFromSource) {
12529  ASSERT(args.length() == 2);
12530  HandleScope scope(isolate);
12531  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
12532  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
12533
12534  Handle<Code> code(function->code(), isolate);
12535
12536  if (code->kind() != Code::FUNCTION &&
12537      code->kind() != Code::OPTIMIZED_FUNCTION) {
12538    return isolate->heap()->undefined_value();
12539  }
12540
12541  RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION));
12542  int closest_pc = 0;
12543  int distance = kMaxInt;
12544  while (!it.done()) {
12545    int statement_position = static_cast<int>(it.rinfo()->data());
12546    // Check if this break point is closer that what was previously found.
12547    if (source_position <= statement_position &&
12548        statement_position - source_position < distance) {
12549      closest_pc =
12550          static_cast<int>(it.rinfo()->pc() - code->instruction_start());
12551      distance = statement_position - source_position;
12552      // Check whether we can't get any closer.
12553      if (distance == 0) break;
12554    }
12555    it.next();
12556  }
12557
12558  return Smi::FromInt(closest_pc);
12559}
12560
12561
12562// Calls specified function with or without entering the debugger.
12563// This is used in unit tests to run code as if debugger is entered or simply
12564// to have a stack with C++ frame in the middle.
12565RUNTIME_FUNCTION(MaybeObject*, Runtime_ExecuteInDebugContext) {
12566  ASSERT(args.length() == 2);
12567  HandleScope scope(isolate);
12568  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
12569  CONVERT_BOOLEAN_ARG_CHECKED(without_debugger, 1);
12570
12571  Handle<Object> result;
12572  bool pending_exception;
12573  {
12574    if (without_debugger) {
12575      result = Execution::Call(function, isolate->global(), 0, NULL,
12576                               &pending_exception);
12577    } else {
12578      EnterDebugger enter_debugger;
12579      result = Execution::Call(function, isolate->global(), 0, NULL,
12580                               &pending_exception);
12581    }
12582  }
12583  if (!pending_exception) {
12584    return *result;
12585  } else {
12586    return Failure::Exception();
12587  }
12588}
12589
12590
12591// Sets a v8 flag.
12592RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFlags) {
12593  CONVERT_ARG_CHECKED(String, arg, 0);
12594  SmartArrayPointer<char> flags =
12595      arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
12596  FlagList::SetFlagsFromString(*flags, StrLength(*flags));
12597  return isolate->heap()->undefined_value();
12598}
12599
12600
12601// Performs a GC.
12602// Presently, it only does a full GC.
12603RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectGarbage) {
12604  isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage");
12605  return isolate->heap()->undefined_value();
12606}
12607
12608
12609// Gets the current heap usage.
12610RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHeapUsage) {
12611  int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
12612  if (!Smi::IsValid(usage)) {
12613    return *isolate->factory()->NewNumberFromInt(usage);
12614  }
12615  return Smi::FromInt(usage);
12616}
12617
12618
12619// Captures a live object list from the present heap.
12620RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLOLEnabled) {
12621#ifdef LIVE_OBJECT_LIST
12622  return isolate->heap()->true_value();
12623#else
12624  return isolate->heap()->false_value();
12625#endif
12626}
12627
12628
12629// Captures a live object list from the present heap.
12630RUNTIME_FUNCTION(MaybeObject*, Runtime_CaptureLOL) {
12631#ifdef LIVE_OBJECT_LIST
12632  return LiveObjectList::Capture();
12633#else
12634  return isolate->heap()->undefined_value();
12635#endif
12636}
12637
12638
12639// Deletes the specified live object list.
12640RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteLOL) {
12641#ifdef LIVE_OBJECT_LIST
12642  CONVERT_SMI_ARG_CHECKED(id, 0);
12643  bool success = LiveObjectList::Delete(id);
12644  return isolate->heap()->ToBoolean(success);
12645#else
12646  return isolate->heap()->undefined_value();
12647#endif
12648}
12649
12650
12651// Generates the response to a debugger request for a dump of the objects
12652// contained in the difference between the captured live object lists
12653// specified by id1 and id2.
12654// If id1 is 0 (i.e. not a valid lol), then the whole of lol id2 will be
12655// dumped.
12656RUNTIME_FUNCTION(MaybeObject*, Runtime_DumpLOL) {
12657#ifdef LIVE_OBJECT_LIST
12658  HandleScope scope;
12659  CONVERT_SMI_ARG_CHECKED(id1, 0);
12660  CONVERT_SMI_ARG_CHECKED(id2, 1);
12661  CONVERT_SMI_ARG_CHECKED(start, 2);
12662  CONVERT_SMI_ARG_CHECKED(count, 3);
12663  CONVERT_ARG_HANDLE_CHECKED(JSObject, filter_obj, 4);
12664  EnterDebugger enter_debugger;
12665  return LiveObjectList::Dump(id1, id2, start, count, filter_obj);
12666#else
12667  return isolate->heap()->undefined_value();
12668#endif
12669}
12670
12671
12672// Gets the specified object as requested by the debugger.
12673// This is only used for obj ids shown in live object lists.
12674RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObj) {
12675#ifdef LIVE_OBJECT_LIST
12676  CONVERT_SMI_ARG_CHECKED(obj_id, 0);
12677  Object* result = LiveObjectList::GetObj(obj_id);
12678  return result;
12679#else
12680  return isolate->heap()->undefined_value();
12681#endif
12682}
12683
12684
12685// Gets the obj id for the specified address if valid.
12686// This is only used for obj ids shown in live object lists.
12687RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObjId) {
12688#ifdef LIVE_OBJECT_LIST
12689  HandleScope scope;
12690  CONVERT_ARG_HANDLE_CHECKED(String, address, 0);
12691  Object* result = LiveObjectList::GetObjId(address);
12692  return result;
12693#else
12694  return isolate->heap()->undefined_value();
12695#endif
12696}
12697
12698
12699// Gets the retainers that references the specified object alive.
12700RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObjRetainers) {
12701#ifdef LIVE_OBJECT_LIST
12702  HandleScope scope;
12703  CONVERT_SMI_ARG_CHECKED(obj_id, 0);
12704  RUNTIME_ASSERT(args[1]->IsUndefined() || args[1]->IsJSObject());
12705  RUNTIME_ASSERT(args[2]->IsUndefined() || args[2]->IsBoolean());
12706  RUNTIME_ASSERT(args[3]->IsUndefined() || args[3]->IsSmi());
12707  RUNTIME_ASSERT(args[4]->IsUndefined() || args[4]->IsSmi());
12708  CONVERT_ARG_HANDLE_CHECKED(JSObject, filter_obj, 5);
12709
12710  Handle<JSObject> instance_filter;
12711  if (args[1]->IsJSObject()) {
12712    instance_filter = args.at<JSObject>(1);
12713  }
12714  bool verbose = false;
12715  if (args[2]->IsBoolean()) {
12716    verbose = args[2]->IsTrue();
12717  }
12718  int start = 0;
12719  if (args[3]->IsSmi()) {
12720    start = args.smi_at(3);
12721  }
12722  int limit = Smi::kMaxValue;
12723  if (args[4]->IsSmi()) {
12724    limit = args.smi_at(4);
12725  }
12726
12727  return LiveObjectList::GetObjRetainers(obj_id,
12728                                         instance_filter,
12729                                         verbose,
12730                                         start,
12731                                         limit,
12732                                         filter_obj);
12733#else
12734  return isolate->heap()->undefined_value();
12735#endif
12736}
12737
12738
12739// Gets the reference path between 2 objects.
12740RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLPath) {
12741#ifdef LIVE_OBJECT_LIST
12742  HandleScope scope;
12743  CONVERT_SMI_ARG_CHECKED(obj_id1, 0);
12744  CONVERT_SMI_ARG_CHECKED(obj_id2, 1);
12745  RUNTIME_ASSERT(args[2]->IsUndefined() || args[2]->IsJSObject());
12746
12747  Handle<JSObject> instance_filter;
12748  if (args[2]->IsJSObject()) {
12749    instance_filter = args.at<JSObject>(2);
12750  }
12751
12752  Object* result =
12753      LiveObjectList::GetPath(obj_id1, obj_id2, instance_filter);
12754  return result;
12755#else
12756  return isolate->heap()->undefined_value();
12757#endif
12758}
12759
12760
12761// Generates the response to a debugger request for a list of all
12762// previously captured live object lists.
12763RUNTIME_FUNCTION(MaybeObject*, Runtime_InfoLOL) {
12764#ifdef LIVE_OBJECT_LIST
12765  CONVERT_SMI_ARG_CHECKED(start, 0);
12766  CONVERT_SMI_ARG_CHECKED(count, 1);
12767  return LiveObjectList::Info(start, count);
12768#else
12769  return isolate->heap()->undefined_value();
12770#endif
12771}
12772
12773
12774// Gets a dump of the specified object as requested by the debugger.
12775// This is only used for obj ids shown in live object lists.
12776RUNTIME_FUNCTION(MaybeObject*, Runtime_PrintLOLObj) {
12777#ifdef LIVE_OBJECT_LIST
12778  HandleScope scope;
12779  CONVERT_SMI_ARG_CHECKED(obj_id, 0);
12780  Object* result = LiveObjectList::PrintObj(obj_id);
12781  return result;
12782#else
12783  return isolate->heap()->undefined_value();
12784#endif
12785}
12786
12787
12788// Resets and releases all previously captured live object lists.
12789RUNTIME_FUNCTION(MaybeObject*, Runtime_ResetLOL) {
12790#ifdef LIVE_OBJECT_LIST
12791  LiveObjectList::Reset();
12792  return isolate->heap()->undefined_value();
12793#else
12794  return isolate->heap()->undefined_value();
12795#endif
12796}
12797
12798
12799// Generates the response to a debugger request for a summary of the types
12800// of objects in the difference between the captured live object lists
12801// specified by id1 and id2.
12802// If id1 is 0 (i.e. not a valid lol), then the whole of lol id2 will be
12803// summarized.
12804RUNTIME_FUNCTION(MaybeObject*, Runtime_SummarizeLOL) {
12805#ifdef LIVE_OBJECT_LIST
12806  HandleScope scope;
12807  CONVERT_SMI_ARG_CHECKED(id1, 0);
12808  CONVERT_SMI_ARG_CHECKED(id2, 1);
12809  CONVERT_ARG_HANDLE_CHECKED(JSObject, filter_obj, 2);
12810
12811  EnterDebugger enter_debugger;
12812  return LiveObjectList::Summarize(id1, id2, filter_obj);
12813#else
12814  return isolate->heap()->undefined_value();
12815#endif
12816}
12817
12818#endif  // ENABLE_DEBUGGER_SUPPORT
12819
12820
12821RUNTIME_FUNCTION(MaybeObject*, Runtime_ProfilerResume) {
12822  NoHandleAllocation ha;
12823  v8::V8::ResumeProfiler();
12824  return isolate->heap()->undefined_value();
12825}
12826
12827
12828RUNTIME_FUNCTION(MaybeObject*, Runtime_ProfilerPause) {
12829  NoHandleAllocation ha;
12830  v8::V8::PauseProfiler();
12831  return isolate->heap()->undefined_value();
12832}
12833
12834
12835// Finds the script object from the script data. NOTE: This operation uses
12836// heap traversal to find the function generated for the source position
12837// for the requested break point. For lazily compiled functions several heap
12838// traversals might be required rendering this operation as a rather slow
12839// operation. However for setting break points which is normally done through
12840// some kind of user interaction the performance is not crucial.
12841static Handle<Object> Runtime_GetScriptFromScriptName(
12842    Handle<String> script_name) {
12843  // Scan the heap for Script objects to find the script with the requested
12844  // script data.
12845  Handle<Script> script;
12846  script_name->GetHeap()->EnsureHeapIsIterable();
12847  AssertNoAllocation no_allocation_during_heap_iteration;
12848  HeapIterator iterator;
12849  HeapObject* obj = NULL;
12850  while (script.is_null() && ((obj = iterator.next()) != NULL)) {
12851    // If a script is found check if it has the script data requested.
12852    if (obj->IsScript()) {
12853      if (Script::cast(obj)->name()->IsString()) {
12854        if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) {
12855          script = Handle<Script>(Script::cast(obj));
12856        }
12857      }
12858    }
12859  }
12860
12861  // If no script with the requested script data is found return undefined.
12862  if (script.is_null()) return FACTORY->undefined_value();
12863
12864  // Return the script found.
12865  return GetScriptWrapper(script);
12866}
12867
12868
12869// Get the script object from script data. NOTE: Regarding performance
12870// see the NOTE for GetScriptFromScriptData.
12871// args[0]: script data for the script to find the source for
12872RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScript) {
12873  HandleScope scope(isolate);
12874
12875  ASSERT(args.length() == 1);
12876
12877  CONVERT_ARG_CHECKED(String, script_name, 0);
12878
12879  // Find the requested script.
12880  Handle<Object> result =
12881      Runtime_GetScriptFromScriptName(Handle<String>(script_name));
12882  return *result;
12883}
12884
12885
12886// Determines whether the given stack frame should be displayed in
12887// a stack trace.  The caller is the error constructor that asked
12888// for the stack trace to be collected.  The first time a construct
12889// call to this function is encountered it is skipped.  The seen_caller
12890// in/out parameter is used to remember if the caller has been seen
12891// yet.
12892static bool ShowFrameInStackTrace(StackFrame* raw_frame,
12893                                  Object* caller,
12894                                  bool* seen_caller) {
12895  // Only display JS frames.
12896  if (!raw_frame->is_java_script()) {
12897    return false;
12898  }
12899  JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
12900  Object* raw_fun = frame->function();
12901  // Not sure when this can happen but skip it just in case.
12902  if (!raw_fun->IsJSFunction()) {
12903    return false;
12904  }
12905  if ((raw_fun == caller) && !(*seen_caller)) {
12906    *seen_caller = true;
12907    return false;
12908  }
12909  // Skip all frames until we've seen the caller.
12910  if (!(*seen_caller)) return false;
12911  // Also, skip non-visible built-in functions and any call with the builtins
12912  // object as receiver, so as to not reveal either the builtins object or
12913  // an internal function.
12914  // The --builtins-in-stack-traces command line flag allows including
12915  // internal call sites in the stack trace for debugging purposes.
12916  if (!FLAG_builtins_in_stack_traces) {
12917    JSFunction* fun = JSFunction::cast(raw_fun);
12918    if (frame->receiver()->IsJSBuiltinsObject() ||
12919        (fun->IsBuiltin() && !fun->shared()->native())) {
12920      return false;
12921    }
12922  }
12923  return true;
12924}
12925
12926
12927// Collect the raw data for a stack trace.  Returns an array of 4
12928// element segments each containing a receiver, function, code and
12929// native code offset.
12930RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectStackTrace) {
12931  ASSERT_EQ(args.length(), 3);
12932  CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
12933  Handle<Object> caller = args.at<Object>(1);
12934  CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[2]);
12935
12936  HandleScope scope(isolate);
12937  Factory* factory = isolate->factory();
12938
12939  limit = Max(limit, 0);  // Ensure that limit is not negative.
12940  int initial_size = Min(limit, 10);
12941  Handle<FixedArray> elements =
12942      factory->NewFixedArrayWithHoles(initial_size * 4);
12943
12944  StackFrameIterator iter(isolate);
12945  // If the caller parameter is a function we skip frames until we're
12946  // under it before starting to collect.
12947  bool seen_caller = !caller->IsJSFunction();
12948  int cursor = 0;
12949  int frames_seen = 0;
12950  while (!iter.done() && frames_seen < limit) {
12951    StackFrame* raw_frame = iter.frame();
12952    if (ShowFrameInStackTrace(raw_frame, *caller, &seen_caller)) {
12953      frames_seen++;
12954      JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
12955      // Set initial size to the maximum inlining level + 1 for the outermost
12956      // function.
12957      List<FrameSummary> frames(Compiler::kMaxInliningLevels + 1);
12958      frame->Summarize(&frames);
12959      for (int i = frames.length() - 1; i >= 0; i--) {
12960        if (cursor + 4 > elements->length()) {
12961          int new_capacity = JSObject::NewElementsCapacity(elements->length());
12962          Handle<FixedArray> new_elements =
12963              factory->NewFixedArrayWithHoles(new_capacity);
12964          for (int i = 0; i < cursor; i++) {
12965            new_elements->set(i, elements->get(i));
12966          }
12967          elements = new_elements;
12968        }
12969        ASSERT(cursor + 4 <= elements->length());
12970
12971        Handle<Object> recv = frames[i].receiver();
12972        Handle<JSFunction> fun = frames[i].function();
12973        Handle<Code> code = frames[i].code();
12974        Handle<Smi> offset(Smi::FromInt(frames[i].offset()));
12975        elements->set(cursor++, *recv);
12976        elements->set(cursor++, *fun);
12977        elements->set(cursor++, *code);
12978        elements->set(cursor++, *offset);
12979      }
12980    }
12981    iter.Advance();
12982  }
12983  Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
12984  // Capture and attach a more detailed stack trace if necessary.
12985  isolate->CaptureAndSetCurrentStackTraceFor(error_object);
12986  result->set_length(Smi::FromInt(cursor));
12987  return *result;
12988}
12989
12990
12991// Returns V8 version as a string.
12992RUNTIME_FUNCTION(MaybeObject*, Runtime_GetV8Version) {
12993  ASSERT_EQ(args.length(), 0);
12994
12995  NoHandleAllocation ha;
12996
12997  const char* version_string = v8::V8::GetVersion();
12998
12999  return isolate->heap()->AllocateStringFromAscii(CStrVector(version_string),
13000                                                  NOT_TENURED);
13001}
13002
13003
13004RUNTIME_FUNCTION(MaybeObject*, Runtime_Abort) {
13005  ASSERT(args.length() == 2);
13006  OS::PrintError("abort: %s\n",
13007                 reinterpret_cast<char*>(args[0]) + args.smi_at(1));
13008  isolate->PrintStack();
13009  OS::Abort();
13010  UNREACHABLE();
13011  return NULL;
13012}
13013
13014
13015RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFromCache) {
13016  // This is only called from codegen, so checks might be more lax.
13017  CONVERT_ARG_CHECKED(JSFunctionResultCache, cache, 0);
13018  Object* key = args[1];
13019
13020  int finger_index = cache->finger_index();
13021  Object* o = cache->get(finger_index);
13022  if (o == key) {
13023    // The fastest case: hit the same place again.
13024    return cache->get(finger_index + 1);
13025  }
13026
13027  for (int i = finger_index - 2;
13028       i >= JSFunctionResultCache::kEntriesIndex;
13029       i -= 2) {
13030    o = cache->get(i);
13031    if (o == key) {
13032      cache->set_finger_index(i);
13033      return cache->get(i + 1);
13034    }
13035  }
13036
13037  int size = cache->size();
13038  ASSERT(size <= cache->length());
13039
13040  for (int i = size - 2; i > finger_index; i -= 2) {
13041    o = cache->get(i);
13042    if (o == key) {
13043      cache->set_finger_index(i);
13044      return cache->get(i + 1);
13045    }
13046  }
13047
13048  // There is no value in the cache.  Invoke the function and cache result.
13049  HandleScope scope(isolate);
13050
13051  Handle<JSFunctionResultCache> cache_handle(cache);
13052  Handle<Object> key_handle(key);
13053  Handle<Object> value;
13054  {
13055    Handle<JSFunction> factory(JSFunction::cast(
13056          cache_handle->get(JSFunctionResultCache::kFactoryIndex)));
13057    // TODO(antonm): consider passing a receiver when constructing a cache.
13058    Handle<Object> receiver(isolate->global_context()->global());
13059    // This handle is nor shared, nor used later, so it's safe.
13060    Handle<Object> argv[] = { key_handle };
13061    bool pending_exception;
13062    value = Execution::Call(factory,
13063                            receiver,
13064                            ARRAY_SIZE(argv),
13065                            argv,
13066                            &pending_exception);
13067    if (pending_exception) return Failure::Exception();
13068  }
13069
13070#ifdef DEBUG
13071  if (FLAG_verify_heap) {
13072    cache_handle->JSFunctionResultCacheVerify();
13073  }
13074#endif
13075
13076  // Function invocation may have cleared the cache.  Reread all the data.
13077  finger_index = cache_handle->finger_index();
13078  size = cache_handle->size();
13079
13080  // If we have spare room, put new data into it, otherwise evict post finger
13081  // entry which is likely to be the least recently used.
13082  int index = -1;
13083  if (size < cache_handle->length()) {
13084    cache_handle->set_size(size + JSFunctionResultCache::kEntrySize);
13085    index = size;
13086  } else {
13087    index = finger_index + JSFunctionResultCache::kEntrySize;
13088    if (index == cache_handle->length()) {
13089      index = JSFunctionResultCache::kEntriesIndex;
13090    }
13091  }
13092
13093  ASSERT(index % 2 == 0);
13094  ASSERT(index >= JSFunctionResultCache::kEntriesIndex);
13095  ASSERT(index < cache_handle->length());
13096
13097  cache_handle->set(index, *key_handle);
13098  cache_handle->set(index + 1, *value);
13099  cache_handle->set_finger_index(index);
13100
13101#ifdef DEBUG
13102  if (FLAG_verify_heap) {
13103    cache_handle->JSFunctionResultCacheVerify();
13104  }
13105#endif
13106
13107  return *value;
13108}
13109
13110
13111RUNTIME_FUNCTION(MaybeObject*, Runtime_NewMessageObject) {
13112  HandleScope scope(isolate);
13113  CONVERT_ARG_HANDLE_CHECKED(String, type, 0);
13114  CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 1);
13115  return *isolate->factory()->NewJSMessageObject(
13116      type,
13117      arguments,
13118      0,
13119      0,
13120      isolate->factory()->undefined_value(),
13121      isolate->factory()->undefined_value(),
13122      isolate->factory()->undefined_value());
13123}
13124
13125
13126RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetType) {
13127  CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
13128  return message->type();
13129}
13130
13131
13132RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetArguments) {
13133  CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
13134  return message->arguments();
13135}
13136
13137
13138RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetStartPosition) {
13139  CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
13140  return Smi::FromInt(message->start_position());
13141}
13142
13143
13144RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetScript) {
13145  CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
13146  return message->script();
13147}
13148
13149
13150#ifdef DEBUG
13151// ListNatives is ONLY used by the fuzz-natives.js in debug mode
13152// Exclude the code in release mode.
13153RUNTIME_FUNCTION(MaybeObject*, Runtime_ListNatives) {
13154  ASSERT(args.length() == 0);
13155  HandleScope scope;
13156#define COUNT_ENTRY(Name, argc, ressize) + 1
13157  int entry_count = 0
13158      RUNTIME_FUNCTION_LIST(COUNT_ENTRY)
13159      INLINE_FUNCTION_LIST(COUNT_ENTRY)
13160      INLINE_RUNTIME_FUNCTION_LIST(COUNT_ENTRY);
13161#undef COUNT_ENTRY
13162  Factory* factory = isolate->factory();
13163  Handle<FixedArray> elements = factory->NewFixedArray(entry_count);
13164  int index = 0;
13165  bool inline_runtime_functions = false;
13166#define ADD_ENTRY(Name, argc, ressize)                                       \
13167  {                                                                          \
13168    HandleScope inner;                                                       \
13169    Handle<String> name;                                                     \
13170    /* Inline runtime functions have an underscore in front of the name. */  \
13171    if (inline_runtime_functions) {                                          \
13172      name = factory->NewStringFromAscii(                                    \
13173          Vector<const char>("_" #Name, StrLength("_" #Name)));              \
13174    } else {                                                                 \
13175      name = factory->NewStringFromAscii(                                    \
13176          Vector<const char>(#Name, StrLength(#Name)));                      \
13177    }                                                                        \
13178    Handle<FixedArray> pair_elements = factory->NewFixedArray(2);            \
13179    pair_elements->set(0, *name);                                            \
13180    pair_elements->set(1, Smi::FromInt(argc));                               \
13181    Handle<JSArray> pair = factory->NewJSArrayWithElements(pair_elements);   \
13182    elements->set(index++, *pair);                                           \
13183  }
13184  inline_runtime_functions = false;
13185  RUNTIME_FUNCTION_LIST(ADD_ENTRY)
13186  inline_runtime_functions = true;
13187  INLINE_FUNCTION_LIST(ADD_ENTRY)
13188  INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY)
13189#undef ADD_ENTRY
13190  ASSERT_EQ(index, entry_count);
13191  Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
13192  return *result;
13193}
13194#endif
13195
13196
13197RUNTIME_FUNCTION(MaybeObject*, Runtime_Log) {
13198  ASSERT(args.length() == 2);
13199  CONVERT_ARG_CHECKED(String, format, 0);
13200  CONVERT_ARG_CHECKED(JSArray, elms, 1);
13201  String::FlatContent format_content = format->GetFlatContent();
13202  RUNTIME_ASSERT(format_content.IsAscii());
13203  Vector<const char> chars = format_content.ToAsciiVector();
13204  LOGGER->LogRuntime(chars, elms);
13205  return isolate->heap()->undefined_value();
13206}
13207
13208
13209RUNTIME_FUNCTION(MaybeObject*, Runtime_IS_VAR) {
13210  UNREACHABLE();  // implemented as macro in the parser
13211  return NULL;
13212}
13213
13214
13215#define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name)        \
13216  RUNTIME_FUNCTION(MaybeObject*, Runtime_Has##Name) {     \
13217    CONVERT_ARG_CHECKED(JSObject, obj, 0);              \
13218    return isolate->heap()->ToBoolean(obj->Has##Name());  \
13219  }
13220
13221ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOnlyElements)
13222ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastElements)
13223ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
13224ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
13225ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalPixelElements)
13226ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
13227ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalByteElements)
13228ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedByteElements)
13229ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalShortElements)
13230ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedShortElements)
13231ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalIntElements)
13232ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedIntElements)
13233ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalFloatElements)
13234ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalDoubleElements)
13235
13236#undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
13237
13238
13239RUNTIME_FUNCTION(MaybeObject*, Runtime_HaveSameMap) {
13240  ASSERT(args.length() == 2);
13241  CONVERT_ARG_CHECKED(JSObject, obj1, 0);
13242  CONVERT_ARG_CHECKED(JSObject, obj2, 1);
13243  return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
13244}
13245
13246// ----------------------------------------------------------------------------
13247// Implementation of Runtime
13248
13249#define F(name, number_of_args, result_size)                             \
13250  { Runtime::k##name, Runtime::RUNTIME, #name,   \
13251    FUNCTION_ADDR(Runtime_##name), number_of_args, result_size },
13252
13253
13254#define I(name, number_of_args, result_size)                             \
13255  { Runtime::kInline##name, Runtime::INLINE,     \
13256    "_" #name, NULL, number_of_args, result_size },
13257
13258static const Runtime::Function kIntrinsicFunctions[] = {
13259  RUNTIME_FUNCTION_LIST(F)
13260  INLINE_FUNCTION_LIST(I)
13261  INLINE_RUNTIME_FUNCTION_LIST(I)
13262};
13263
13264
13265MaybeObject* Runtime::InitializeIntrinsicFunctionNames(Heap* heap,
13266                                                       Object* dictionary) {
13267  ASSERT(Isolate::Current()->heap() == heap);
13268  ASSERT(dictionary != NULL);
13269  ASSERT(StringDictionary::cast(dictionary)->NumberOfElements() == 0);
13270  for (int i = 0; i < kNumFunctions; ++i) {
13271    Object* name_symbol;
13272    { MaybeObject* maybe_name_symbol =
13273          heap->LookupAsciiSymbol(kIntrinsicFunctions[i].name);
13274      if (!maybe_name_symbol->ToObject(&name_symbol)) return maybe_name_symbol;
13275    }
13276    StringDictionary* string_dictionary = StringDictionary::cast(dictionary);
13277    { MaybeObject* maybe_dictionary = string_dictionary->Add(
13278          String::cast(name_symbol),
13279          Smi::FromInt(i),
13280          PropertyDetails(NONE, NORMAL));
13281      if (!maybe_dictionary->ToObject(&dictionary)) {
13282        // Non-recoverable failure.  Calling code must restart heap
13283        // initialization.
13284        return maybe_dictionary;
13285      }
13286    }
13287  }
13288  return dictionary;
13289}
13290
13291
13292const Runtime::Function* Runtime::FunctionForSymbol(Handle<String> name) {
13293  Heap* heap = name->GetHeap();
13294  int entry = heap->intrinsic_function_names()->FindEntry(*name);
13295  if (entry != kNotFound) {
13296    Object* smi_index = heap->intrinsic_function_names()->ValueAt(entry);
13297    int function_index = Smi::cast(smi_index)->value();
13298    return &(kIntrinsicFunctions[function_index]);
13299  }
13300  return NULL;
13301}
13302
13303
13304const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
13305  return &(kIntrinsicFunctions[static_cast<int>(id)]);
13306}
13307
13308
13309void Runtime::PerformGC(Object* result) {
13310  Isolate* isolate = Isolate::Current();
13311  Failure* failure = Failure::cast(result);
13312  if (failure->IsRetryAfterGC()) {
13313    if (isolate->heap()->new_space()->AddFreshPage()) {
13314      return;
13315    }
13316
13317    // Try to do a garbage collection; ignore it if it fails. The C
13318    // entry stub will throw an out-of-memory exception in that case.
13319    isolate->heap()->CollectGarbage(failure->allocation_space(),
13320                                    "Runtime::PerformGC");
13321  } else {
13322    // Handle last resort GC and make sure to allow future allocations
13323    // to grow the heap without causing GCs (if possible).
13324    isolate->counters()->gc_last_resort_from_js()->Increment();
13325    isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
13326                                       "Runtime::PerformGC");
13327  }
13328}
13329
13330
13331} }  // namespace v8::internal
13332