runtime.cc revision 25f6136652d8341ed047e7fc1a450af5bd218ea9
1// Copyright 2006-2009 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 "codegen.h"
36#include "compiler.h"
37#include "cpu.h"
38#include "dateparser-inl.h"
39#include "debug.h"
40#include "execution.h"
41#include "jsregexp.h"
42#include "liveedit.h"
43#include "parser.h"
44#include "platform.h"
45#include "runtime.h"
46#include "scopeinfo.h"
47#include "smart-pointer.h"
48#include "stub-cache.h"
49#include "v8threads.h"
50
51namespace v8 {
52namespace internal {
53
54
55#define RUNTIME_ASSERT(value) \
56  if (!(value)) return Top::ThrowIllegalOperation();
57
58// Cast the given object to a value of the specified type and store
59// it in a variable with the given name.  If the object is not of the
60// expected type call IllegalOperation and return.
61#define CONVERT_CHECKED(Type, name, obj)                             \
62  RUNTIME_ASSERT(obj->Is##Type());                                   \
63  Type* name = Type::cast(obj);
64
65#define CONVERT_ARG_CHECKED(Type, name, index)                       \
66  RUNTIME_ASSERT(args[index]->Is##Type());                           \
67  Handle<Type> name = args.at<Type>(index);
68
69// Cast the given object to a boolean and store it in a variable with
70// the given name.  If the object is not a boolean call IllegalOperation
71// and return.
72#define CONVERT_BOOLEAN_CHECKED(name, obj)                            \
73  RUNTIME_ASSERT(obj->IsBoolean());                                   \
74  bool name = (obj)->IsTrue();
75
76// Cast the given object to a Smi and store its value in an int variable
77// with the given name.  If the object is not a Smi call IllegalOperation
78// and return.
79#define CONVERT_SMI_CHECKED(name, obj)                            \
80  RUNTIME_ASSERT(obj->IsSmi());                                   \
81  int name = Smi::cast(obj)->value();
82
83// Cast the given object to a double and store it in a variable with
84// the given name.  If the object is not a number (as opposed to
85// the number not-a-number) call IllegalOperation and return.
86#define CONVERT_DOUBLE_CHECKED(name, obj)                            \
87  RUNTIME_ASSERT(obj->IsNumber());                                   \
88  double name = (obj)->Number();
89
90// Call the specified converter on the object *comand store the result in
91// a variable of the specified type with the given name.  If the
92// object is not a Number call IllegalOperation and return.
93#define CONVERT_NUMBER_CHECKED(type, name, Type, obj)                \
94  RUNTIME_ASSERT(obj->IsNumber());                                   \
95  type name = NumberTo##Type(obj);
96
97// Non-reentrant string buffer for efficient general use in this file.
98static StaticResource<StringInputBuffer> runtime_string_input_buffer;
99
100
101static Object* DeepCopyBoilerplate(JSObject* boilerplate) {
102  StackLimitCheck check;
103  if (check.HasOverflowed()) return Top::StackOverflow();
104
105  Object* result = Heap::CopyJSObject(boilerplate);
106  if (result->IsFailure()) return result;
107  JSObject* copy = JSObject::cast(result);
108
109  // Deep copy local properties.
110  if (copy->HasFastProperties()) {
111    FixedArray* properties = copy->properties();
112    for (int i = 0; i < properties->length(); i++) {
113      Object* value = properties->get(i);
114      if (value->IsJSObject()) {
115        JSObject* js_object = JSObject::cast(value);
116        result = DeepCopyBoilerplate(js_object);
117        if (result->IsFailure()) return result;
118        properties->set(i, result);
119      }
120    }
121    int nof = copy->map()->inobject_properties();
122    for (int i = 0; i < nof; i++) {
123      Object* value = copy->InObjectPropertyAt(i);
124      if (value->IsJSObject()) {
125        JSObject* js_object = JSObject::cast(value);
126        result = DeepCopyBoilerplate(js_object);
127        if (result->IsFailure()) return result;
128        copy->InObjectPropertyAtPut(i, result);
129      }
130    }
131  } else {
132    result = Heap::AllocateFixedArray(copy->NumberOfLocalProperties(NONE));
133    if (result->IsFailure()) return result;
134    FixedArray* names = FixedArray::cast(result);
135    copy->GetLocalPropertyNames(names, 0);
136    for (int i = 0; i < names->length(); i++) {
137      ASSERT(names->get(i)->IsString());
138      String* key_string = String::cast(names->get(i));
139      PropertyAttributes attributes =
140          copy->GetLocalPropertyAttribute(key_string);
141      // Only deep copy fields from the object literal expression.
142      // In particular, don't try to copy the length attribute of
143      // an array.
144      if (attributes != NONE) continue;
145      Object* value = copy->GetProperty(key_string, &attributes);
146      ASSERT(!value->IsFailure());
147      if (value->IsJSObject()) {
148        JSObject* js_object = JSObject::cast(value);
149        result = DeepCopyBoilerplate(js_object);
150        if (result->IsFailure()) return result;
151        result = copy->SetProperty(key_string, result, NONE);
152        if (result->IsFailure()) return result;
153      }
154    }
155  }
156
157  // Deep copy local elements.
158  // Pixel elements cannot be created using an object literal.
159  ASSERT(!copy->HasPixelElements() && !copy->HasExternalArrayElements());
160  switch (copy->GetElementsKind()) {
161    case JSObject::FAST_ELEMENTS: {
162      FixedArray* elements = FixedArray::cast(copy->elements());
163      for (int i = 0; i < elements->length(); i++) {
164        Object* value = elements->get(i);
165        if (value->IsJSObject()) {
166          JSObject* js_object = JSObject::cast(value);
167          result = DeepCopyBoilerplate(js_object);
168          if (result->IsFailure()) return result;
169          elements->set(i, result);
170        }
171      }
172      break;
173    }
174    case JSObject::DICTIONARY_ELEMENTS: {
175      NumberDictionary* element_dictionary = copy->element_dictionary();
176      int capacity = element_dictionary->Capacity();
177      for (int i = 0; i < capacity; i++) {
178        Object* k = element_dictionary->KeyAt(i);
179        if (element_dictionary->IsKey(k)) {
180          Object* value = element_dictionary->ValueAt(i);
181          if (value->IsJSObject()) {
182            JSObject* js_object = JSObject::cast(value);
183            result = DeepCopyBoilerplate(js_object);
184            if (result->IsFailure()) return result;
185            element_dictionary->ValueAtPut(i, result);
186          }
187        }
188      }
189      break;
190    }
191    default:
192      UNREACHABLE();
193      break;
194  }
195  return copy;
196}
197
198
199static Object* Runtime_CloneLiteralBoilerplate(Arguments args) {
200  CONVERT_CHECKED(JSObject, boilerplate, args[0]);
201  return DeepCopyBoilerplate(boilerplate);
202}
203
204
205static Object* Runtime_CloneShallowLiteralBoilerplate(Arguments args) {
206  CONVERT_CHECKED(JSObject, boilerplate, args[0]);
207  return Heap::CopyJSObject(boilerplate);
208}
209
210
211static Handle<Map> ComputeObjectLiteralMap(
212    Handle<Context> context,
213    Handle<FixedArray> constant_properties,
214    bool* is_result_from_cache) {
215  int number_of_properties = constant_properties->length() / 2;
216  if (FLAG_canonicalize_object_literal_maps) {
217    // First find prefix of consecutive symbol keys.
218    int number_of_symbol_keys = 0;
219    while ((number_of_symbol_keys < number_of_properties) &&
220           (constant_properties->get(number_of_symbol_keys*2)->IsSymbol())) {
221      number_of_symbol_keys++;
222    }
223    // Based on the number of prefix symbols key we decide whether
224    // to use the map cache in the global context.
225    const int kMaxKeys = 10;
226    if ((number_of_symbol_keys == number_of_properties) &&
227        (number_of_symbol_keys < kMaxKeys)) {
228      // Create the fixed array with the key.
229      Handle<FixedArray> keys = Factory::NewFixedArray(number_of_symbol_keys);
230      for (int i = 0; i < number_of_symbol_keys; i++) {
231        keys->set(i, constant_properties->get(i*2));
232      }
233      *is_result_from_cache = true;
234      return Factory::ObjectLiteralMapFromCache(context, keys);
235    }
236  }
237  *is_result_from_cache = false;
238  return Factory::CopyMap(
239      Handle<Map>(context->object_function()->initial_map()),
240      number_of_properties);
241}
242
243
244static Handle<Object> CreateLiteralBoilerplate(
245    Handle<FixedArray> literals,
246    Handle<FixedArray> constant_properties);
247
248
249static Handle<Object> CreateObjectLiteralBoilerplate(
250    Handle<FixedArray> literals,
251    Handle<FixedArray> constant_properties,
252    bool should_have_fast_elements) {
253  // Get the global context from the literals array.  This is the
254  // context in which the function was created and we use the object
255  // function from this context to create the object literal.  We do
256  // not use the object function from the current global context
257  // because this might be the object function from another context
258  // which we should not have access to.
259  Handle<Context> context =
260      Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals));
261
262  bool is_result_from_cache;
263  Handle<Map> map = ComputeObjectLiteralMap(context,
264                                            constant_properties,
265                                            &is_result_from_cache);
266
267  Handle<JSObject> boilerplate = Factory::NewJSObjectFromMap(map);
268
269  // Normalize the elements of the boilerplate to save space if needed.
270  if (!should_have_fast_elements) NormalizeElements(boilerplate);
271
272  {  // Add the constant properties to the boilerplate.
273    int length = constant_properties->length();
274    OptimizedObjectForAddingMultipleProperties opt(boilerplate,
275                                                   length / 2,
276                                                   !is_result_from_cache);
277    for (int index = 0; index < length; index +=2) {
278      Handle<Object> key(constant_properties->get(index+0));
279      Handle<Object> value(constant_properties->get(index+1));
280      if (value->IsFixedArray()) {
281        // The value contains the constant_properties of a
282        // simple object literal.
283        Handle<FixedArray> array = Handle<FixedArray>::cast(value);
284        value = CreateLiteralBoilerplate(literals, array);
285        if (value.is_null()) return value;
286      }
287      Handle<Object> result;
288      uint32_t element_index = 0;
289      if (key->IsSymbol()) {
290        // If key is a symbol it is not an array element.
291        Handle<String> name(String::cast(*key));
292        ASSERT(!name->AsArrayIndex(&element_index));
293        result = SetProperty(boilerplate, name, value, NONE);
294      } else if (Array::IndexFromObject(*key, &element_index)) {
295        // Array index (uint32).
296        result = SetElement(boilerplate, element_index, value);
297      } else {
298        // Non-uint32 number.
299        ASSERT(key->IsNumber());
300        double num = key->Number();
301        char arr[100];
302        Vector<char> buffer(arr, ARRAY_SIZE(arr));
303        const char* str = DoubleToCString(num, buffer);
304        Handle<String> name = Factory::NewStringFromAscii(CStrVector(str));
305        result = SetProperty(boilerplate, name, value, NONE);
306      }
307      // If setting the property on the boilerplate throws an
308      // exception, the exception is converted to an empty handle in
309      // the handle based operations.  In that case, we need to
310      // convert back to an exception.
311      if (result.is_null()) return result;
312    }
313  }
314
315  return boilerplate;
316}
317
318
319static Handle<Object> CreateArrayLiteralBoilerplate(
320    Handle<FixedArray> literals,
321    Handle<FixedArray> elements) {
322  // Create the JSArray.
323  Handle<JSFunction> constructor(
324      JSFunction::GlobalContextFromLiterals(*literals)->array_function());
325  Handle<Object> object = Factory::NewJSObject(constructor);
326
327  Handle<Object> copied_elements = Factory::CopyFixedArray(elements);
328
329  Handle<FixedArray> content = Handle<FixedArray>::cast(copied_elements);
330  for (int i = 0; i < content->length(); i++) {
331    if (content->get(i)->IsFixedArray()) {
332      // The value contains the constant_properties of a
333      // simple object literal.
334      Handle<FixedArray> fa(FixedArray::cast(content->get(i)));
335      Handle<Object> result =
336        CreateLiteralBoilerplate(literals, fa);
337      if (result.is_null()) return result;
338      content->set(i, *result);
339    }
340  }
341
342  // Set the elements.
343  Handle<JSArray>::cast(object)->SetContent(*content);
344  return object;
345}
346
347
348static Handle<Object> CreateLiteralBoilerplate(
349    Handle<FixedArray> literals,
350    Handle<FixedArray> array) {
351  Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
352  switch (CompileTimeValue::GetType(array)) {
353    case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS:
354      return CreateObjectLiteralBoilerplate(literals, elements, true);
355    case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS:
356      return CreateObjectLiteralBoilerplate(literals, elements, false);
357    case CompileTimeValue::ARRAY_LITERAL:
358      return CreateArrayLiteralBoilerplate(literals, elements);
359    default:
360      UNREACHABLE();
361      return Handle<Object>::null();
362  }
363}
364
365
366static Object* Runtime_CreateArrayLiteralBoilerplate(Arguments args) {
367  // Takes a FixedArray of elements containing the literal elements of
368  // the array literal and produces JSArray with those elements.
369  // Additionally takes the literals array of the surrounding function
370  // which contains the context from which to get the Array function
371  // to use for creating the array literal.
372  HandleScope scope;
373  ASSERT(args.length() == 3);
374  CONVERT_ARG_CHECKED(FixedArray, literals, 0);
375  CONVERT_SMI_CHECKED(literals_index, args[1]);
376  CONVERT_ARG_CHECKED(FixedArray, elements, 2);
377
378  Handle<Object> object = CreateArrayLiteralBoilerplate(literals, elements);
379  if (object.is_null()) return Failure::Exception();
380
381  // Update the functions literal and return the boilerplate.
382  literals->set(literals_index, *object);
383  return *object;
384}
385
386
387static Object* Runtime_CreateObjectLiteral(Arguments args) {
388  HandleScope scope;
389  ASSERT(args.length() == 4);
390  CONVERT_ARG_CHECKED(FixedArray, literals, 0);
391  CONVERT_SMI_CHECKED(literals_index, args[1]);
392  CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2);
393  CONVERT_SMI_CHECKED(fast_elements, args[3]);
394  bool should_have_fast_elements = fast_elements == 1;
395
396  // Check if boilerplate exists. If not, create it first.
397  Handle<Object> boilerplate(literals->get(literals_index));
398  if (*boilerplate == Heap::undefined_value()) {
399    boilerplate = CreateObjectLiteralBoilerplate(literals,
400                                                 constant_properties,
401                                                 should_have_fast_elements);
402    if (boilerplate.is_null()) return Failure::Exception();
403    // Update the functions literal and return the boilerplate.
404    literals->set(literals_index, *boilerplate);
405  }
406  return DeepCopyBoilerplate(JSObject::cast(*boilerplate));
407}
408
409
410static Object* Runtime_CreateObjectLiteralShallow(Arguments args) {
411  HandleScope scope;
412  ASSERT(args.length() == 4);
413  CONVERT_ARG_CHECKED(FixedArray, literals, 0);
414  CONVERT_SMI_CHECKED(literals_index, args[1]);
415  CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2);
416  CONVERT_SMI_CHECKED(fast_elements, args[3]);
417  bool should_have_fast_elements = fast_elements == 1;
418
419  // Check if boilerplate exists. If not, create it first.
420  Handle<Object> boilerplate(literals->get(literals_index));
421  if (*boilerplate == Heap::undefined_value()) {
422    boilerplate = CreateObjectLiteralBoilerplate(literals,
423                                                 constant_properties,
424                                                 should_have_fast_elements);
425    if (boilerplate.is_null()) return Failure::Exception();
426    // Update the functions literal and return the boilerplate.
427    literals->set(literals_index, *boilerplate);
428  }
429  return Heap::CopyJSObject(JSObject::cast(*boilerplate));
430}
431
432
433static Object* Runtime_CreateArrayLiteral(Arguments args) {
434  HandleScope scope;
435  ASSERT(args.length() == 3);
436  CONVERT_ARG_CHECKED(FixedArray, literals, 0);
437  CONVERT_SMI_CHECKED(literals_index, args[1]);
438  CONVERT_ARG_CHECKED(FixedArray, elements, 2);
439
440  // Check if boilerplate exists. If not, create it first.
441  Handle<Object> boilerplate(literals->get(literals_index));
442  if (*boilerplate == Heap::undefined_value()) {
443    boilerplate = CreateArrayLiteralBoilerplate(literals, elements);
444    if (boilerplate.is_null()) return Failure::Exception();
445    // Update the functions literal and return the boilerplate.
446    literals->set(literals_index, *boilerplate);
447  }
448  return DeepCopyBoilerplate(JSObject::cast(*boilerplate));
449}
450
451
452static Object* Runtime_CreateArrayLiteralShallow(Arguments args) {
453  HandleScope scope;
454  ASSERT(args.length() == 3);
455  CONVERT_ARG_CHECKED(FixedArray, literals, 0);
456  CONVERT_SMI_CHECKED(literals_index, args[1]);
457  CONVERT_ARG_CHECKED(FixedArray, elements, 2);
458
459  // Check if boilerplate exists. If not, create it first.
460  Handle<Object> boilerplate(literals->get(literals_index));
461  if (*boilerplate == Heap::undefined_value()) {
462    boilerplate = CreateArrayLiteralBoilerplate(literals, elements);
463    if (boilerplate.is_null()) return Failure::Exception();
464    // Update the functions literal and return the boilerplate.
465    literals->set(literals_index, *boilerplate);
466  }
467  return Heap::CopyJSObject(JSObject::cast(*boilerplate));
468}
469
470
471static Object* Runtime_CreateCatchExtensionObject(Arguments args) {
472  ASSERT(args.length() == 2);
473  CONVERT_CHECKED(String, key, args[0]);
474  Object* value = args[1];
475  // Create a catch context extension object.
476  JSFunction* constructor =
477      Top::context()->global_context()->context_extension_function();
478  Object* object = Heap::AllocateJSObject(constructor);
479  if (object->IsFailure()) return object;
480  // Assign the exception value to the catch variable and make sure
481  // that the catch variable is DontDelete.
482  value = JSObject::cast(object)->SetProperty(key, value, DONT_DELETE);
483  if (value->IsFailure()) return value;
484  return object;
485}
486
487
488static Object* Runtime_ClassOf(Arguments args) {
489  NoHandleAllocation ha;
490  ASSERT(args.length() == 1);
491  Object* obj = args[0];
492  if (!obj->IsJSObject()) return Heap::null_value();
493  return JSObject::cast(obj)->class_name();
494}
495
496
497static Object* Runtime_IsInPrototypeChain(Arguments args) {
498  NoHandleAllocation ha;
499  ASSERT(args.length() == 2);
500  // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
501  Object* O = args[0];
502  Object* V = args[1];
503  while (true) {
504    Object* prototype = V->GetPrototype();
505    if (prototype->IsNull()) return Heap::false_value();
506    if (O == prototype) return Heap::true_value();
507    V = prototype;
508  }
509}
510
511
512// Inserts an object as the hidden prototype of another object.
513static Object* Runtime_SetHiddenPrototype(Arguments args) {
514  NoHandleAllocation ha;
515  ASSERT(args.length() == 2);
516  CONVERT_CHECKED(JSObject, jsobject, args[0]);
517  CONVERT_CHECKED(JSObject, proto, args[1]);
518
519  // Sanity checks.  The old prototype (that we are replacing) could
520  // theoretically be null, but if it is not null then check that we
521  // didn't already install a hidden prototype here.
522  RUNTIME_ASSERT(!jsobject->GetPrototype()->IsHeapObject() ||
523    !HeapObject::cast(jsobject->GetPrototype())->map()->is_hidden_prototype());
524  RUNTIME_ASSERT(!proto->map()->is_hidden_prototype());
525
526  // Allocate up front before we start altering state in case we get a GC.
527  Object* map_or_failure = proto->map()->CopyDropTransitions();
528  if (map_or_failure->IsFailure()) return map_or_failure;
529  Map* new_proto_map = Map::cast(map_or_failure);
530
531  map_or_failure = jsobject->map()->CopyDropTransitions();
532  if (map_or_failure->IsFailure()) return map_or_failure;
533  Map* new_map = Map::cast(map_or_failure);
534
535  // Set proto's prototype to be the old prototype of the object.
536  new_proto_map->set_prototype(jsobject->GetPrototype());
537  proto->set_map(new_proto_map);
538  new_proto_map->set_is_hidden_prototype();
539
540  // Set the object's prototype to proto.
541  new_map->set_prototype(proto);
542  jsobject->set_map(new_map);
543
544  return Heap::undefined_value();
545}
546
547
548static Object* Runtime_IsConstructCall(Arguments args) {
549  NoHandleAllocation ha;
550  ASSERT(args.length() == 0);
551  JavaScriptFrameIterator it;
552  return Heap::ToBoolean(it.frame()->IsConstructor());
553}
554
555
556// Recursively traverses hidden prototypes if property is not found
557static void GetOwnPropertyImplementation(JSObject* obj,
558                                         String* name,
559                                         LookupResult* result) {
560  obj->LocalLookupRealNamedProperty(name, result);
561
562  if (!result->IsProperty()) {
563    Object* proto = obj->GetPrototype();
564    if (proto->IsJSObject() &&
565      JSObject::cast(proto)->map()->is_hidden_prototype())
566      GetOwnPropertyImplementation(JSObject::cast(proto),
567                                   name, result);
568  }
569}
570
571
572// Returns an array with the property description:
573//  if args[1] is not a property on args[0]
574//          returns undefined
575//  if args[1] is a data property on args[0]
576//         [false, value, Writeable, Enumerable, Configurable]
577//  if args[1] is an accessor on args[0]
578//         [true, GetFunction, SetFunction, Enumerable, Configurable]
579static Object* Runtime_GetOwnProperty(Arguments args) {
580  ASSERT(args.length() == 2);
581  HandleScope scope;
582  Handle<FixedArray> elms = Factory::NewFixedArray(5);
583  Handle<JSArray> desc = Factory::NewJSArrayWithElements(elms);
584  LookupResult result;
585  CONVERT_CHECKED(JSObject, obj, args[0]);
586  CONVERT_CHECKED(String, name, args[1]);
587
588  // Use recursive implementation to also traverse hidden prototypes
589  GetOwnPropertyImplementation(obj, name, &result);
590
591  if (!result.IsProperty())
592    return Heap::undefined_value();
593
594  if (result.type() == CALLBACKS) {
595    Object* structure = result.GetCallbackObject();
596    if (structure->IsProxy() || structure->IsAccessorInfo()) {
597      // Property that is internally implemented as a callback or
598      // an API defined callback.
599      Object* value = obj->GetPropertyWithCallback(
600          obj, structure, name, result.holder());
601      elms->set(0, Heap::false_value());
602      elms->set(1, value);
603      elms->set(2, Heap::ToBoolean(!result.IsReadOnly()));
604    } else if (structure->IsFixedArray()) {
605      // __defineGetter__/__defineSetter__ callback.
606      elms->set(0, Heap::true_value());
607      elms->set(1, FixedArray::cast(structure)->get(0));
608      elms->set(2, FixedArray::cast(structure)->get(1));
609    } else {
610      return Heap::undefined_value();
611    }
612  } else {
613    elms->set(0, Heap::false_value());
614    elms->set(1, result.GetLazyValue());
615    elms->set(2, Heap::ToBoolean(!result.IsReadOnly()));
616  }
617
618  elms->set(3, Heap::ToBoolean(!result.IsDontEnum()));
619  elms->set(4, Heap::ToBoolean(!result.IsDontDelete()));
620  return *desc;
621}
622
623
624static Object* Runtime_IsExtensible(Arguments args) {
625  ASSERT(args.length() == 1);
626  CONVERT_CHECKED(JSObject, obj, args[0]);
627  return obj->map()->is_extensible() ?  Heap::true_value()
628                                     : Heap::false_value();
629}
630
631
632static Object* Runtime_RegExpCompile(Arguments args) {
633  HandleScope scope;
634  ASSERT(args.length() == 3);
635  CONVERT_ARG_CHECKED(JSRegExp, re, 0);
636  CONVERT_ARG_CHECKED(String, pattern, 1);
637  CONVERT_ARG_CHECKED(String, flags, 2);
638  Handle<Object> result = RegExpImpl::Compile(re, pattern, flags);
639  if (result.is_null()) return Failure::Exception();
640  return *result;
641}
642
643
644static Object* Runtime_CreateApiFunction(Arguments args) {
645  HandleScope scope;
646  ASSERT(args.length() == 1);
647  CONVERT_ARG_CHECKED(FunctionTemplateInfo, data, 0);
648  return *Factory::CreateApiFunction(data);
649}
650
651
652static Object* Runtime_IsTemplate(Arguments args) {
653  ASSERT(args.length() == 1);
654  Object* arg = args[0];
655  bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
656  return Heap::ToBoolean(result);
657}
658
659
660static Object* Runtime_GetTemplateField(Arguments args) {
661  ASSERT(args.length() == 2);
662  CONVERT_CHECKED(HeapObject, templ, args[0]);
663  CONVERT_CHECKED(Smi, field, args[1]);
664  int index = field->value();
665  int offset = index * kPointerSize + HeapObject::kHeaderSize;
666  InstanceType type = templ->map()->instance_type();
667  RUNTIME_ASSERT(type ==  FUNCTION_TEMPLATE_INFO_TYPE ||
668                 type ==  OBJECT_TEMPLATE_INFO_TYPE);
669  RUNTIME_ASSERT(offset > 0);
670  if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
671    RUNTIME_ASSERT(offset < FunctionTemplateInfo::kSize);
672  } else {
673    RUNTIME_ASSERT(offset < ObjectTemplateInfo::kSize);
674  }
675  return *HeapObject::RawField(templ, offset);
676}
677
678
679static Object* Runtime_DisableAccessChecks(Arguments args) {
680  ASSERT(args.length() == 1);
681  CONVERT_CHECKED(HeapObject, object, args[0]);
682  Map* old_map = object->map();
683  bool needs_access_checks = old_map->is_access_check_needed();
684  if (needs_access_checks) {
685    // Copy map so it won't interfere constructor's initial map.
686    Object* new_map = old_map->CopyDropTransitions();
687    if (new_map->IsFailure()) return new_map;
688
689    Map::cast(new_map)->set_is_access_check_needed(false);
690    object->set_map(Map::cast(new_map));
691  }
692  return needs_access_checks ? Heap::true_value() : Heap::false_value();
693}
694
695
696static Object* Runtime_EnableAccessChecks(Arguments args) {
697  ASSERT(args.length() == 1);
698  CONVERT_CHECKED(HeapObject, object, args[0]);
699  Map* old_map = object->map();
700  if (!old_map->is_access_check_needed()) {
701    // Copy map so it won't interfere constructor's initial map.
702    Object* new_map = old_map->CopyDropTransitions();
703    if (new_map->IsFailure()) return new_map;
704
705    Map::cast(new_map)->set_is_access_check_needed(true);
706    object->set_map(Map::cast(new_map));
707  }
708  return Heap::undefined_value();
709}
710
711
712static Object* ThrowRedeclarationError(const char* type, Handle<String> name) {
713  HandleScope scope;
714  Handle<Object> type_handle = Factory::NewStringFromAscii(CStrVector(type));
715  Handle<Object> args[2] = { type_handle, name };
716  Handle<Object> error =
717      Factory::NewTypeError("redeclaration", HandleVector(args, 2));
718  return Top::Throw(*error);
719}
720
721
722static Object* Runtime_DeclareGlobals(Arguments args) {
723  HandleScope scope;
724  Handle<GlobalObject> global = Handle<GlobalObject>(Top::context()->global());
725
726  Handle<Context> context = args.at<Context>(0);
727  CONVERT_ARG_CHECKED(FixedArray, pairs, 1);
728  bool is_eval = Smi::cast(args[2])->value() == 1;
729
730  // Compute the property attributes. According to ECMA-262, section
731  // 13, page 71, the property must be read-only and
732  // non-deletable. However, neither SpiderMonkey nor KJS creates the
733  // property as read-only, so we don't either.
734  PropertyAttributes base = is_eval ? NONE : DONT_DELETE;
735
736  // Traverse the name/value pairs and set the properties.
737  int length = pairs->length();
738  for (int i = 0; i < length; i += 2) {
739    HandleScope scope;
740    Handle<String> name(String::cast(pairs->get(i)));
741    Handle<Object> value(pairs->get(i + 1));
742
743    // We have to declare a global const property. To capture we only
744    // assign to it when evaluating the assignment for "const x =
745    // <expr>" the initial value is the hole.
746    bool is_const_property = value->IsTheHole();
747
748    if (value->IsUndefined() || is_const_property) {
749      // Lookup the property in the global object, and don't set the
750      // value of the variable if the property is already there.
751      LookupResult lookup;
752      global->Lookup(*name, &lookup);
753      if (lookup.IsProperty()) {
754        // Determine if the property is local by comparing the holder
755        // against the global object. The information will be used to
756        // avoid throwing re-declaration errors when declaring
757        // variables or constants that exist in the prototype chain.
758        bool is_local = (*global == lookup.holder());
759        // Get the property attributes and determine if the property is
760        // read-only.
761        PropertyAttributes attributes = global->GetPropertyAttribute(*name);
762        bool is_read_only = (attributes & READ_ONLY) != 0;
763        if (lookup.type() == INTERCEPTOR) {
764          // If the interceptor says the property is there, we
765          // just return undefined without overwriting the property.
766          // Otherwise, we continue to setting the property.
767          if (attributes != ABSENT) {
768            // Check if the existing property conflicts with regards to const.
769            if (is_local && (is_read_only || is_const_property)) {
770              const char* type = (is_read_only) ? "const" : "var";
771              return ThrowRedeclarationError(type, name);
772            };
773            // The property already exists without conflicting: Go to
774            // the next declaration.
775            continue;
776          }
777          // Fall-through and introduce the absent property by using
778          // SetProperty.
779        } else {
780          if (is_local && (is_read_only || is_const_property)) {
781            const char* type = (is_read_only) ? "const" : "var";
782            return ThrowRedeclarationError(type, name);
783          }
784          // The property already exists without conflicting: Go to
785          // the next declaration.
786          continue;
787        }
788      }
789    } else {
790      // Copy the function and update its context. Use it as value.
791      Handle<SharedFunctionInfo> shared =
792          Handle<SharedFunctionInfo>::cast(value);
793      Handle<JSFunction> function =
794          Factory::NewFunctionFromSharedFunctionInfo(shared, context, TENURED);
795      value = function;
796    }
797
798    LookupResult lookup;
799    global->LocalLookup(*name, &lookup);
800
801    PropertyAttributes attributes = is_const_property
802        ? static_cast<PropertyAttributes>(base | READ_ONLY)
803        : base;
804
805    if (lookup.IsProperty()) {
806      // There's a local property that we need to overwrite because
807      // we're either declaring a function or there's an interceptor
808      // that claims the property is absent.
809
810      // Check for conflicting re-declarations. We cannot have
811      // conflicting types in case of intercepted properties because
812      // they are absent.
813      if (lookup.type() != INTERCEPTOR &&
814          (lookup.IsReadOnly() || is_const_property)) {
815        const char* type = (lookup.IsReadOnly()) ? "const" : "var";
816        return ThrowRedeclarationError(type, name);
817      }
818      SetProperty(global, name, value, attributes);
819    } else {
820      // If a property with this name does not already exist on the
821      // global object add the property locally.  We take special
822      // precautions to always add it as a local property even in case
823      // of callbacks in the prototype chain (this rules out using
824      // SetProperty).  Also, we must use the handle-based version to
825      // avoid GC issues.
826      IgnoreAttributesAndSetLocalProperty(global, name, value, attributes);
827    }
828  }
829
830  return Heap::undefined_value();
831}
832
833
834static Object* Runtime_DeclareContextSlot(Arguments args) {
835  HandleScope scope;
836  ASSERT(args.length() == 4);
837
838  CONVERT_ARG_CHECKED(Context, context, 0);
839  Handle<String> name(String::cast(args[1]));
840  PropertyAttributes mode =
841      static_cast<PropertyAttributes>(Smi::cast(args[2])->value());
842  ASSERT(mode == READ_ONLY || mode == NONE);
843  Handle<Object> initial_value(args[3]);
844
845  // Declarations are always done in the function context.
846  context = Handle<Context>(context->fcontext());
847
848  int index;
849  PropertyAttributes attributes;
850  ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
851  Handle<Object> holder =
852      context->Lookup(name, flags, &index, &attributes);
853
854  if (attributes != ABSENT) {
855    // The name was declared before; check for conflicting
856    // re-declarations: This is similar to the code in parser.cc in
857    // the AstBuildingParser::Declare function.
858    if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
859      // Functions are not read-only.
860      ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
861      const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
862      return ThrowRedeclarationError(type, name);
863    }
864
865    // Initialize it if necessary.
866    if (*initial_value != NULL) {
867      if (index >= 0) {
868        // The variable or constant context slot should always be in
869        // the function context or the arguments object.
870        if (holder->IsContext()) {
871          ASSERT(holder.is_identical_to(context));
872          if (((attributes & READ_ONLY) == 0) ||
873              context->get(index)->IsTheHole()) {
874            context->set(index, *initial_value);
875          }
876        } else {
877          Handle<JSObject>::cast(holder)->SetElement(index, *initial_value);
878        }
879      } else {
880        // Slow case: The property is not in the FixedArray part of the context.
881        Handle<JSObject> context_ext = Handle<JSObject>::cast(holder);
882        SetProperty(context_ext, name, initial_value, mode);
883      }
884    }
885
886  } else {
887    // The property is not in the function context. It needs to be
888    // "declared" in the function context's extension context, or in the
889    // global context.
890    Handle<JSObject> context_ext;
891    if (context->has_extension()) {
892      // The function context's extension context exists - use it.
893      context_ext = Handle<JSObject>(context->extension());
894    } else {
895      // The function context's extension context does not exists - allocate
896      // it.
897      context_ext = Factory::NewJSObject(Top::context_extension_function());
898      // And store it in the extension slot.
899      context->set_extension(*context_ext);
900    }
901    ASSERT(*context_ext != NULL);
902
903    // Declare the property by setting it to the initial value if provided,
904    // or undefined, and use the correct mode (e.g. READ_ONLY attribute for
905    // constant declarations).
906    ASSERT(!context_ext->HasLocalProperty(*name));
907    Handle<Object> value(Heap::undefined_value());
908    if (*initial_value != NULL) value = initial_value;
909    SetProperty(context_ext, name, value, mode);
910    ASSERT(context_ext->GetLocalPropertyAttribute(*name) == mode);
911  }
912
913  return Heap::undefined_value();
914}
915
916
917static Object* Runtime_InitializeVarGlobal(Arguments args) {
918  NoHandleAllocation nha;
919
920  // Determine if we need to assign to the variable if it already
921  // exists (based on the number of arguments).
922  RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
923  bool assign = args.length() == 2;
924
925  CONVERT_ARG_CHECKED(String, name, 0);
926  GlobalObject* global = Top::context()->global();
927
928  // According to ECMA-262, section 12.2, page 62, the property must
929  // not be deletable.
930  PropertyAttributes attributes = DONT_DELETE;
931
932  // Lookup the property locally in the global object. If it isn't
933  // there, there is a property with this name in the prototype chain.
934  // We follow Safari and Firefox behavior and only set the property
935  // locally if there is an explicit initialization value that we have
936  // to assign to the property. When adding the property we take
937  // special precautions to always add it as a local property even in
938  // case of callbacks in the prototype chain (this rules out using
939  // SetProperty).  We have IgnoreAttributesAndSetLocalProperty for
940  // this.
941  // Note that objects can have hidden prototypes, so we need to traverse
942  // the whole chain of hidden prototypes to do a 'local' lookup.
943  JSObject* real_holder = global;
944  LookupResult lookup;
945  while (true) {
946    real_holder->LocalLookup(*name, &lookup);
947    if (lookup.IsProperty()) {
948      // Determine if this is a redeclaration of something read-only.
949      if (lookup.IsReadOnly()) {
950        // If we found readonly property on one of hidden prototypes,
951        // just shadow it.
952        if (real_holder != Top::context()->global()) break;
953        return ThrowRedeclarationError("const", name);
954      }
955
956      // Determine if this is a redeclaration of an intercepted read-only
957      // property and figure out if the property exists at all.
958      bool found = true;
959      PropertyType type = lookup.type();
960      if (type == INTERCEPTOR) {
961        HandleScope handle_scope;
962        Handle<JSObject> holder(real_holder);
963        PropertyAttributes intercepted = holder->GetPropertyAttribute(*name);
964        real_holder = *holder;
965        if (intercepted == ABSENT) {
966          // The interceptor claims the property isn't there. We need to
967          // make sure to introduce it.
968          found = false;
969        } else if ((intercepted & READ_ONLY) != 0) {
970          // The property is present, but read-only. Since we're trying to
971          // overwrite it with a variable declaration we must throw a
972          // re-declaration error.  However if we found readonly property
973          // on one of hidden prototypes, just shadow it.
974          if (real_holder != Top::context()->global()) break;
975          return ThrowRedeclarationError("const", name);
976        }
977      }
978
979      if (found && !assign) {
980        // The global property is there and we're not assigning any value
981        // to it. Just return.
982        return Heap::undefined_value();
983      }
984
985      // Assign the value (or undefined) to the property.
986      Object* value = (assign) ? args[1] : Heap::undefined_value();
987      return real_holder->SetProperty(&lookup, *name, value, attributes);
988    }
989
990    Object* proto = real_holder->GetPrototype();
991    if (!proto->IsJSObject())
992      break;
993
994    if (!JSObject::cast(proto)->map()->is_hidden_prototype())
995      break;
996
997    real_holder = JSObject::cast(proto);
998  }
999
1000  global = Top::context()->global();
1001  if (assign) {
1002    return global->IgnoreAttributesAndSetLocalProperty(*name,
1003                                                       args[1],
1004                                                       attributes);
1005  }
1006  return Heap::undefined_value();
1007}
1008
1009
1010static Object* Runtime_InitializeConstGlobal(Arguments args) {
1011  // All constants are declared with an initial value. The name
1012  // of the constant is the first argument and the initial value
1013  // is the second.
1014  RUNTIME_ASSERT(args.length() == 2);
1015  CONVERT_ARG_CHECKED(String, name, 0);
1016  Handle<Object> value = args.at<Object>(1);
1017
1018  // Get the current global object from top.
1019  GlobalObject* global = Top::context()->global();
1020
1021  // According to ECMA-262, section 12.2, page 62, the property must
1022  // not be deletable. Since it's a const, it must be READ_ONLY too.
1023  PropertyAttributes attributes =
1024      static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
1025
1026  // Lookup the property locally in the global object. If it isn't
1027  // there, we add the property and take special precautions to always
1028  // add it as a local property even in case of callbacks in the
1029  // prototype chain (this rules out using SetProperty).
1030  // We use IgnoreAttributesAndSetLocalProperty instead
1031  LookupResult lookup;
1032  global->LocalLookup(*name, &lookup);
1033  if (!lookup.IsProperty()) {
1034    return global->IgnoreAttributesAndSetLocalProperty(*name,
1035                                                       *value,
1036                                                       attributes);
1037  }
1038
1039  // Determine if this is a redeclaration of something not
1040  // read-only. In case the result is hidden behind an interceptor we
1041  // need to ask it for the property attributes.
1042  if (!lookup.IsReadOnly()) {
1043    if (lookup.type() != INTERCEPTOR) {
1044      return ThrowRedeclarationError("var", name);
1045    }
1046
1047    PropertyAttributes intercepted = global->GetPropertyAttribute(*name);
1048
1049    // Throw re-declaration error if the intercepted property is present
1050    // but not read-only.
1051    if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
1052      return ThrowRedeclarationError("var", name);
1053    }
1054
1055    // Restore global object from context (in case of GC) and continue
1056    // with setting the value because the property is either absent or
1057    // read-only. We also have to do redo the lookup.
1058    global = Top::context()->global();
1059
1060    // BUG 1213579: Handle the case where we have to set a read-only
1061    // property through an interceptor and only do it if it's
1062    // uninitialized, e.g. the hole. Nirk...
1063    global->SetProperty(*name, *value, attributes);
1064    return *value;
1065  }
1066
1067  // Set the value, but only we're assigning the initial value to a
1068  // constant. For now, we determine this by checking if the
1069  // current value is the hole.
1070  PropertyType type = lookup.type();
1071  if (type == FIELD) {
1072    FixedArray* properties = global->properties();
1073    int index = lookup.GetFieldIndex();
1074    if (properties->get(index)->IsTheHole()) {
1075      properties->set(index, *value);
1076    }
1077  } else if (type == NORMAL) {
1078    if (global->GetNormalizedProperty(&lookup)->IsTheHole()) {
1079      global->SetNormalizedProperty(&lookup, *value);
1080    }
1081  } else {
1082    // Ignore re-initialization of constants that have already been
1083    // assigned a function value.
1084    ASSERT(lookup.IsReadOnly() && type == CONSTANT_FUNCTION);
1085  }
1086
1087  // Use the set value as the result of the operation.
1088  return *value;
1089}
1090
1091
1092static Object* Runtime_InitializeConstContextSlot(Arguments args) {
1093  HandleScope scope;
1094  ASSERT(args.length() == 3);
1095
1096  Handle<Object> value(args[0]);
1097  ASSERT(!value->IsTheHole());
1098  CONVERT_ARG_CHECKED(Context, context, 1);
1099  Handle<String> name(String::cast(args[2]));
1100
1101  // Initializations are always done in the function context.
1102  context = Handle<Context>(context->fcontext());
1103
1104  int index;
1105  PropertyAttributes attributes;
1106  ContextLookupFlags flags = FOLLOW_CHAINS;
1107  Handle<Object> holder =
1108      context->Lookup(name, flags, &index, &attributes);
1109
1110  // In most situations, the property introduced by the const
1111  // declaration should be present in the context extension object.
1112  // However, because declaration and initialization are separate, the
1113  // property might have been deleted (if it was introduced by eval)
1114  // before we reach the initialization point.
1115  //
1116  // Example:
1117  //
1118  //    function f() { eval("delete x; const x;"); }
1119  //
1120  // In that case, the initialization behaves like a normal assignment
1121  // to property 'x'.
1122  if (index >= 0) {
1123    // Property was found in a context.
1124    if (holder->IsContext()) {
1125      // The holder cannot be the function context.  If it is, there
1126      // should have been a const redeclaration error when declaring
1127      // the const property.
1128      ASSERT(!holder.is_identical_to(context));
1129      if ((attributes & READ_ONLY) == 0) {
1130        Handle<Context>::cast(holder)->set(index, *value);
1131      }
1132    } else {
1133      // The holder is an arguments object.
1134      ASSERT((attributes & READ_ONLY) == 0);
1135      Handle<JSObject>::cast(holder)->SetElement(index, *value);
1136    }
1137    return *value;
1138  }
1139
1140  // The property could not be found, we introduce it in the global
1141  // context.
1142  if (attributes == ABSENT) {
1143    Handle<JSObject> global = Handle<JSObject>(Top::context()->global());
1144    SetProperty(global, name, value, NONE);
1145    return *value;
1146  }
1147
1148  // The property was present in a context extension object.
1149  Handle<JSObject> context_ext = Handle<JSObject>::cast(holder);
1150
1151  if (*context_ext == context->extension()) {
1152    // This is the property that was introduced by the const
1153    // declaration.  Set it if it hasn't been set before.  NOTE: We
1154    // cannot use GetProperty() to get the current value as it
1155    // 'unholes' the value.
1156    LookupResult lookup;
1157    context_ext->LocalLookupRealNamedProperty(*name, &lookup);
1158    ASSERT(lookup.IsProperty());  // the property was declared
1159    ASSERT(lookup.IsReadOnly());  // and it was declared as read-only
1160
1161    PropertyType type = lookup.type();
1162    if (type == FIELD) {
1163      FixedArray* properties = context_ext->properties();
1164      int index = lookup.GetFieldIndex();
1165      if (properties->get(index)->IsTheHole()) {
1166        properties->set(index, *value);
1167      }
1168    } else if (type == NORMAL) {
1169      if (context_ext->GetNormalizedProperty(&lookup)->IsTheHole()) {
1170        context_ext->SetNormalizedProperty(&lookup, *value);
1171      }
1172    } else {
1173      // We should not reach here. Any real, named property should be
1174      // either a field or a dictionary slot.
1175      UNREACHABLE();
1176    }
1177  } else {
1178    // The property was found in a different context extension object.
1179    // Set it if it is not a read-only property.
1180    if ((attributes & READ_ONLY) == 0) {
1181      Handle<Object> set = SetProperty(context_ext, name, value, attributes);
1182      // Setting a property might throw an exception.  Exceptions
1183      // are converted to empty handles in handle operations.  We
1184      // need to convert back to exceptions here.
1185      if (set.is_null()) {
1186        ASSERT(Top::has_pending_exception());
1187        return Failure::Exception();
1188      }
1189    }
1190  }
1191
1192  return *value;
1193}
1194
1195
1196static Object* Runtime_OptimizeObjectForAddingMultipleProperties(
1197    Arguments args) {
1198  HandleScope scope;
1199  ASSERT(args.length() == 2);
1200  CONVERT_ARG_CHECKED(JSObject, object, 0);
1201  CONVERT_SMI_CHECKED(properties, args[1]);
1202  if (object->HasFastProperties()) {
1203    NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties);
1204  }
1205  return *object;
1206}
1207
1208
1209static Object* Runtime_RegExpExec(Arguments args) {
1210  HandleScope scope;
1211  ASSERT(args.length() == 4);
1212  CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
1213  CONVERT_ARG_CHECKED(String, subject, 1);
1214  // Due to the way the JS calls are constructed this must be less than the
1215  // length of a string, i.e. it is always a Smi.  We check anyway for security.
1216  CONVERT_SMI_CHECKED(index, args[2]);
1217  CONVERT_ARG_CHECKED(JSArray, last_match_info, 3);
1218  RUNTIME_ASSERT(last_match_info->HasFastElements());
1219  RUNTIME_ASSERT(index >= 0);
1220  RUNTIME_ASSERT(index <= subject->length());
1221  Counters::regexp_entry_runtime.Increment();
1222  Handle<Object> result = RegExpImpl::Exec(regexp,
1223                                           subject,
1224                                           index,
1225                                           last_match_info);
1226  if (result.is_null()) return Failure::Exception();
1227  return *result;
1228}
1229
1230
1231static Object* Runtime_RegExpConstructResult(Arguments args) {
1232  ASSERT(args.length() == 3);
1233  CONVERT_SMI_CHECKED(elements_count, args[0]);
1234  if (elements_count > JSArray::kMaxFastElementsLength) {
1235    return Top::ThrowIllegalOperation();
1236  }
1237  Object* new_object = Heap::AllocateFixedArrayWithHoles(elements_count);
1238  if (new_object->IsFailure()) return new_object;
1239  FixedArray* elements = FixedArray::cast(new_object);
1240  new_object = Heap::AllocateRaw(JSRegExpResult::kSize,
1241                                 NEW_SPACE,
1242                                 OLD_POINTER_SPACE);
1243  if (new_object->IsFailure()) return new_object;
1244  {
1245    AssertNoAllocation no_gc;
1246    HandleScope scope;
1247    reinterpret_cast<HeapObject*>(new_object)->
1248        set_map(Top::global_context()->regexp_result_map());
1249  }
1250  JSArray* array = JSArray::cast(new_object);
1251  array->set_properties(Heap::empty_fixed_array());
1252  array->set_elements(elements);
1253  array->set_length(Smi::FromInt(elements_count));
1254  // Write in-object properties after the length of the array.
1255  array->InObjectPropertyAtPut(JSRegExpResult::kIndexIndex, args[1]);
1256  array->InObjectPropertyAtPut(JSRegExpResult::kInputIndex, args[2]);
1257  return array;
1258}
1259
1260
1261static Object* Runtime_RegExpInitializeObject(Arguments args) {
1262  AssertNoAllocation no_alloc;
1263  ASSERT(args.length() == 5);
1264  CONVERT_CHECKED(JSRegExp, regexp, args[0]);
1265  CONVERT_CHECKED(String, source, args[1]);
1266
1267  Object* global = args[2];
1268  if (!global->IsTrue()) global = Heap::false_value();
1269
1270  Object* ignoreCase = args[3];
1271  if (!ignoreCase->IsTrue()) ignoreCase = Heap::false_value();
1272
1273  Object* multiline = args[4];
1274  if (!multiline->IsTrue()) multiline = Heap::false_value();
1275
1276  Map* map = regexp->map();
1277  Object* constructor = map->constructor();
1278  if (constructor->IsJSFunction() &&
1279      JSFunction::cast(constructor)->initial_map() == map) {
1280    // If we still have the original map, set in-object properties directly.
1281    regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, source);
1282    // TODO(lrn): Consider skipping write barrier on booleans as well.
1283    // Both true and false should be in oldspace at all times.
1284    regexp->InObjectPropertyAtPut(JSRegExp::kGlobalFieldIndex, global);
1285    regexp->InObjectPropertyAtPut(JSRegExp::kIgnoreCaseFieldIndex, ignoreCase);
1286    regexp->InObjectPropertyAtPut(JSRegExp::kMultilineFieldIndex, multiline);
1287    regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex,
1288                                  Smi::FromInt(0),
1289                                  SKIP_WRITE_BARRIER);
1290    return regexp;
1291  }
1292
1293  // Map has changed, so use generic, but slower, method.
1294  PropertyAttributes final =
1295      static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE);
1296  PropertyAttributes writable =
1297      static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
1298  regexp->IgnoreAttributesAndSetLocalProperty(Heap::source_symbol(),
1299                                              source,
1300                                              final);
1301  regexp->IgnoreAttributesAndSetLocalProperty(Heap::global_symbol(),
1302                                              global,
1303                                              final);
1304  regexp->IgnoreAttributesAndSetLocalProperty(Heap::ignore_case_symbol(),
1305                                              ignoreCase,
1306                                              final);
1307  regexp->IgnoreAttributesAndSetLocalProperty(Heap::multiline_symbol(),
1308                                              multiline,
1309                                              final);
1310  regexp->IgnoreAttributesAndSetLocalProperty(Heap::last_index_symbol(),
1311                                              Smi::FromInt(0),
1312                                              writable);
1313  return regexp;
1314}
1315
1316
1317static Object* Runtime_FinishArrayPrototypeSetup(Arguments args) {
1318  HandleScope scope;
1319  ASSERT(args.length() == 1);
1320  CONVERT_ARG_CHECKED(JSArray, prototype, 0);
1321  // This is necessary to enable fast checks for absence of elements
1322  // on Array.prototype and below.
1323  prototype->set_elements(Heap::empty_fixed_array());
1324  return Smi::FromInt(0);
1325}
1326
1327
1328static Handle<JSFunction> InstallBuiltin(Handle<JSObject> holder,
1329                                         const char* name,
1330                                         Builtins::Name builtin_name) {
1331  Handle<String> key = Factory::LookupAsciiSymbol(name);
1332  Handle<Code> code(Builtins::builtin(builtin_name));
1333  Handle<JSFunction> optimized = Factory::NewFunction(key,
1334                                                      JS_OBJECT_TYPE,
1335                                                      JSObject::kHeaderSize,
1336                                                      code,
1337                                                      false);
1338  optimized->shared()->DontAdaptArguments();
1339  SetProperty(holder, key, optimized, NONE);
1340  return optimized;
1341}
1342
1343
1344static Object* Runtime_SpecialArrayFunctions(Arguments args) {
1345  HandleScope scope;
1346  ASSERT(args.length() == 1);
1347  CONVERT_ARG_CHECKED(JSObject, holder, 0);
1348
1349  InstallBuiltin(holder, "pop", Builtins::ArrayPop);
1350  InstallBuiltin(holder, "push", Builtins::ArrayPush);
1351  InstallBuiltin(holder, "shift", Builtins::ArrayShift);
1352  InstallBuiltin(holder, "unshift", Builtins::ArrayUnshift);
1353  InstallBuiltin(holder, "slice", Builtins::ArraySlice);
1354  InstallBuiltin(holder, "splice", Builtins::ArraySplice);
1355  InstallBuiltin(holder, "concat", Builtins::ArrayConcat);
1356
1357  return *holder;
1358}
1359
1360
1361static Object* Runtime_GetGlobalReceiver(Arguments args) {
1362  // Returns a real global receiver, not one of builtins object.
1363  Context* global_context = Top::context()->global()->global_context();
1364  return global_context->global()->global_receiver();
1365}
1366
1367
1368static Object* Runtime_MaterializeRegExpLiteral(Arguments args) {
1369  HandleScope scope;
1370  ASSERT(args.length() == 4);
1371  CONVERT_ARG_CHECKED(FixedArray, literals, 0);
1372  int index = Smi::cast(args[1])->value();
1373  Handle<String> pattern = args.at<String>(2);
1374  Handle<String> flags = args.at<String>(3);
1375
1376  // Get the RegExp function from the context in the literals array.
1377  // This is the RegExp function from the context in which the
1378  // function was created.  We do not use the RegExp function from the
1379  // current global context because this might be the RegExp function
1380  // from another context which we should not have access to.
1381  Handle<JSFunction> constructor =
1382      Handle<JSFunction>(
1383          JSFunction::GlobalContextFromLiterals(*literals)->regexp_function());
1384  // Compute the regular expression literal.
1385  bool has_pending_exception;
1386  Handle<Object> regexp =
1387      RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
1388                                      &has_pending_exception);
1389  if (has_pending_exception) {
1390    ASSERT(Top::has_pending_exception());
1391    return Failure::Exception();
1392  }
1393  literals->set(index, *regexp);
1394  return *regexp;
1395}
1396
1397
1398static Object* Runtime_FunctionGetName(Arguments args) {
1399  NoHandleAllocation ha;
1400  ASSERT(args.length() == 1);
1401
1402  CONVERT_CHECKED(JSFunction, f, args[0]);
1403  return f->shared()->name();
1404}
1405
1406
1407static Object* Runtime_FunctionSetName(Arguments args) {
1408  NoHandleAllocation ha;
1409  ASSERT(args.length() == 2);
1410
1411  CONVERT_CHECKED(JSFunction, f, args[0]);
1412  CONVERT_CHECKED(String, name, args[1]);
1413  f->shared()->set_name(name);
1414  return Heap::undefined_value();
1415}
1416
1417
1418static Object* Runtime_FunctionRemovePrototype(Arguments args) {
1419  NoHandleAllocation ha;
1420  ASSERT(args.length() == 1);
1421
1422  CONVERT_CHECKED(JSFunction, f, args[0]);
1423  Object* obj = f->RemovePrototype();
1424  if (obj->IsFailure()) return obj;
1425
1426  return Heap::undefined_value();
1427}
1428
1429
1430static Object* Runtime_FunctionGetScript(Arguments args) {
1431  HandleScope scope;
1432  ASSERT(args.length() == 1);
1433
1434  CONVERT_CHECKED(JSFunction, fun, args[0]);
1435  Handle<Object> script = Handle<Object>(fun->shared()->script());
1436  if (!script->IsScript()) return Heap::undefined_value();
1437
1438  return *GetScriptWrapper(Handle<Script>::cast(script));
1439}
1440
1441
1442static Object* Runtime_FunctionGetSourceCode(Arguments args) {
1443  NoHandleAllocation ha;
1444  ASSERT(args.length() == 1);
1445
1446  CONVERT_CHECKED(JSFunction, f, args[0]);
1447  return f->shared()->GetSourceCode();
1448}
1449
1450
1451static Object* Runtime_FunctionGetScriptSourcePosition(Arguments args) {
1452  NoHandleAllocation ha;
1453  ASSERT(args.length() == 1);
1454
1455  CONVERT_CHECKED(JSFunction, fun, args[0]);
1456  int pos = fun->shared()->start_position();
1457  return Smi::FromInt(pos);
1458}
1459
1460
1461static Object* Runtime_FunctionGetPositionForOffset(Arguments args) {
1462  ASSERT(args.length() == 2);
1463
1464  CONVERT_CHECKED(JSFunction, fun, args[0]);
1465  CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]);
1466
1467  Code* code = fun->code();
1468  RUNTIME_ASSERT(0 <= offset && offset < code->Size());
1469
1470  Address pc = code->address() + offset;
1471  return Smi::FromInt(fun->code()->SourcePosition(pc));
1472}
1473
1474
1475
1476static Object* Runtime_FunctionSetInstanceClassName(Arguments args) {
1477  NoHandleAllocation ha;
1478  ASSERT(args.length() == 2);
1479
1480  CONVERT_CHECKED(JSFunction, fun, args[0]);
1481  CONVERT_CHECKED(String, name, args[1]);
1482  fun->SetInstanceClassName(name);
1483  return Heap::undefined_value();
1484}
1485
1486
1487static Object* Runtime_FunctionSetLength(Arguments args) {
1488  NoHandleAllocation ha;
1489  ASSERT(args.length() == 2);
1490
1491  CONVERT_CHECKED(JSFunction, fun, args[0]);
1492  CONVERT_CHECKED(Smi, length, args[1]);
1493  fun->shared()->set_length(length->value());
1494  return length;
1495}
1496
1497
1498static Object* Runtime_FunctionSetPrototype(Arguments args) {
1499  NoHandleAllocation ha;
1500  ASSERT(args.length() == 2);
1501
1502  CONVERT_CHECKED(JSFunction, fun, args[0]);
1503  ASSERT(fun->should_have_prototype());
1504  Object* obj = Accessors::FunctionSetPrototype(fun, args[1], NULL);
1505  if (obj->IsFailure()) return obj;
1506  return args[0];  // return TOS
1507}
1508
1509
1510static Object* Runtime_FunctionIsAPIFunction(Arguments args) {
1511  NoHandleAllocation ha;
1512  ASSERT(args.length() == 1);
1513
1514  CONVERT_CHECKED(JSFunction, f, args[0]);
1515  return f->shared()->IsApiFunction() ? Heap::true_value()
1516                                      : Heap::false_value();
1517}
1518
1519static Object* Runtime_FunctionIsBuiltin(Arguments args) {
1520  NoHandleAllocation ha;
1521  ASSERT(args.length() == 1);
1522
1523  CONVERT_CHECKED(JSFunction, f, args[0]);
1524  return f->IsBuiltin() ? Heap::true_value() : Heap::false_value();
1525}
1526
1527
1528static Object* Runtime_SetCode(Arguments args) {
1529  HandleScope scope;
1530  ASSERT(args.length() == 2);
1531
1532  CONVERT_ARG_CHECKED(JSFunction, target, 0);
1533  Handle<Object> code = args.at<Object>(1);
1534
1535  Handle<Context> context(target->context());
1536
1537  if (!code->IsNull()) {
1538    RUNTIME_ASSERT(code->IsJSFunction());
1539    Handle<JSFunction> fun = Handle<JSFunction>::cast(code);
1540    Handle<SharedFunctionInfo> shared(fun->shared());
1541    SetExpectedNofProperties(target, shared->expected_nof_properties());
1542
1543    if (!EnsureCompiled(shared, KEEP_EXCEPTION)) {
1544      return Failure::Exception();
1545    }
1546    // Set the code, formal parameter count, and the length of the target
1547    // function.
1548    target->set_code(fun->code());
1549    target->shared()->set_length(shared->length());
1550    target->shared()->set_formal_parameter_count(
1551        shared->formal_parameter_count());
1552    // Set the source code of the target function to undefined.
1553    // SetCode is only used for built-in constructors like String,
1554    // Array, and Object, and some web code
1555    // doesn't like seeing source code for constructors.
1556    target->shared()->set_script(Heap::undefined_value());
1557    // Clear the optimization hints related to the compiled code as these are no
1558    // longer valid when the code is overwritten.
1559    target->shared()->ClearThisPropertyAssignmentsInfo();
1560    context = Handle<Context>(fun->context());
1561
1562    // Make sure we get a fresh copy of the literal vector to avoid
1563    // cross context contamination.
1564    int number_of_literals = fun->NumberOfLiterals();
1565    Handle<FixedArray> literals =
1566        Factory::NewFixedArray(number_of_literals, TENURED);
1567    if (number_of_literals > 0) {
1568      // Insert the object, regexp and array functions in the literals
1569      // array prefix.  These are the functions that will be used when
1570      // creating object, regexp and array literals.
1571      literals->set(JSFunction::kLiteralGlobalContextIndex,
1572                    context->global_context());
1573    }
1574    // It's okay to skip the write barrier here because the literals
1575    // are guaranteed to be in old space.
1576    target->set_literals(*literals, SKIP_WRITE_BARRIER);
1577  }
1578
1579  target->set_context(*context);
1580  return *target;
1581}
1582
1583
1584static Object* CharCodeAt(String* subject, Object* index) {
1585  uint32_t i = 0;
1586  if (!Array::IndexFromObject(index, &i)) return Heap::nan_value();
1587  // Flatten the string.  If someone wants to get a char at an index
1588  // in a cons string, it is likely that more indices will be
1589  // accessed.
1590  Object* flat = subject->TryFlatten();
1591  if (flat->IsFailure()) return flat;
1592  subject = String::cast(flat);
1593  if (i >= static_cast<uint32_t>(subject->length())) {
1594    return Heap::nan_value();
1595  }
1596  return Smi::FromInt(subject->Get(i));
1597}
1598
1599
1600static Object* CharFromCode(Object* char_code) {
1601  uint32_t code;
1602  if (Array::IndexFromObject(char_code, &code)) {
1603    if (code <= 0xffff) {
1604      return Heap::LookupSingleCharacterStringFromCode(code);
1605    }
1606  }
1607  return Heap::empty_string();
1608}
1609
1610
1611static Object* Runtime_StringCharCodeAt(Arguments args) {
1612  NoHandleAllocation ha;
1613  ASSERT(args.length() == 2);
1614
1615  CONVERT_CHECKED(String, subject, args[0]);
1616  Object* index = args[1];
1617  return CharCodeAt(subject, index);
1618}
1619
1620
1621static Object* Runtime_StringCharAt(Arguments args) {
1622  NoHandleAllocation ha;
1623  ASSERT(args.length() == 2);
1624
1625  CONVERT_CHECKED(String, subject, args[0]);
1626  Object* index = args[1];
1627  Object* code = CharCodeAt(subject, index);
1628  if (code == Heap::nan_value()) {
1629    return Heap::undefined_value();
1630  }
1631  return CharFromCode(code);
1632}
1633
1634
1635static Object* Runtime_CharFromCode(Arguments args) {
1636  NoHandleAllocation ha;
1637  ASSERT(args.length() == 1);
1638  return CharFromCode(args[0]);
1639}
1640
1641
1642class FixedArrayBuilder {
1643 public:
1644  explicit FixedArrayBuilder(int initial_capacity)
1645      : array_(Factory::NewFixedArrayWithHoles(initial_capacity)),
1646        length_(0) {
1647    // Require a non-zero initial size. Ensures that doubling the size to
1648    // extend the array will work.
1649    ASSERT(initial_capacity > 0);
1650  }
1651
1652  explicit FixedArrayBuilder(Handle<FixedArray> backing_store)
1653      : array_(backing_store),
1654        length_(0) {
1655    // Require a non-zero initial size. Ensures that doubling the size to
1656    // extend the array will work.
1657    ASSERT(backing_store->length() > 0);
1658  }
1659
1660  bool HasCapacity(int elements) {
1661    int length = array_->length();
1662    int required_length = length_ + elements;
1663    return (length >= required_length);
1664  }
1665
1666  void EnsureCapacity(int elements) {
1667    int length = array_->length();
1668    int required_length = length_ + elements;
1669    if (length < required_length) {
1670      int new_length = length;
1671      do {
1672        new_length *= 2;
1673      } while (new_length < required_length);
1674      Handle<FixedArray> extended_array =
1675          Factory::NewFixedArrayWithHoles(new_length);
1676      array_->CopyTo(0, *extended_array, 0, length_);
1677      array_ = extended_array;
1678    }
1679  }
1680
1681  void Add(Object* value) {
1682    ASSERT(length_ < capacity());
1683    array_->set(length_, value);
1684    length_++;
1685  }
1686
1687  void Add(Smi* value) {
1688    ASSERT(length_ < capacity());
1689    array_->set(length_, value);
1690    length_++;
1691  }
1692
1693  Handle<FixedArray> array() {
1694    return array_;
1695  }
1696
1697  int length() {
1698    return length_;
1699  }
1700
1701  int capacity() {
1702    return array_->length();
1703  }
1704
1705  Handle<JSArray> ToJSArray() {
1706    Handle<JSArray> result_array = Factory::NewJSArrayWithElements(array_);
1707    result_array->set_length(Smi::FromInt(length_));
1708    return result_array;
1709  }
1710
1711  Handle<JSArray> ToJSArray(Handle<JSArray> target_array) {
1712    target_array->set_elements(*array_);
1713    target_array->set_length(Smi::FromInt(length_));
1714    return target_array;
1715  }
1716
1717 private:
1718  Handle<FixedArray> array_;
1719  int length_;
1720};
1721
1722
1723// Forward declarations.
1724const int kStringBuilderConcatHelperLengthBits = 11;
1725const int kStringBuilderConcatHelperPositionBits = 19;
1726
1727template <typename schar>
1728static inline void StringBuilderConcatHelper(String*,
1729                                             schar*,
1730                                             FixedArray*,
1731                                             int);
1732
1733typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits>
1734    StringBuilderSubstringLength;
1735typedef BitField<int,
1736                 kStringBuilderConcatHelperLengthBits,
1737                 kStringBuilderConcatHelperPositionBits>
1738    StringBuilderSubstringPosition;
1739
1740
1741class ReplacementStringBuilder {
1742 public:
1743  ReplacementStringBuilder(Handle<String> subject, int estimated_part_count)
1744      : array_builder_(estimated_part_count),
1745        subject_(subject),
1746        character_count_(0),
1747        is_ascii_(subject->IsAsciiRepresentation()) {
1748    // Require a non-zero initial size. Ensures that doubling the size to
1749    // extend the array will work.
1750    ASSERT(estimated_part_count > 0);
1751  }
1752
1753  static inline void AddSubjectSlice(FixedArrayBuilder* builder,
1754                                     int from,
1755                                     int to) {
1756    ASSERT(from >= 0);
1757    int length = to - from;
1758    ASSERT(length > 0);
1759    if (StringBuilderSubstringLength::is_valid(length) &&
1760        StringBuilderSubstringPosition::is_valid(from)) {
1761      int encoded_slice = StringBuilderSubstringLength::encode(length) |
1762          StringBuilderSubstringPosition::encode(from);
1763      builder->Add(Smi::FromInt(encoded_slice));
1764    } else {
1765      // Otherwise encode as two smis.
1766      builder->Add(Smi::FromInt(-length));
1767      builder->Add(Smi::FromInt(from));
1768    }
1769  }
1770
1771
1772  void EnsureCapacity(int elements) {
1773    array_builder_.EnsureCapacity(elements);
1774  }
1775
1776
1777  void AddSubjectSlice(int from, int to) {
1778    AddSubjectSlice(&array_builder_, from, to);
1779    IncrementCharacterCount(to - from);
1780  }
1781
1782
1783  void AddString(Handle<String> string) {
1784    int length = string->length();
1785    ASSERT(length > 0);
1786    AddElement(*string);
1787    if (!string->IsAsciiRepresentation()) {
1788      is_ascii_ = false;
1789    }
1790    IncrementCharacterCount(length);
1791  }
1792
1793
1794  Handle<String> ToString() {
1795    if (array_builder_.length() == 0) {
1796      return Factory::empty_string();
1797    }
1798
1799    Handle<String> joined_string;
1800    if (is_ascii_) {
1801      joined_string = NewRawAsciiString(character_count_);
1802      AssertNoAllocation no_alloc;
1803      SeqAsciiString* seq = SeqAsciiString::cast(*joined_string);
1804      char* char_buffer = seq->GetChars();
1805      StringBuilderConcatHelper(*subject_,
1806                                char_buffer,
1807                                *array_builder_.array(),
1808                                array_builder_.length());
1809    } else {
1810      // Non-ASCII.
1811      joined_string = NewRawTwoByteString(character_count_);
1812      AssertNoAllocation no_alloc;
1813      SeqTwoByteString* seq = SeqTwoByteString::cast(*joined_string);
1814      uc16* char_buffer = seq->GetChars();
1815      StringBuilderConcatHelper(*subject_,
1816                                char_buffer,
1817                                *array_builder_.array(),
1818                                array_builder_.length());
1819    }
1820    return joined_string;
1821  }
1822
1823
1824  void IncrementCharacterCount(int by) {
1825    if (character_count_ > String::kMaxLength - by) {
1826      V8::FatalProcessOutOfMemory("String.replace result too large.");
1827    }
1828    character_count_ += by;
1829  }
1830
1831  Handle<JSArray> GetParts() {
1832    Handle<JSArray> result =
1833        Factory::NewJSArrayWithElements(array_builder_.array());
1834    result->set_length(Smi::FromInt(array_builder_.length()));
1835    return result;
1836  }
1837
1838 private:
1839  Handle<String> NewRawAsciiString(int size) {
1840    CALL_HEAP_FUNCTION(Heap::AllocateRawAsciiString(size), String);
1841  }
1842
1843
1844  Handle<String> NewRawTwoByteString(int size) {
1845    CALL_HEAP_FUNCTION(Heap::AllocateRawTwoByteString(size), String);
1846  }
1847
1848
1849  void AddElement(Object* element) {
1850    ASSERT(element->IsSmi() || element->IsString());
1851    ASSERT(array_builder_.capacity() > array_builder_.length());
1852    array_builder_.Add(element);
1853  }
1854
1855  FixedArrayBuilder array_builder_;
1856  Handle<String> subject_;
1857  int character_count_;
1858  bool is_ascii_;
1859};
1860
1861
1862class CompiledReplacement {
1863 public:
1864  CompiledReplacement()
1865      : parts_(1), replacement_substrings_(0) {}
1866
1867  void Compile(Handle<String> replacement,
1868               int capture_count,
1869               int subject_length);
1870
1871  void Apply(ReplacementStringBuilder* builder,
1872             int match_from,
1873             int match_to,
1874             Handle<JSArray> last_match_info);
1875
1876  // Number of distinct parts of the replacement pattern.
1877  int parts() {
1878    return parts_.length();
1879  }
1880 private:
1881  enum PartType {
1882    SUBJECT_PREFIX = 1,
1883    SUBJECT_SUFFIX,
1884    SUBJECT_CAPTURE,
1885    REPLACEMENT_SUBSTRING,
1886    REPLACEMENT_STRING,
1887
1888    NUMBER_OF_PART_TYPES
1889  };
1890
1891  struct ReplacementPart {
1892    static inline ReplacementPart SubjectMatch() {
1893      return ReplacementPart(SUBJECT_CAPTURE, 0);
1894    }
1895    static inline ReplacementPart SubjectCapture(int capture_index) {
1896      return ReplacementPart(SUBJECT_CAPTURE, capture_index);
1897    }
1898    static inline ReplacementPart SubjectPrefix() {
1899      return ReplacementPart(SUBJECT_PREFIX, 0);
1900    }
1901    static inline ReplacementPart SubjectSuffix(int subject_length) {
1902      return ReplacementPart(SUBJECT_SUFFIX, subject_length);
1903    }
1904    static inline ReplacementPart ReplacementString() {
1905      return ReplacementPart(REPLACEMENT_STRING, 0);
1906    }
1907    static inline ReplacementPart ReplacementSubString(int from, int to) {
1908      ASSERT(from >= 0);
1909      ASSERT(to > from);
1910      return ReplacementPart(-from, to);
1911    }
1912
1913    // If tag <= 0 then it is the negation of a start index of a substring of
1914    // the replacement pattern, otherwise it's a value from PartType.
1915    ReplacementPart(int tag, int data)
1916        : tag(tag), data(data) {
1917      // Must be non-positive or a PartType value.
1918      ASSERT(tag < NUMBER_OF_PART_TYPES);
1919    }
1920    // Either a value of PartType or a non-positive number that is
1921    // the negation of an index into the replacement string.
1922    int tag;
1923    // The data value's interpretation depends on the value of tag:
1924    // tag == SUBJECT_PREFIX ||
1925    // tag == SUBJECT_SUFFIX:  data is unused.
1926    // tag == SUBJECT_CAPTURE: data is the number of the capture.
1927    // tag == REPLACEMENT_SUBSTRING ||
1928    // tag == REPLACEMENT_STRING:    data is index into array of substrings
1929    //                               of the replacement string.
1930    // tag <= 0: Temporary representation of the substring of the replacement
1931    //           string ranging over -tag .. data.
1932    //           Is replaced by REPLACEMENT_{SUB,}STRING when we create the
1933    //           substring objects.
1934    int data;
1935  };
1936
1937  template<typename Char>
1938  static void ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
1939                                      Vector<Char> characters,
1940                                      int capture_count,
1941                                      int subject_length) {
1942    int length = characters.length();
1943    int last = 0;
1944    for (int i = 0; i < length; i++) {
1945      Char c = characters[i];
1946      if (c == '$') {
1947        int next_index = i + 1;
1948        if (next_index == length) {  // No next character!
1949          break;
1950        }
1951        Char c2 = characters[next_index];
1952        switch (c2) {
1953        case '$':
1954          if (i > last) {
1955            // There is a substring before. Include the first "$".
1956            parts->Add(ReplacementPart::ReplacementSubString(last, next_index));
1957            last = next_index + 1;  // Continue after the second "$".
1958          } else {
1959            // Let the next substring start with the second "$".
1960            last = next_index;
1961          }
1962          i = next_index;
1963          break;
1964        case '`':
1965          if (i > last) {
1966            parts->Add(ReplacementPart::ReplacementSubString(last, i));
1967          }
1968          parts->Add(ReplacementPart::SubjectPrefix());
1969          i = next_index;
1970          last = i + 1;
1971          break;
1972        case '\'':
1973          if (i > last) {
1974            parts->Add(ReplacementPart::ReplacementSubString(last, i));
1975          }
1976          parts->Add(ReplacementPart::SubjectSuffix(subject_length));
1977          i = next_index;
1978          last = i + 1;
1979          break;
1980        case '&':
1981          if (i > last) {
1982            parts->Add(ReplacementPart::ReplacementSubString(last, i));
1983          }
1984          parts->Add(ReplacementPart::SubjectMatch());
1985          i = next_index;
1986          last = i + 1;
1987          break;
1988        case '0':
1989        case '1':
1990        case '2':
1991        case '3':
1992        case '4':
1993        case '5':
1994        case '6':
1995        case '7':
1996        case '8':
1997        case '9': {
1998          int capture_ref = c2 - '0';
1999          if (capture_ref > capture_count) {
2000            i = next_index;
2001            continue;
2002          }
2003          int second_digit_index = next_index + 1;
2004          if (second_digit_index < length) {
2005            // Peek ahead to see if we have two digits.
2006            Char c3 = characters[second_digit_index];
2007            if ('0' <= c3 && c3 <= '9') {  // Double digits.
2008              int double_digit_ref = capture_ref * 10 + c3 - '0';
2009              if (double_digit_ref <= capture_count) {
2010                next_index = second_digit_index;
2011                capture_ref = double_digit_ref;
2012              }
2013            }
2014          }
2015          if (capture_ref > 0) {
2016            if (i > last) {
2017              parts->Add(ReplacementPart::ReplacementSubString(last, i));
2018            }
2019            ASSERT(capture_ref <= capture_count);
2020            parts->Add(ReplacementPart::SubjectCapture(capture_ref));
2021            last = next_index + 1;
2022          }
2023          i = next_index;
2024          break;
2025        }
2026        default:
2027          i = next_index;
2028          break;
2029        }
2030      }
2031    }
2032    if (length > last) {
2033      if (last == 0) {
2034        parts->Add(ReplacementPart::ReplacementString());
2035      } else {
2036        parts->Add(ReplacementPart::ReplacementSubString(last, length));
2037      }
2038    }
2039  }
2040
2041  ZoneList<ReplacementPart> parts_;
2042  ZoneList<Handle<String> > replacement_substrings_;
2043};
2044
2045
2046void CompiledReplacement::Compile(Handle<String> replacement,
2047                                  int capture_count,
2048                                  int subject_length) {
2049  ASSERT(replacement->IsFlat());
2050  if (replacement->IsAsciiRepresentation()) {
2051    AssertNoAllocation no_alloc;
2052    ParseReplacementPattern(&parts_,
2053                            replacement->ToAsciiVector(),
2054                            capture_count,
2055                            subject_length);
2056  } else {
2057    ASSERT(replacement->IsTwoByteRepresentation());
2058    AssertNoAllocation no_alloc;
2059
2060    ParseReplacementPattern(&parts_,
2061                            replacement->ToUC16Vector(),
2062                            capture_count,
2063                            subject_length);
2064  }
2065  // Find substrings of replacement string and create them as String objects.
2066  int substring_index = 0;
2067  for (int i = 0, n = parts_.length(); i < n; i++) {
2068    int tag = parts_[i].tag;
2069    if (tag <= 0) {  // A replacement string slice.
2070      int from = -tag;
2071      int to = parts_[i].data;
2072      replacement_substrings_.Add(Factory::NewSubString(replacement, from, to));
2073      parts_[i].tag = REPLACEMENT_SUBSTRING;
2074      parts_[i].data = substring_index;
2075      substring_index++;
2076    } else if (tag == REPLACEMENT_STRING) {
2077      replacement_substrings_.Add(replacement);
2078      parts_[i].data = substring_index;
2079      substring_index++;
2080    }
2081  }
2082}
2083
2084
2085void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
2086                                int match_from,
2087                                int match_to,
2088                                Handle<JSArray> last_match_info) {
2089  for (int i = 0, n = parts_.length(); i < n; i++) {
2090    ReplacementPart part = parts_[i];
2091    switch (part.tag) {
2092      case SUBJECT_PREFIX:
2093        if (match_from > 0) builder->AddSubjectSlice(0, match_from);
2094        break;
2095      case SUBJECT_SUFFIX: {
2096        int subject_length = part.data;
2097        if (match_to < subject_length) {
2098          builder->AddSubjectSlice(match_to, subject_length);
2099        }
2100        break;
2101      }
2102      case SUBJECT_CAPTURE: {
2103        int capture = part.data;
2104        FixedArray* match_info = FixedArray::cast(last_match_info->elements());
2105        int from = RegExpImpl::GetCapture(match_info, capture * 2);
2106        int to = RegExpImpl::GetCapture(match_info, capture * 2 + 1);
2107        if (from >= 0 && to > from) {
2108          builder->AddSubjectSlice(from, to);
2109        }
2110        break;
2111      }
2112      case REPLACEMENT_SUBSTRING:
2113      case REPLACEMENT_STRING:
2114        builder->AddString(replacement_substrings_[part.data]);
2115        break;
2116      default:
2117        UNREACHABLE();
2118    }
2119  }
2120}
2121
2122
2123
2124static Object* StringReplaceRegExpWithString(String* subject,
2125                                             JSRegExp* regexp,
2126                                             String* replacement,
2127                                             JSArray* last_match_info) {
2128  ASSERT(subject->IsFlat());
2129  ASSERT(replacement->IsFlat());
2130
2131  HandleScope handles;
2132
2133  int length = subject->length();
2134  Handle<String> subject_handle(subject);
2135  Handle<JSRegExp> regexp_handle(regexp);
2136  Handle<String> replacement_handle(replacement);
2137  Handle<JSArray> last_match_info_handle(last_match_info);
2138  Handle<Object> match = RegExpImpl::Exec(regexp_handle,
2139                                          subject_handle,
2140                                          0,
2141                                          last_match_info_handle);
2142  if (match.is_null()) {
2143    return Failure::Exception();
2144  }
2145  if (match->IsNull()) {
2146    return *subject_handle;
2147  }
2148
2149  int capture_count = regexp_handle->CaptureCount();
2150
2151  // CompiledReplacement uses zone allocation.
2152  CompilationZoneScope zone(DELETE_ON_EXIT);
2153  CompiledReplacement compiled_replacement;
2154  compiled_replacement.Compile(replacement_handle,
2155                               capture_count,
2156                               length);
2157
2158  bool is_global = regexp_handle->GetFlags().is_global();
2159
2160  // Guessing the number of parts that the final result string is built
2161  // from. Global regexps can match any number of times, so we guess
2162  // conservatively.
2163  int expected_parts =
2164      (compiled_replacement.parts() + 1) * (is_global ? 4 : 1) + 1;
2165  ReplacementStringBuilder builder(subject_handle, expected_parts);
2166
2167  // Index of end of last match.
2168  int prev = 0;
2169
2170  // Number of parts added by compiled replacement plus preceeding
2171  // string and possibly suffix after last match.  It is possible for
2172  // all components to use two elements when encoded as two smis.
2173  const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2);
2174  bool matched = true;
2175  do {
2176    ASSERT(last_match_info_handle->HasFastElements());
2177    // Increase the capacity of the builder before entering local handle-scope,
2178    // so its internal buffer can safely allocate a new handle if it grows.
2179    builder.EnsureCapacity(parts_added_per_loop);
2180
2181    HandleScope loop_scope;
2182    int start, end;
2183    {
2184      AssertNoAllocation match_info_array_is_not_in_a_handle;
2185      FixedArray* match_info_array =
2186          FixedArray::cast(last_match_info_handle->elements());
2187
2188      ASSERT_EQ(capture_count * 2 + 2,
2189                RegExpImpl::GetLastCaptureCount(match_info_array));
2190      start = RegExpImpl::GetCapture(match_info_array, 0);
2191      end = RegExpImpl::GetCapture(match_info_array, 1);
2192    }
2193
2194    if (prev < start) {
2195      builder.AddSubjectSlice(prev, start);
2196    }
2197    compiled_replacement.Apply(&builder,
2198                               start,
2199                               end,
2200                               last_match_info_handle);
2201    prev = end;
2202
2203    // Only continue checking for global regexps.
2204    if (!is_global) break;
2205
2206    // Continue from where the match ended, unless it was an empty match.
2207    int next = end;
2208    if (start == end) {
2209      next = end + 1;
2210      if (next > length) break;
2211    }
2212
2213    match = RegExpImpl::Exec(regexp_handle,
2214                             subject_handle,
2215                             next,
2216                             last_match_info_handle);
2217    if (match.is_null()) {
2218      return Failure::Exception();
2219    }
2220    matched = !match->IsNull();
2221  } while (matched);
2222
2223  if (prev < length) {
2224    builder.AddSubjectSlice(prev, length);
2225  }
2226
2227  return *(builder.ToString());
2228}
2229
2230
2231static Object* Runtime_StringReplaceRegExpWithString(Arguments args) {
2232  ASSERT(args.length() == 4);
2233
2234  CONVERT_CHECKED(String, subject, args[0]);
2235  if (!subject->IsFlat()) {
2236    Object* flat_subject = subject->TryFlatten();
2237    if (flat_subject->IsFailure()) {
2238      return flat_subject;
2239    }
2240    subject = String::cast(flat_subject);
2241  }
2242
2243  CONVERT_CHECKED(String, replacement, args[2]);
2244  if (!replacement->IsFlat()) {
2245    Object* flat_replacement = replacement->TryFlatten();
2246    if (flat_replacement->IsFailure()) {
2247      return flat_replacement;
2248    }
2249    replacement = String::cast(flat_replacement);
2250  }
2251
2252  CONVERT_CHECKED(JSRegExp, regexp, args[1]);
2253  CONVERT_CHECKED(JSArray, last_match_info, args[3]);
2254
2255  ASSERT(last_match_info->HasFastElements());
2256
2257  return StringReplaceRegExpWithString(subject,
2258                                       regexp,
2259                                       replacement,
2260                                       last_match_info);
2261}
2262
2263
2264// Cap on the maximal shift in the Boyer-Moore implementation. By setting a
2265// limit, we can fix the size of tables.
2266static const int kBMMaxShift = 0xff;
2267// Reduce alphabet to this size.
2268static const int kBMAlphabetSize = 0x100;
2269// For patterns below this length, the skip length of Boyer-Moore is too short
2270// to compensate for the algorithmic overhead compared to simple brute force.
2271static const int kBMMinPatternLength = 5;
2272
2273// Holds the two buffers used by Boyer-Moore string search's Good Suffix
2274// shift. Only allows the last kBMMaxShift characters of the needle
2275// to be indexed.
2276class BMGoodSuffixBuffers {
2277 public:
2278  BMGoodSuffixBuffers() {}
2279  inline void init(int needle_length) {
2280    ASSERT(needle_length > 1);
2281    int start = needle_length < kBMMaxShift ? 0 : needle_length - kBMMaxShift;
2282    int len = needle_length - start;
2283    biased_suffixes_ = suffixes_ - start;
2284    biased_good_suffix_shift_ = good_suffix_shift_ - start;
2285    for (int i = 0; i <= len; i++) {
2286      good_suffix_shift_[i] = len;
2287    }
2288  }
2289  inline int& suffix(int index) {
2290    ASSERT(biased_suffixes_ + index >= suffixes_);
2291    return biased_suffixes_[index];
2292  }
2293  inline int& shift(int index) {
2294    ASSERT(biased_good_suffix_shift_ + index >= good_suffix_shift_);
2295    return biased_good_suffix_shift_[index];
2296  }
2297 private:
2298  int suffixes_[kBMMaxShift + 1];
2299  int good_suffix_shift_[kBMMaxShift + 1];
2300  int* biased_suffixes_;
2301  int* biased_good_suffix_shift_;
2302  DISALLOW_COPY_AND_ASSIGN(BMGoodSuffixBuffers);
2303};
2304
2305// buffers reused by BoyerMoore
2306static int bad_char_occurrence[kBMAlphabetSize];
2307static BMGoodSuffixBuffers bmgs_buffers;
2308
2309// State of the string match tables.
2310// SIMPLE: No usable content in the buffers.
2311// BOYER_MOORE_HORSPOOL: The bad_char_occurences table has been populated.
2312// BOYER_MOORE: The bmgs_buffers tables have also been populated.
2313// Whenever starting with a new needle, one should call InitializeStringSearch
2314// to determine which search strategy to use, and in the case of a long-needle
2315// strategy, the call also initializes the algorithm to SIMPLE.
2316enum StringSearchAlgorithm { SIMPLE_SEARCH, BOYER_MOORE_HORSPOOL, BOYER_MOORE };
2317static StringSearchAlgorithm algorithm;
2318
2319
2320// Compute the bad-char table for Boyer-Moore in the static buffer.
2321template <typename pchar>
2322static void BoyerMoorePopulateBadCharTable(Vector<const pchar> pattern) {
2323  // Only preprocess at most kBMMaxShift last characters of pattern.
2324  int start = pattern.length() < kBMMaxShift ? 0
2325                                             : pattern.length() - kBMMaxShift;
2326  // Run forwards to populate bad_char_table, so that *last* instance
2327  // of character equivalence class is the one registered.
2328  // Notice: Doesn't include the last character.
2329  int table_size = (sizeof(pchar) == 1) ? String::kMaxAsciiCharCode + 1
2330                                        : kBMAlphabetSize;
2331  if (start == 0) {  // All patterns less than kBMMaxShift in length.
2332    memset(bad_char_occurrence, -1, table_size * sizeof(*bad_char_occurrence));
2333  } else {
2334    for (int i = 0; i < table_size; i++) {
2335      bad_char_occurrence[i] = start - 1;
2336    }
2337  }
2338  for (int i = start; i < pattern.length() - 1; i++) {
2339    pchar c = pattern[i];
2340    int bucket = (sizeof(pchar) ==1) ? c : c % kBMAlphabetSize;
2341    bad_char_occurrence[bucket] = i;
2342  }
2343}
2344
2345
2346template <typename pchar>
2347static void BoyerMoorePopulateGoodSuffixTable(Vector<const pchar> pattern) {
2348  int m = pattern.length();
2349  int start = m < kBMMaxShift ? 0 : m - kBMMaxShift;
2350  int len = m - start;
2351  // Compute Good Suffix tables.
2352  bmgs_buffers.init(m);
2353
2354  bmgs_buffers.shift(m-1) = 1;
2355  bmgs_buffers.suffix(m) = m + 1;
2356  pchar last_char = pattern[m - 1];
2357  int suffix = m + 1;
2358  for (int i = m; i > start;) {
2359    for (pchar c = pattern[i - 1]; suffix <= m && c != pattern[suffix - 1];) {
2360      if (bmgs_buffers.shift(suffix) == len) {
2361        bmgs_buffers.shift(suffix) = suffix - i;
2362      }
2363      suffix = bmgs_buffers.suffix(suffix);
2364    }
2365    i--;
2366    suffix--;
2367    bmgs_buffers.suffix(i) = suffix;
2368    if (suffix == m) {
2369      // No suffix to extend, so we check against last_char only.
2370      while (i > start && pattern[i - 1] != last_char) {
2371        if (bmgs_buffers.shift(m) == len) {
2372          bmgs_buffers.shift(m) = m - i;
2373        }
2374        i--;
2375        bmgs_buffers.suffix(i) = m;
2376      }
2377      if (i > start) {
2378        i--;
2379        suffix--;
2380        bmgs_buffers.suffix(i) = suffix;
2381      }
2382    }
2383  }
2384  if (suffix < m) {
2385    for (int i = start; i <= m; i++) {
2386      if (bmgs_buffers.shift(i) == len) {
2387        bmgs_buffers.shift(i) = suffix - start;
2388      }
2389      if (i == suffix) {
2390        suffix = bmgs_buffers.suffix(suffix);
2391      }
2392    }
2393  }
2394}
2395
2396
2397template <typename schar, typename pchar>
2398static inline int CharOccurrence(int char_code) {
2399  if (sizeof(schar) == 1) {
2400    return bad_char_occurrence[char_code];
2401  }
2402  if (sizeof(pchar) == 1) {
2403    if (char_code > String::kMaxAsciiCharCode) {
2404      return -1;
2405    }
2406    return bad_char_occurrence[char_code];
2407  }
2408  return bad_char_occurrence[char_code % kBMAlphabetSize];
2409}
2410
2411
2412// Restricted simplified Boyer-Moore string matching.
2413// Uses only the bad-shift table of Boyer-Moore and only uses it
2414// for the character compared to the last character of the needle.
2415template <typename schar, typename pchar>
2416static int BoyerMooreHorspool(Vector<const schar> subject,
2417                              Vector<const pchar> pattern,
2418                              int start_index,
2419                              bool* complete) {
2420  ASSERT(algorithm <= BOYER_MOORE_HORSPOOL);
2421  int n = subject.length();
2422  int m = pattern.length();
2423
2424  int badness = -m;
2425
2426  // How bad we are doing without a good-suffix table.
2427  int idx;  // No matches found prior to this index.
2428  pchar last_char = pattern[m - 1];
2429  int last_char_shift = m - 1 - CharOccurrence<schar, pchar>(last_char);
2430  // Perform search
2431  for (idx = start_index; idx <= n - m;) {
2432    int j = m - 1;
2433    int c;
2434    while (last_char != (c = subject[idx + j])) {
2435      int bc_occ = CharOccurrence<schar, pchar>(c);
2436      int shift = j - bc_occ;
2437      idx += shift;
2438      badness += 1 - shift;  // at most zero, so badness cannot increase.
2439      if (idx > n - m) {
2440        *complete = true;
2441        return -1;
2442      }
2443    }
2444    j--;
2445    while (j >= 0 && pattern[j] == (subject[idx + j])) j--;
2446    if (j < 0) {
2447      *complete = true;
2448      return idx;
2449    } else {
2450      idx += last_char_shift;
2451      // Badness increases by the number of characters we have
2452      // checked, and decreases by the number of characters we
2453      // can skip by shifting. It's a measure of how we are doing
2454      // compared to reading each character exactly once.
2455      badness += (m - j) - last_char_shift;
2456      if (badness > 0) {
2457        *complete = false;
2458        return idx;
2459      }
2460    }
2461  }
2462  *complete = true;
2463  return -1;
2464}
2465
2466
2467template <typename schar, typename pchar>
2468static int BoyerMooreIndexOf(Vector<const schar> subject,
2469                             Vector<const pchar> pattern,
2470                             int idx) {
2471  ASSERT(algorithm <= BOYER_MOORE);
2472  int n = subject.length();
2473  int m = pattern.length();
2474  // Only preprocess at most kBMMaxShift last characters of pattern.
2475  int start = m < kBMMaxShift ? 0 : m - kBMMaxShift;
2476
2477  pchar last_char = pattern[m - 1];
2478  // Continue search from i.
2479  while (idx <= n - m) {
2480    int j = m - 1;
2481    schar c;
2482    while (last_char != (c = subject[idx + j])) {
2483      int shift = j - CharOccurrence<schar, pchar>(c);
2484      idx += shift;
2485      if (idx > n - m) {
2486        return -1;
2487      }
2488    }
2489    while (j >= 0 && pattern[j] == (c = subject[idx + j])) j--;
2490    if (j < 0) {
2491      return idx;
2492    } else if (j < start) {
2493      // we have matched more than our tables allow us to be smart about.
2494      // Fall back on BMH shift.
2495      idx += m - 1 - CharOccurrence<schar, pchar>(last_char);
2496    } else {
2497      int gs_shift = bmgs_buffers.shift(j + 1);       // Good suffix shift.
2498      int bc_occ = CharOccurrence<schar, pchar>(c);
2499      int shift = j - bc_occ;                         // Bad-char shift.
2500      if (gs_shift > shift) {
2501        shift = gs_shift;
2502      }
2503      idx += shift;
2504    }
2505  }
2506
2507  return -1;
2508}
2509
2510
2511template <typename schar>
2512static inline int SingleCharIndexOf(Vector<const schar> string,
2513                                    schar pattern_char,
2514                                    int start_index) {
2515  if (sizeof(schar) == 1) {
2516    const schar* pos = reinterpret_cast<const schar*>(
2517        memchr(string.start() + start_index,
2518               pattern_char,
2519               string.length() - start_index));
2520    if (pos == NULL) return -1;
2521    return static_cast<int>(pos - string.start());
2522  }
2523  for (int i = start_index, n = string.length(); i < n; i++) {
2524    if (pattern_char == string[i]) {
2525      return i;
2526    }
2527  }
2528  return -1;
2529}
2530
2531
2532template <typename schar>
2533static int SingleCharLastIndexOf(Vector<const schar> string,
2534                                 schar pattern_char,
2535                                 int start_index) {
2536  for (int i = start_index; i >= 0; i--) {
2537    if (pattern_char == string[i]) {
2538      return i;
2539    }
2540  }
2541  return -1;
2542}
2543
2544
2545// Trivial string search for shorter strings.
2546// On return, if "complete" is set to true, the return value is the
2547// final result of searching for the patter in the subject.
2548// If "complete" is set to false, the return value is the index where
2549// further checking should start, i.e., it's guaranteed that the pattern
2550// does not occur at a position prior to the returned index.
2551template <typename pchar, typename schar>
2552static int SimpleIndexOf(Vector<const schar> subject,
2553                         Vector<const pchar> pattern,
2554                         int idx,
2555                         bool* complete) {
2556  // Badness is a count of how much work we have done.  When we have
2557  // done enough work we decide it's probably worth switching to a better
2558  // algorithm.
2559  int badness = -10 - (pattern.length() << 2);
2560
2561  // We know our pattern is at least 2 characters, we cache the first so
2562  // the common case of the first character not matching is faster.
2563  pchar pattern_first_char = pattern[0];
2564  for (int i = idx, n = subject.length() - pattern.length(); i <= n; i++) {
2565    badness++;
2566    if (badness > 0) {
2567      *complete = false;
2568      return i;
2569    }
2570    if (sizeof(schar) == 1 && sizeof(pchar) == 1) {
2571      const schar* pos = reinterpret_cast<const schar*>(
2572          memchr(subject.start() + i,
2573                 pattern_first_char,
2574                 n - i + 1));
2575      if (pos == NULL) {
2576        *complete = true;
2577        return -1;
2578      }
2579      i = static_cast<int>(pos - subject.start());
2580    } else {
2581      if (subject[i] != pattern_first_char) continue;
2582    }
2583    int j = 1;
2584    do {
2585      if (pattern[j] != subject[i+j]) {
2586        break;
2587      }
2588      j++;
2589    } while (j < pattern.length());
2590    if (j == pattern.length()) {
2591      *complete = true;
2592      return i;
2593    }
2594    badness += j;
2595  }
2596  *complete = true;
2597  return -1;
2598}
2599
2600// Simple indexOf that never bails out. For short patterns only.
2601template <typename pchar, typename schar>
2602static int SimpleIndexOf(Vector<const schar> subject,
2603                         Vector<const pchar> pattern,
2604                         int idx) {
2605  pchar pattern_first_char = pattern[0];
2606  for (int i = idx, n = subject.length() - pattern.length(); i <= n; i++) {
2607    if (sizeof(schar) == 1 && sizeof(pchar) == 1) {
2608      const schar* pos = reinterpret_cast<const schar*>(
2609          memchr(subject.start() + i,
2610                 pattern_first_char,
2611                 n - i + 1));
2612      if (pos == NULL) return -1;
2613      i = static_cast<int>(pos - subject.start());
2614    } else {
2615      if (subject[i] != pattern_first_char) continue;
2616    }
2617    int j = 1;
2618    do {
2619      if (pattern[j] != subject[i+j]) {
2620        break;
2621      }
2622      j++;
2623    } while (j < pattern.length());
2624    if (j == pattern.length()) {
2625      return i;
2626    }
2627  }
2628  return -1;
2629}
2630
2631
2632// Strategy for searching for a string in another string.
2633enum StringSearchStrategy { SEARCH_FAIL, SEARCH_SHORT, SEARCH_LONG };
2634
2635
2636template <typename pchar>
2637static inline StringSearchStrategy InitializeStringSearch(
2638    Vector<const pchar> pat, bool ascii_subject) {
2639  ASSERT(pat.length() > 1);
2640  // We have an ASCII haystack and a non-ASCII needle. Check if there
2641  // really is a non-ASCII character in the needle and bail out if there
2642  // is.
2643  if (ascii_subject && sizeof(pchar) > 1) {
2644    for (int i = 0; i < pat.length(); i++) {
2645      uc16 c = pat[i];
2646      if (c > String::kMaxAsciiCharCode) {
2647        return SEARCH_FAIL;
2648      }
2649    }
2650  }
2651  if (pat.length() < kBMMinPatternLength) {
2652    return SEARCH_SHORT;
2653  }
2654  algorithm = SIMPLE_SEARCH;
2655  return SEARCH_LONG;
2656}
2657
2658
2659// Dispatch long needle searches to different algorithms.
2660template <typename schar, typename pchar>
2661static int ComplexIndexOf(Vector<const schar> sub,
2662                          Vector<const pchar> pat,
2663                          int start_index) {
2664  ASSERT(pat.length() >= kBMMinPatternLength);
2665  // Try algorithms in order of increasing setup cost and expected performance.
2666  bool complete;
2667  int idx = start_index;
2668  switch (algorithm) {
2669    case SIMPLE_SEARCH:
2670      idx = SimpleIndexOf(sub, pat, idx, &complete);
2671      if (complete) return idx;
2672      BoyerMoorePopulateBadCharTable(pat);
2673      algorithm = BOYER_MOORE_HORSPOOL;
2674      // FALLTHROUGH.
2675    case BOYER_MOORE_HORSPOOL:
2676      idx = BoyerMooreHorspool(sub, pat, idx, &complete);
2677      if (complete) return idx;
2678      // Build the Good Suffix table and continue searching.
2679      BoyerMoorePopulateGoodSuffixTable(pat);
2680      algorithm = BOYER_MOORE;
2681      // FALLTHROUGH.
2682    case BOYER_MOORE:
2683      return BoyerMooreIndexOf(sub, pat, idx);
2684  }
2685  UNREACHABLE();
2686  return -1;
2687}
2688
2689
2690// Dispatch to different search strategies for a single search.
2691// If searching multiple times on the same needle, the search
2692// strategy should only be computed once and then dispatch to different
2693// loops.
2694template <typename schar, typename pchar>
2695static int StringSearch(Vector<const schar> sub,
2696                        Vector<const pchar> pat,
2697                        int start_index) {
2698  bool ascii_subject = (sizeof(schar) == 1);
2699  StringSearchStrategy strategy = InitializeStringSearch(pat, ascii_subject);
2700  switch (strategy) {
2701    case SEARCH_FAIL: return -1;
2702    case SEARCH_SHORT: return SimpleIndexOf(sub, pat, start_index);
2703    case SEARCH_LONG: return ComplexIndexOf(sub, pat, start_index);
2704  }
2705  UNREACHABLE();
2706  return -1;
2707}
2708
2709
2710// Perform string match of pattern on subject, starting at start index.
2711// Caller must ensure that 0 <= start_index <= sub->length(),
2712// and should check that pat->length() + start_index <= sub->length()
2713int Runtime::StringMatch(Handle<String> sub,
2714                         Handle<String> pat,
2715                         int start_index) {
2716  ASSERT(0 <= start_index);
2717  ASSERT(start_index <= sub->length());
2718
2719  int pattern_length = pat->length();
2720  if (pattern_length == 0) return start_index;
2721
2722  int subject_length = sub->length();
2723  if (start_index + pattern_length > subject_length) return -1;
2724
2725  if (!sub->IsFlat()) {
2726    FlattenString(sub);
2727  }
2728
2729  // Searching for one specific character is common.  For one
2730  // character patterns linear search is necessary, so any smart
2731  // algorithm is unnecessary overhead.
2732  if (pattern_length == 1) {
2733    AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
2734    if (sub->IsAsciiRepresentation()) {
2735      uc16 pchar = pat->Get(0);
2736      if (pchar > String::kMaxAsciiCharCode) {
2737        return -1;
2738      }
2739      Vector<const char> ascii_vector =
2740        sub->ToAsciiVector().SubVector(start_index, subject_length);
2741      const void* pos = memchr(ascii_vector.start(),
2742                               static_cast<const char>(pchar),
2743                               static_cast<size_t>(ascii_vector.length()));
2744      if (pos == NULL) {
2745        return -1;
2746      }
2747      return static_cast<int>(reinterpret_cast<const char*>(pos)
2748          - ascii_vector.start() + start_index);
2749    }
2750    return SingleCharIndexOf(sub->ToUC16Vector(), pat->Get(0), start_index);
2751  }
2752
2753  if (!pat->IsFlat()) {
2754    FlattenString(pat);
2755  }
2756
2757  AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
2758  // dispatch on type of strings
2759  if (pat->IsAsciiRepresentation()) {
2760    Vector<const char> pat_vector = pat->ToAsciiVector();
2761    if (sub->IsAsciiRepresentation()) {
2762      return StringSearch(sub->ToAsciiVector(), pat_vector, start_index);
2763    }
2764    return StringSearch(sub->ToUC16Vector(), pat_vector, start_index);
2765  }
2766  Vector<const uc16> pat_vector = pat->ToUC16Vector();
2767  if (sub->IsAsciiRepresentation()) {
2768    return StringSearch(sub->ToAsciiVector(), pat_vector, start_index);
2769  }
2770  return StringSearch(sub->ToUC16Vector(), pat_vector, start_index);
2771}
2772
2773
2774static Object* Runtime_StringIndexOf(Arguments args) {
2775  HandleScope scope;  // create a new handle scope
2776  ASSERT(args.length() == 3);
2777
2778  CONVERT_ARG_CHECKED(String, sub, 0);
2779  CONVERT_ARG_CHECKED(String, pat, 1);
2780
2781  Object* index = args[2];
2782  uint32_t start_index;
2783  if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1);
2784
2785  RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
2786  int position = Runtime::StringMatch(sub, pat, start_index);
2787  return Smi::FromInt(position);
2788}
2789
2790
2791template <typename schar, typename pchar>
2792static int StringMatchBackwards(Vector<const schar> sub,
2793                                Vector<const pchar> pat,
2794                                int idx) {
2795  ASSERT(pat.length() >= 1);
2796  ASSERT(idx + pat.length() <= sub.length());
2797
2798  if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
2799    for (int i = 0; i < pat.length(); i++) {
2800      uc16 c = pat[i];
2801      if (c > String::kMaxAsciiCharCode) {
2802        return -1;
2803      }
2804    }
2805  }
2806
2807  pchar pattern_first_char = pat[0];
2808  for (int i = idx; i >= 0; i--) {
2809    if (sub[i] != pattern_first_char) continue;
2810    int j = 1;
2811    while (j < pat.length()) {
2812      if (pat[j] != sub[i+j]) {
2813        break;
2814      }
2815      j++;
2816    }
2817    if (j == pat.length()) {
2818      return i;
2819    }
2820  }
2821  return -1;
2822}
2823
2824static Object* Runtime_StringLastIndexOf(Arguments args) {
2825  HandleScope scope;  // create a new handle scope
2826  ASSERT(args.length() == 3);
2827
2828  CONVERT_ARG_CHECKED(String, sub, 0);
2829  CONVERT_ARG_CHECKED(String, pat, 1);
2830
2831  Object* index = args[2];
2832  uint32_t start_index;
2833  if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1);
2834
2835  uint32_t pat_length = pat->length();
2836  uint32_t sub_length = sub->length();
2837
2838  if (start_index + pat_length > sub_length) {
2839    start_index = sub_length - pat_length;
2840  }
2841
2842  if (pat_length == 0) {
2843    return Smi::FromInt(start_index);
2844  }
2845
2846  if (!sub->IsFlat()) {
2847    FlattenString(sub);
2848  }
2849
2850  if (pat_length == 1) {
2851    AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
2852    if (sub->IsAsciiRepresentation()) {
2853      uc16 pchar = pat->Get(0);
2854      if (pchar > String::kMaxAsciiCharCode) {
2855        return Smi::FromInt(-1);
2856      }
2857      return Smi::FromInt(SingleCharLastIndexOf(sub->ToAsciiVector(),
2858                                                static_cast<char>(pat->Get(0)),
2859                                                start_index));
2860    } else {
2861      return Smi::FromInt(SingleCharLastIndexOf(sub->ToUC16Vector(),
2862                                                pat->Get(0),
2863                                                start_index));
2864    }
2865  }
2866
2867  if (!pat->IsFlat()) {
2868    FlattenString(pat);
2869  }
2870
2871  AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
2872
2873  int position = -1;
2874
2875  if (pat->IsAsciiRepresentation()) {
2876    Vector<const char> pat_vector = pat->ToAsciiVector();
2877    if (sub->IsAsciiRepresentation()) {
2878      position = StringMatchBackwards(sub->ToAsciiVector(),
2879                                      pat_vector,
2880                                      start_index);
2881    } else {
2882      position = StringMatchBackwards(sub->ToUC16Vector(),
2883                                      pat_vector,
2884                                      start_index);
2885    }
2886  } else {
2887    Vector<const uc16> pat_vector = pat->ToUC16Vector();
2888    if (sub->IsAsciiRepresentation()) {
2889      position = StringMatchBackwards(sub->ToAsciiVector(),
2890                                      pat_vector,
2891                                      start_index);
2892    } else {
2893      position = StringMatchBackwards(sub->ToUC16Vector(),
2894                                      pat_vector,
2895                                      start_index);
2896    }
2897  }
2898
2899  return Smi::FromInt(position);
2900}
2901
2902
2903static Object* Runtime_StringLocaleCompare(Arguments args) {
2904  NoHandleAllocation ha;
2905  ASSERT(args.length() == 2);
2906
2907  CONVERT_CHECKED(String, str1, args[0]);
2908  CONVERT_CHECKED(String, str2, args[1]);
2909
2910  if (str1 == str2) return Smi::FromInt(0);  // Equal.
2911  int str1_length = str1->length();
2912  int str2_length = str2->length();
2913
2914  // Decide trivial cases without flattening.
2915  if (str1_length == 0) {
2916    if (str2_length == 0) return Smi::FromInt(0);  // Equal.
2917    return Smi::FromInt(-str2_length);
2918  } else {
2919    if (str2_length == 0) return Smi::FromInt(str1_length);
2920  }
2921
2922  int end = str1_length < str2_length ? str1_length : str2_length;
2923
2924  // No need to flatten if we are going to find the answer on the first
2925  // character.  At this point we know there is at least one character
2926  // in each string, due to the trivial case handling above.
2927  int d = str1->Get(0) - str2->Get(0);
2928  if (d != 0) return Smi::FromInt(d);
2929
2930  str1->TryFlatten();
2931  str2->TryFlatten();
2932
2933  static StringInputBuffer buf1;
2934  static StringInputBuffer buf2;
2935
2936  buf1.Reset(str1);
2937  buf2.Reset(str2);
2938
2939  for (int i = 0; i < end; i++) {
2940    uint16_t char1 = buf1.GetNext();
2941    uint16_t char2 = buf2.GetNext();
2942    if (char1 != char2) return Smi::FromInt(char1 - char2);
2943  }
2944
2945  return Smi::FromInt(str1_length - str2_length);
2946}
2947
2948
2949static Object* Runtime_SubString(Arguments args) {
2950  NoHandleAllocation ha;
2951  ASSERT(args.length() == 3);
2952
2953  CONVERT_CHECKED(String, value, args[0]);
2954  Object* from = args[1];
2955  Object* to = args[2];
2956  int start, end;
2957  // We have a fast integer-only case here to avoid a conversion to double in
2958  // the common case where from and to are Smis.
2959  if (from->IsSmi() && to->IsSmi()) {
2960    start = Smi::cast(from)->value();
2961    end = Smi::cast(to)->value();
2962  } else {
2963    CONVERT_DOUBLE_CHECKED(from_number, from);
2964    CONVERT_DOUBLE_CHECKED(to_number, to);
2965    start = FastD2I(from_number);
2966    end = FastD2I(to_number);
2967  }
2968  RUNTIME_ASSERT(end >= start);
2969  RUNTIME_ASSERT(start >= 0);
2970  RUNTIME_ASSERT(end <= value->length());
2971  Counters::sub_string_runtime.Increment();
2972  return value->SubString(start, end);
2973}
2974
2975
2976static Object* Runtime_StringMatch(Arguments args) {
2977  ASSERT_EQ(3, args.length());
2978
2979  CONVERT_ARG_CHECKED(String, subject, 0);
2980  CONVERT_ARG_CHECKED(JSRegExp, regexp, 1);
2981  CONVERT_ARG_CHECKED(JSArray, regexp_info, 2);
2982  HandleScope handles;
2983
2984  Handle<Object> match = RegExpImpl::Exec(regexp, subject, 0, regexp_info);
2985
2986  if (match.is_null()) {
2987    return Failure::Exception();
2988  }
2989  if (match->IsNull()) {
2990    return Heap::null_value();
2991  }
2992  int length = subject->length();
2993
2994  CompilationZoneScope zone_space(DELETE_ON_EXIT);
2995  ZoneList<int> offsets(8);
2996  do {
2997    int start;
2998    int end;
2999    {
3000      AssertNoAllocation no_alloc;
3001      FixedArray* elements = FixedArray::cast(regexp_info->elements());
3002      start = Smi::cast(elements->get(RegExpImpl::kFirstCapture))->value();
3003      end = Smi::cast(elements->get(RegExpImpl::kFirstCapture + 1))->value();
3004    }
3005    offsets.Add(start);
3006    offsets.Add(end);
3007    int index = start < end ? end : end + 1;
3008    if (index > length) break;
3009    match = RegExpImpl::Exec(regexp, subject, index, regexp_info);
3010    if (match.is_null()) {
3011      return Failure::Exception();
3012    }
3013  } while (!match->IsNull());
3014  int matches = offsets.length() / 2;
3015  Handle<FixedArray> elements = Factory::NewFixedArray(matches);
3016  for (int i = 0; i < matches ; i++) {
3017    int from = offsets.at(i * 2);
3018    int to = offsets.at(i * 2 + 1);
3019    elements->set(i, *Factory::NewSubString(subject, from, to));
3020  }
3021  Handle<JSArray> result = Factory::NewJSArrayWithElements(elements);
3022  result->set_length(Smi::FromInt(matches));
3023  return *result;
3024}
3025
3026
3027// Two smis before and after the match, for very long strings.
3028const int kMaxBuilderEntriesPerRegExpMatch = 5;
3029
3030
3031static void SetLastMatchInfoNoCaptures(Handle<String> subject,
3032                                       Handle<JSArray> last_match_info,
3033                                       int match_start,
3034                                       int match_end) {
3035  // Fill last_match_info with a single capture.
3036  last_match_info->EnsureSize(2 + RegExpImpl::kLastMatchOverhead);
3037  AssertNoAllocation no_gc;
3038  FixedArray* elements = FixedArray::cast(last_match_info->elements());
3039  RegExpImpl::SetLastCaptureCount(elements, 2);
3040  RegExpImpl::SetLastInput(elements, *subject);
3041  RegExpImpl::SetLastSubject(elements, *subject);
3042  RegExpImpl::SetCapture(elements, 0, match_start);
3043  RegExpImpl::SetCapture(elements, 1, match_end);
3044}
3045
3046
3047template <typename schar>
3048static bool SearchCharMultiple(Vector<schar> subject,
3049                               String* pattern,
3050                               schar pattern_char,
3051                               FixedArrayBuilder* builder,
3052                               int* match_pos) {
3053  // Position of last match.
3054  int pos = *match_pos;
3055  int subject_length = subject.length();
3056  while (pos < subject_length) {
3057    int match_end = pos + 1;
3058    if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
3059      *match_pos = pos;
3060      return false;
3061    }
3062    int new_pos = SingleCharIndexOf(subject, pattern_char, match_end);
3063    if (new_pos >= 0) {
3064      // Match has been found.
3065      if (new_pos > match_end) {
3066        ReplacementStringBuilder::AddSubjectSlice(builder, match_end, new_pos);
3067      }
3068      pos = new_pos;
3069      builder->Add(pattern);
3070    } else {
3071      break;
3072    }
3073  }
3074  if (pos + 1 < subject_length) {
3075    ReplacementStringBuilder::AddSubjectSlice(builder, pos + 1, subject_length);
3076  }
3077  *match_pos = pos;
3078  return true;
3079}
3080
3081
3082static bool SearchCharMultiple(Handle<String> subject,
3083                               Handle<String> pattern,
3084                               Handle<JSArray> last_match_info,
3085                               FixedArrayBuilder* builder) {
3086  ASSERT(subject->IsFlat());
3087  ASSERT_EQ(1, pattern->length());
3088  uc16 pattern_char = pattern->Get(0);
3089  // Treating position before first as initial "previous match position".
3090  int match_pos = -1;
3091
3092  for (;;) {  // Break when search complete.
3093    builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3094    AssertNoAllocation no_gc;
3095    if (subject->IsAsciiRepresentation()) {
3096      if (pattern_char > String::kMaxAsciiCharCode) {
3097        break;
3098      }
3099      Vector<const char> subject_vector = subject->ToAsciiVector();
3100      char pattern_ascii_char = static_cast<char>(pattern_char);
3101      bool complete = SearchCharMultiple<const char>(subject_vector,
3102                                                     *pattern,
3103                                                     pattern_ascii_char,
3104                                                     builder,
3105                                                     &match_pos);
3106      if (complete) break;
3107    } else {
3108      Vector<const uc16> subject_vector = subject->ToUC16Vector();
3109      bool complete = SearchCharMultiple<const uc16>(subject_vector,
3110                                                     *pattern,
3111                                                     pattern_char,
3112                                                     builder,
3113                                                     &match_pos);
3114      if (complete) break;
3115    }
3116  }
3117
3118  if (match_pos >= 0) {
3119    SetLastMatchInfoNoCaptures(subject,
3120                               last_match_info,
3121                               match_pos,
3122                               match_pos + 1);
3123    return true;
3124  }
3125  return false;  // No matches at all.
3126}
3127
3128
3129template <typename schar, typename pchar>
3130static bool SearchStringMultiple(Vector<schar> subject,
3131                                 String* pattern,
3132                                 Vector<pchar> pattern_string,
3133                                 FixedArrayBuilder* builder,
3134                                 int* match_pos) {
3135  int pos = *match_pos;
3136  int subject_length = subject.length();
3137  int pattern_length = pattern_string.length();
3138  int max_search_start = subject_length - pattern_length;
3139  bool is_ascii = (sizeof(schar) == 1);
3140  StringSearchStrategy strategy =
3141      InitializeStringSearch(pattern_string, is_ascii);
3142  switch (strategy) {
3143    case SEARCH_FAIL: break;
3144    case SEARCH_SHORT:
3145      while (pos <= max_search_start) {
3146        if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
3147          *match_pos = pos;
3148          return false;
3149        }
3150        // Position of end of previous match.
3151        int match_end = pos + pattern_length;
3152        int new_pos = SimpleIndexOf(subject, pattern_string, match_end);
3153        if (new_pos >= 0) {
3154          // A match.
3155          if (new_pos > match_end) {
3156            ReplacementStringBuilder::AddSubjectSlice(builder,
3157                                                      match_end,
3158                                                      new_pos);
3159          }
3160          pos = new_pos;
3161          builder->Add(pattern);
3162        } else {
3163          break;
3164        }
3165      }
3166      break;
3167    case SEARCH_LONG:
3168      while (pos  <= max_search_start) {
3169        if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
3170          *match_pos = pos;
3171          return false;
3172        }
3173        int match_end = pos + pattern_length;
3174        int new_pos = ComplexIndexOf(subject, pattern_string, match_end);
3175        if (new_pos >= 0) {
3176          // A match has been found.
3177          if (new_pos > match_end) {
3178            ReplacementStringBuilder::AddSubjectSlice(builder,
3179                                                      match_end,
3180                                                      new_pos);
3181          }
3182          pos = new_pos;
3183          builder->Add(pattern);
3184        } else {
3185         break;
3186        }
3187      }
3188      break;
3189  }
3190  if (pos < max_search_start) {
3191    ReplacementStringBuilder::AddSubjectSlice(builder,
3192                                              pos + pattern_length,
3193                                              subject_length);
3194  }
3195  *match_pos = pos;
3196  return true;
3197}
3198
3199
3200static bool SearchStringMultiple(Handle<String> subject,
3201                                 Handle<String> pattern,
3202                                 Handle<JSArray> last_match_info,
3203                                 FixedArrayBuilder* builder) {
3204  ASSERT(subject->IsFlat());
3205  ASSERT(pattern->IsFlat());
3206  ASSERT(pattern->length() > 1);
3207
3208  // Treating as if a previous match was before first character.
3209  int match_pos = -pattern->length();
3210
3211  for (;;) {  // Break when search complete.
3212    builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3213    AssertNoAllocation no_gc;
3214    if (subject->IsAsciiRepresentation()) {
3215      Vector<const char> subject_vector = subject->ToAsciiVector();
3216      if (pattern->IsAsciiRepresentation()) {
3217        if (SearchStringMultiple(subject_vector,
3218                                 *pattern,
3219                                 pattern->ToAsciiVector(),
3220                                 builder,
3221                                 &match_pos)) break;
3222      } else {
3223        if (SearchStringMultiple(subject_vector,
3224                                 *pattern,
3225                                 pattern->ToUC16Vector(),
3226                                 builder,
3227                                 &match_pos)) break;
3228      }
3229    } else {
3230      Vector<const uc16> subject_vector = subject->ToUC16Vector();
3231      if (pattern->IsAsciiRepresentation()) {
3232        if (SearchStringMultiple(subject_vector,
3233                                 *pattern,
3234                                 pattern->ToAsciiVector(),
3235                                 builder,
3236                                 &match_pos)) break;
3237      } else {
3238        if (SearchStringMultiple(subject_vector,
3239                                 *pattern,
3240                                 pattern->ToUC16Vector(),
3241                                 builder,
3242                                 &match_pos)) break;
3243      }
3244    }
3245  }
3246
3247  if (match_pos >= 0) {
3248    SetLastMatchInfoNoCaptures(subject,
3249                               last_match_info,
3250                               match_pos,
3251                               match_pos + pattern->length());
3252    return true;
3253  }
3254  return false;  // No matches at all.
3255}
3256
3257
3258static RegExpImpl::IrregexpResult SearchRegExpNoCaptureMultiple(
3259    Handle<String> subject,
3260    Handle<JSRegExp> regexp,
3261    Handle<JSArray> last_match_array,
3262    FixedArrayBuilder* builder) {
3263  ASSERT(subject->IsFlat());
3264  int match_start = -1;
3265  int match_end = 0;
3266  int pos = 0;
3267  int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject);
3268  if (required_registers < 0) return RegExpImpl::RE_EXCEPTION;
3269
3270  OffsetsVector registers(required_registers);
3271  Vector<int> register_vector(registers.vector(), registers.length());
3272  int subject_length = subject->length();
3273
3274  for (;;) {  // Break on failure, return on exception.
3275    RegExpImpl::IrregexpResult result =
3276        RegExpImpl::IrregexpExecOnce(regexp,
3277                                     subject,
3278                                     pos,
3279                                     register_vector);
3280    if (result == RegExpImpl::RE_SUCCESS) {
3281      match_start = register_vector[0];
3282      builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3283      if (match_end < match_start) {
3284        ReplacementStringBuilder::AddSubjectSlice(builder,
3285                                                  match_end,
3286                                                  match_start);
3287      }
3288      match_end = register_vector[1];
3289      HandleScope loop_scope;
3290      builder->Add(*Factory::NewSubString(subject, match_start, match_end));
3291      if (match_start != match_end) {
3292        pos = match_end;
3293      } else {
3294        pos = match_end + 1;
3295        if (pos > subject_length) break;
3296      }
3297    } else if (result == RegExpImpl::RE_FAILURE) {
3298      break;
3299    } else {
3300      ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION);
3301      return result;
3302    }
3303  }
3304
3305  if (match_start >= 0) {
3306    if (match_end < subject_length) {
3307      ReplacementStringBuilder::AddSubjectSlice(builder,
3308                                                match_end,
3309                                                subject_length);
3310    }
3311    SetLastMatchInfoNoCaptures(subject,
3312                               last_match_array,
3313                               match_start,
3314                               match_end);
3315    return RegExpImpl::RE_SUCCESS;
3316  } else {
3317    return RegExpImpl::RE_FAILURE;  // No matches at all.
3318  }
3319}
3320
3321
3322static RegExpImpl::IrregexpResult SearchRegExpMultiple(
3323    Handle<String> subject,
3324    Handle<JSRegExp> regexp,
3325    Handle<JSArray> last_match_array,
3326    FixedArrayBuilder* builder) {
3327
3328  ASSERT(subject->IsFlat());
3329  int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject);
3330  if (required_registers < 0) return RegExpImpl::RE_EXCEPTION;
3331
3332  OffsetsVector registers(required_registers);
3333  Vector<int> register_vector(registers.vector(), registers.length());
3334
3335  RegExpImpl::IrregexpResult result =
3336      RegExpImpl::IrregexpExecOnce(regexp,
3337                                   subject,
3338                                   0,
3339                                   register_vector);
3340
3341  int capture_count = regexp->CaptureCount();
3342  int subject_length = subject->length();
3343
3344  // Position to search from.
3345  int pos = 0;
3346  // End of previous match. Differs from pos if match was empty.
3347  int match_end = 0;
3348  if (result == RegExpImpl::RE_SUCCESS) {
3349    // Need to keep a copy of the previous match for creating last_match_info
3350    // at the end, so we have two vectors that we swap between.
3351    OffsetsVector registers2(required_registers);
3352    Vector<int> prev_register_vector(registers2.vector(), registers2.length());
3353
3354    do {
3355      int match_start = register_vector[0];
3356      builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3357      if (match_end < match_start) {
3358        ReplacementStringBuilder::AddSubjectSlice(builder,
3359                                                  match_end,
3360                                                  match_start);
3361      }
3362      match_end = register_vector[1];
3363
3364      {
3365        // Avoid accumulating new handles inside loop.
3366        HandleScope temp_scope;
3367        // Arguments array to replace function is match, captures, index and
3368        // subject, i.e., 3 + capture count in total.
3369        Handle<FixedArray> elements = Factory::NewFixedArray(3 + capture_count);
3370        elements->set(0, *Factory::NewSubString(subject,
3371                                                match_start,
3372                                                match_end));
3373        for (int i = 1; i <= capture_count; i++) {
3374          int start = register_vector[i * 2];
3375          if (start >= 0) {
3376            int end = register_vector[i * 2 + 1];
3377            ASSERT(start <= end);
3378            Handle<String> substring = Factory::NewSubString(subject,
3379                                                             start,
3380                                                             end);
3381            elements->set(i, *substring);
3382          } else {
3383            ASSERT(register_vector[i * 2 + 1] < 0);
3384            elements->set(i, Heap::undefined_value());
3385          }
3386        }
3387        elements->set(capture_count + 1, Smi::FromInt(match_start));
3388        elements->set(capture_count + 2, *subject);
3389        builder->Add(*Factory::NewJSArrayWithElements(elements));
3390      }
3391      // Swap register vectors, so the last successful match is in
3392      // prev_register_vector.
3393      Vector<int> tmp = prev_register_vector;
3394      prev_register_vector = register_vector;
3395      register_vector = tmp;
3396
3397      if (match_end > match_start) {
3398        pos = match_end;
3399      } else {
3400        pos = match_end + 1;
3401        if (pos > subject_length) {
3402          break;
3403        }
3404      }
3405
3406      result = RegExpImpl::IrregexpExecOnce(regexp,
3407                                            subject,
3408                                            pos,
3409                                            register_vector);
3410    } while (result == RegExpImpl::RE_SUCCESS);
3411
3412    if (result != RegExpImpl::RE_EXCEPTION) {
3413      // Finished matching, with at least one match.
3414      if (match_end < subject_length) {
3415        ReplacementStringBuilder::AddSubjectSlice(builder,
3416                                                  match_end,
3417                                                  subject_length);
3418      }
3419
3420      int last_match_capture_count = (capture_count + 1) * 2;
3421      int last_match_array_size =
3422          last_match_capture_count + RegExpImpl::kLastMatchOverhead;
3423      last_match_array->EnsureSize(last_match_array_size);
3424      AssertNoAllocation no_gc;
3425      FixedArray* elements = FixedArray::cast(last_match_array->elements());
3426      RegExpImpl::SetLastCaptureCount(elements, last_match_capture_count);
3427      RegExpImpl::SetLastSubject(elements, *subject);
3428      RegExpImpl::SetLastInput(elements, *subject);
3429      for (int i = 0; i < last_match_capture_count; i++) {
3430        RegExpImpl::SetCapture(elements, i, prev_register_vector[i]);
3431      }
3432      return RegExpImpl::RE_SUCCESS;
3433    }
3434  }
3435  // No matches at all, return failure or exception result directly.
3436  return result;
3437}
3438
3439
3440static Object* Runtime_RegExpExecMultiple(Arguments args) {
3441  ASSERT(args.length() == 4);
3442  HandleScope handles;
3443
3444  CONVERT_ARG_CHECKED(String, subject, 1);
3445  if (!subject->IsFlat()) { FlattenString(subject); }
3446  CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
3447  CONVERT_ARG_CHECKED(JSArray, last_match_info, 2);
3448  CONVERT_ARG_CHECKED(JSArray, result_array, 3);
3449
3450  ASSERT(last_match_info->HasFastElements());
3451  ASSERT(regexp->GetFlags().is_global());
3452  Handle<FixedArray> result_elements;
3453  if (result_array->HasFastElements()) {
3454    result_elements =
3455        Handle<FixedArray>(FixedArray::cast(result_array->elements()));
3456  } else {
3457    result_elements = Factory::NewFixedArrayWithHoles(16);
3458  }
3459  FixedArrayBuilder builder(result_elements);
3460
3461  if (regexp->TypeTag() == JSRegExp::ATOM) {
3462    Handle<String> pattern(
3463        String::cast(regexp->DataAt(JSRegExp::kAtomPatternIndex)));
3464    int pattern_length = pattern->length();
3465    if (pattern_length == 1) {
3466      if (SearchCharMultiple(subject, pattern, last_match_info, &builder)) {
3467        return *builder.ToJSArray(result_array);
3468      }
3469      return Heap::null_value();
3470    }
3471
3472    if (!pattern->IsFlat()) FlattenString(pattern);
3473    if (SearchStringMultiple(subject, pattern, last_match_info, &builder)) {
3474      return *builder.ToJSArray(result_array);
3475    }
3476    return Heap::null_value();
3477  }
3478
3479  ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP);
3480
3481  RegExpImpl::IrregexpResult result;
3482  if (regexp->CaptureCount() == 0) {
3483    result = SearchRegExpNoCaptureMultiple(subject,
3484                                           regexp,
3485                                           last_match_info,
3486                                           &builder);
3487  } else {
3488    result = SearchRegExpMultiple(subject, regexp, last_match_info, &builder);
3489  }
3490  if (result == RegExpImpl::RE_SUCCESS) return *builder.ToJSArray(result_array);
3491  if (result == RegExpImpl::RE_FAILURE) return Heap::null_value();
3492  ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION);
3493  return Failure::Exception();
3494}
3495
3496
3497static Object* Runtime_NumberToRadixString(Arguments args) {
3498  NoHandleAllocation ha;
3499  ASSERT(args.length() == 2);
3500
3501  // Fast case where the result is a one character string.
3502  if (args[0]->IsSmi() && args[1]->IsSmi()) {
3503    int value = Smi::cast(args[0])->value();
3504    int radix = Smi::cast(args[1])->value();
3505    if (value >= 0 && value < radix) {
3506      RUNTIME_ASSERT(radix <= 36);
3507      // Character array used for conversion.
3508      static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
3509      return Heap::LookupSingleCharacterStringFromCode(kCharTable[value]);
3510    }
3511  }
3512
3513  // Slow case.
3514  CONVERT_DOUBLE_CHECKED(value, args[0]);
3515  if (isnan(value)) {
3516    return Heap::AllocateStringFromAscii(CStrVector("NaN"));
3517  }
3518  if (isinf(value)) {
3519    if (value < 0) {
3520      return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
3521    }
3522    return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
3523  }
3524  CONVERT_DOUBLE_CHECKED(radix_number, args[1]);
3525  int radix = FastD2I(radix_number);
3526  RUNTIME_ASSERT(2 <= radix && radix <= 36);
3527  char* str = DoubleToRadixCString(value, radix);
3528  Object* result = Heap::AllocateStringFromAscii(CStrVector(str));
3529  DeleteArray(str);
3530  return result;
3531}
3532
3533
3534static Object* Runtime_NumberToFixed(Arguments args) {
3535  NoHandleAllocation ha;
3536  ASSERT(args.length() == 2);
3537
3538  CONVERT_DOUBLE_CHECKED(value, args[0]);
3539  if (isnan(value)) {
3540    return Heap::AllocateStringFromAscii(CStrVector("NaN"));
3541  }
3542  if (isinf(value)) {
3543    if (value < 0) {
3544      return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
3545    }
3546    return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
3547  }
3548  CONVERT_DOUBLE_CHECKED(f_number, args[1]);
3549  int f = FastD2I(f_number);
3550  RUNTIME_ASSERT(f >= 0);
3551  char* str = DoubleToFixedCString(value, f);
3552  Object* res = Heap::AllocateStringFromAscii(CStrVector(str));
3553  DeleteArray(str);
3554  return res;
3555}
3556
3557
3558static Object* Runtime_NumberToExponential(Arguments args) {
3559  NoHandleAllocation ha;
3560  ASSERT(args.length() == 2);
3561
3562  CONVERT_DOUBLE_CHECKED(value, args[0]);
3563  if (isnan(value)) {
3564    return Heap::AllocateStringFromAscii(CStrVector("NaN"));
3565  }
3566  if (isinf(value)) {
3567    if (value < 0) {
3568      return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
3569    }
3570    return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
3571  }
3572  CONVERT_DOUBLE_CHECKED(f_number, args[1]);
3573  int f = FastD2I(f_number);
3574  RUNTIME_ASSERT(f >= -1 && f <= 20);
3575  char* str = DoubleToExponentialCString(value, f);
3576  Object* res = Heap::AllocateStringFromAscii(CStrVector(str));
3577  DeleteArray(str);
3578  return res;
3579}
3580
3581
3582static Object* Runtime_NumberToPrecision(Arguments args) {
3583  NoHandleAllocation ha;
3584  ASSERT(args.length() == 2);
3585
3586  CONVERT_DOUBLE_CHECKED(value, args[0]);
3587  if (isnan(value)) {
3588    return Heap::AllocateStringFromAscii(CStrVector("NaN"));
3589  }
3590  if (isinf(value)) {
3591    if (value < 0) {
3592      return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
3593    }
3594    return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
3595  }
3596  CONVERT_DOUBLE_CHECKED(f_number, args[1]);
3597  int f = FastD2I(f_number);
3598  RUNTIME_ASSERT(f >= 1 && f <= 21);
3599  char* str = DoubleToPrecisionCString(value, f);
3600  Object* res = Heap::AllocateStringFromAscii(CStrVector(str));
3601  DeleteArray(str);
3602  return res;
3603}
3604
3605
3606// Returns a single character string where first character equals
3607// string->Get(index).
3608static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
3609  if (index < static_cast<uint32_t>(string->length())) {
3610    string->TryFlatten();
3611    return LookupSingleCharacterStringFromCode(
3612        string->Get(index));
3613  }
3614  return Execution::CharAt(string, index);
3615}
3616
3617
3618Object* Runtime::GetElementOrCharAt(Handle<Object> object, uint32_t index) {
3619  // Handle [] indexing on Strings
3620  if (object->IsString()) {
3621    Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
3622    if (!result->IsUndefined()) return *result;
3623  }
3624
3625  // Handle [] indexing on String objects
3626  if (object->IsStringObjectWithCharacterAt(index)) {
3627    Handle<JSValue> js_value = Handle<JSValue>::cast(object);
3628    Handle<Object> result =
3629        GetCharAt(Handle<String>(String::cast(js_value->value())), index);
3630    if (!result->IsUndefined()) return *result;
3631  }
3632
3633  if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
3634    Handle<Object> prototype = GetPrototype(object);
3635    return prototype->GetElement(index);
3636  }
3637
3638  return GetElement(object, index);
3639}
3640
3641
3642Object* Runtime::GetElement(Handle<Object> object, uint32_t index) {
3643  return object->GetElement(index);
3644}
3645
3646
3647Object* Runtime::GetObjectProperty(Handle<Object> object, Handle<Object> key) {
3648  HandleScope scope;
3649
3650  if (object->IsUndefined() || object->IsNull()) {
3651    Handle<Object> args[2] = { key, object };
3652    Handle<Object> error =
3653        Factory::NewTypeError("non_object_property_load",
3654                              HandleVector(args, 2));
3655    return Top::Throw(*error);
3656  }
3657
3658  // Check if the given key is an array index.
3659  uint32_t index;
3660  if (Array::IndexFromObject(*key, &index)) {
3661    return GetElementOrCharAt(object, index);
3662  }
3663
3664  // Convert the key to a string - possibly by calling back into JavaScript.
3665  Handle<String> name;
3666  if (key->IsString()) {
3667    name = Handle<String>::cast(key);
3668  } else {
3669    bool has_pending_exception = false;
3670    Handle<Object> converted =
3671        Execution::ToString(key, &has_pending_exception);
3672    if (has_pending_exception) return Failure::Exception();
3673    name = Handle<String>::cast(converted);
3674  }
3675
3676  // Check if the name is trivially convertible to an index and get
3677  // the element if so.
3678  if (name->AsArrayIndex(&index)) {
3679    return GetElementOrCharAt(object, index);
3680  } else {
3681    PropertyAttributes attr;
3682    return object->GetProperty(*name, &attr);
3683  }
3684}
3685
3686
3687static Object* Runtime_GetProperty(Arguments args) {
3688  NoHandleAllocation ha;
3689  ASSERT(args.length() == 2);
3690
3691  Handle<Object> object = args.at<Object>(0);
3692  Handle<Object> key = args.at<Object>(1);
3693
3694  return Runtime::GetObjectProperty(object, key);
3695}
3696
3697
3698// KeyedStringGetProperty is called from KeyedLoadIC::GenerateGeneric.
3699static Object* Runtime_KeyedGetProperty(Arguments args) {
3700  NoHandleAllocation ha;
3701  ASSERT(args.length() == 2);
3702
3703  // Fast cases for getting named properties of the receiver JSObject
3704  // itself.
3705  //
3706  // The global proxy objects has to be excluded since LocalLookup on
3707  // the global proxy object can return a valid result even though the
3708  // global proxy object never has properties.  This is the case
3709  // because the global proxy object forwards everything to its hidden
3710  // prototype including local lookups.
3711  //
3712  // Additionally, we need to make sure that we do not cache results
3713  // for objects that require access checks.
3714  if (args[0]->IsJSObject() &&
3715      !args[0]->IsJSGlobalProxy() &&
3716      !args[0]->IsAccessCheckNeeded() &&
3717      args[1]->IsString()) {
3718    JSObject* receiver = JSObject::cast(args[0]);
3719    String* key = String::cast(args[1]);
3720    if (receiver->HasFastProperties()) {
3721      // Attempt to use lookup cache.
3722      Map* receiver_map = receiver->map();
3723      int offset = KeyedLookupCache::Lookup(receiver_map, key);
3724      if (offset != -1) {
3725        Object* value = receiver->FastPropertyAt(offset);
3726        return value->IsTheHole() ? Heap::undefined_value() : value;
3727      }
3728      // Lookup cache miss.  Perform lookup and update the cache if appropriate.
3729      LookupResult result;
3730      receiver->LocalLookup(key, &result);
3731      if (result.IsProperty() && result.type() == FIELD) {
3732        int offset = result.GetFieldIndex();
3733        KeyedLookupCache::Update(receiver_map, key, offset);
3734        return receiver->FastPropertyAt(offset);
3735      }
3736    } else {
3737      // Attempt dictionary lookup.
3738      StringDictionary* dictionary = receiver->property_dictionary();
3739      int entry = dictionary->FindEntry(key);
3740      if ((entry != StringDictionary::kNotFound) &&
3741          (dictionary->DetailsAt(entry).type() == NORMAL)) {
3742        Object* value = dictionary->ValueAt(entry);
3743        if (!receiver->IsGlobalObject()) return value;
3744        value = JSGlobalPropertyCell::cast(value)->value();
3745        if (!value->IsTheHole()) return value;
3746        // If value is the hole do the general lookup.
3747      }
3748    }
3749  } else if (args[0]->IsString() && args[1]->IsSmi()) {
3750    // Fast case for string indexing using [] with a smi index.
3751    HandleScope scope;
3752    Handle<String> str = args.at<String>(0);
3753    int index = Smi::cast(args[1])->value();
3754    Handle<Object> result = GetCharAt(str, index);
3755    return *result;
3756  }
3757
3758  // Fall back to GetObjectProperty.
3759  return Runtime::GetObjectProperty(args.at<Object>(0),
3760                                    args.at<Object>(1));
3761}
3762
3763
3764static Object* Runtime_DefineOrRedefineAccessorProperty(Arguments args) {
3765  ASSERT(args.length() == 5);
3766  HandleScope scope;
3767  CONVERT_ARG_CHECKED(JSObject, obj, 0);
3768  CONVERT_CHECKED(String, name, args[1]);
3769  CONVERT_CHECKED(Smi, flag_setter, args[2]);
3770  CONVERT_CHECKED(JSFunction, fun, args[3]);
3771  CONVERT_CHECKED(Smi, flag_attr, args[4]);
3772  int unchecked = flag_attr->value();
3773  RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
3774  RUNTIME_ASSERT(!obj->IsNull());
3775  LookupResult result;
3776  obj->LocalLookupRealNamedProperty(name, &result);
3777
3778  PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
3779  // If an existing property is either FIELD, NORMAL or CONSTANT_FUNCTION
3780  // delete it to avoid running into trouble in DefineAccessor, which
3781  // handles this incorrectly if the property is readonly (does nothing)
3782  if (result.IsProperty() &&
3783      (result.type() == FIELD || result.type() == NORMAL
3784       || result.type() == CONSTANT_FUNCTION)) {
3785    obj->DeleteProperty(name, JSObject::NORMAL_DELETION);
3786  }
3787  return obj->DefineAccessor(name, flag_setter->value() == 0, fun, attr);
3788}
3789
3790static Object* Runtime_DefineOrRedefineDataProperty(Arguments args) {
3791  ASSERT(args.length() == 4);
3792  HandleScope scope;
3793  CONVERT_ARG_CHECKED(JSObject, js_object, 0);
3794  CONVERT_ARG_CHECKED(String, name, 1);
3795  Handle<Object> obj_value = args.at<Object>(2);
3796
3797  CONVERT_CHECKED(Smi, flag, args[3]);
3798  int unchecked = flag->value();
3799  RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
3800
3801  LookupResult result;
3802  js_object->LocalLookupRealNamedProperty(*name, &result);
3803
3804  PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
3805
3806  // Take special care when attributes are different and there is already
3807  // a property. For simplicity we normalize the property which enables us
3808  // to not worry about changing the instance_descriptor and creating a new
3809  // map. The current version of SetObjectProperty does not handle attributes
3810  // correctly in the case where a property is a field and is reset with
3811  // new attributes.
3812  if (result.IsProperty() && attr != result.GetAttributes()) {
3813    // New attributes - normalize to avoid writing to instance descriptor
3814    js_object->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
3815    // Use IgnoreAttributes version since a readonly property may be
3816    // overridden and SetProperty does not allow this.
3817    return js_object->IgnoreAttributesAndSetLocalProperty(*name,
3818                                                          *obj_value,
3819                                                          attr);
3820  }
3821  return Runtime::SetObjectProperty(js_object, name, obj_value, attr);
3822}
3823
3824
3825Object* Runtime::SetObjectProperty(Handle<Object> object,
3826                                   Handle<Object> key,
3827                                   Handle<Object> value,
3828                                   PropertyAttributes attr) {
3829  HandleScope scope;
3830
3831  if (object->IsUndefined() || object->IsNull()) {
3832    Handle<Object> args[2] = { key, object };
3833    Handle<Object> error =
3834        Factory::NewTypeError("non_object_property_store",
3835                              HandleVector(args, 2));
3836    return Top::Throw(*error);
3837  }
3838
3839  // If the object isn't a JavaScript object, we ignore the store.
3840  if (!object->IsJSObject()) return *value;
3841
3842  Handle<JSObject> js_object = Handle<JSObject>::cast(object);
3843
3844  // Check if the given key is an array index.
3845  uint32_t index;
3846  if (Array::IndexFromObject(*key, &index)) {
3847    // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
3848    // of a string using [] notation.  We need to support this too in
3849    // JavaScript.
3850    // In the case of a String object we just need to redirect the assignment to
3851    // the underlying string if the index is in range.  Since the underlying
3852    // string does nothing with the assignment then we can ignore such
3853    // assignments.
3854    if (js_object->IsStringObjectWithCharacterAt(index)) {
3855      return *value;
3856    }
3857
3858    Handle<Object> result = SetElement(js_object, index, value);
3859    if (result.is_null()) return Failure::Exception();
3860    return *value;
3861  }
3862
3863  if (key->IsString()) {
3864    Handle<Object> result;
3865    if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
3866      result = SetElement(js_object, index, value);
3867    } else {
3868      Handle<String> key_string = Handle<String>::cast(key);
3869      key_string->TryFlatten();
3870      result = SetProperty(js_object, key_string, value, attr);
3871    }
3872    if (result.is_null()) return Failure::Exception();
3873    return *value;
3874  }
3875
3876  // Call-back into JavaScript to convert the key to a string.
3877  bool has_pending_exception = false;
3878  Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
3879  if (has_pending_exception) return Failure::Exception();
3880  Handle<String> name = Handle<String>::cast(converted);
3881
3882  if (name->AsArrayIndex(&index)) {
3883    return js_object->SetElement(index, *value);
3884  } else {
3885    return js_object->SetProperty(*name, *value, attr);
3886  }
3887}
3888
3889
3890Object* Runtime::ForceSetObjectProperty(Handle<JSObject> js_object,
3891                                        Handle<Object> key,
3892                                        Handle<Object> value,
3893                                        PropertyAttributes attr) {
3894  HandleScope scope;
3895
3896  // Check if the given key is an array index.
3897  uint32_t index;
3898  if (Array::IndexFromObject(*key, &index)) {
3899    // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
3900    // of a string using [] notation.  We need to support this too in
3901    // JavaScript.
3902    // In the case of a String object we just need to redirect the assignment to
3903    // the underlying string if the index is in range.  Since the underlying
3904    // string does nothing with the assignment then we can ignore such
3905    // assignments.
3906    if (js_object->IsStringObjectWithCharacterAt(index)) {
3907      return *value;
3908    }
3909
3910    return js_object->SetElement(index, *value);
3911  }
3912
3913  if (key->IsString()) {
3914    if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
3915      return js_object->SetElement(index, *value);
3916    } else {
3917      Handle<String> key_string = Handle<String>::cast(key);
3918      key_string->TryFlatten();
3919      return js_object->IgnoreAttributesAndSetLocalProperty(*key_string,
3920                                                            *value,
3921                                                            attr);
3922    }
3923  }
3924
3925  // Call-back into JavaScript to convert the key to a string.
3926  bool has_pending_exception = false;
3927  Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
3928  if (has_pending_exception) return Failure::Exception();
3929  Handle<String> name = Handle<String>::cast(converted);
3930
3931  if (name->AsArrayIndex(&index)) {
3932    return js_object->SetElement(index, *value);
3933  } else {
3934    return js_object->IgnoreAttributesAndSetLocalProperty(*name, *value, attr);
3935  }
3936}
3937
3938
3939Object* Runtime::ForceDeleteObjectProperty(Handle<JSObject> js_object,
3940                                           Handle<Object> key) {
3941  HandleScope scope;
3942
3943  // Check if the given key is an array index.
3944  uint32_t index;
3945  if (Array::IndexFromObject(*key, &index)) {
3946    // In Firefox/SpiderMonkey, Safari and Opera you can access the
3947    // characters of a string using [] notation.  In the case of a
3948    // String object we just need to redirect the deletion to the
3949    // underlying string if the index is in range.  Since the
3950    // underlying string does nothing with the deletion, we can ignore
3951    // such deletions.
3952    if (js_object->IsStringObjectWithCharacterAt(index)) {
3953      return Heap::true_value();
3954    }
3955
3956    return js_object->DeleteElement(index, JSObject::FORCE_DELETION);
3957  }
3958
3959  Handle<String> key_string;
3960  if (key->IsString()) {
3961    key_string = Handle<String>::cast(key);
3962  } else {
3963    // Call-back into JavaScript to convert the key to a string.
3964    bool has_pending_exception = false;
3965    Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
3966    if (has_pending_exception) return Failure::Exception();
3967    key_string = Handle<String>::cast(converted);
3968  }
3969
3970  key_string->TryFlatten();
3971  return js_object->DeleteProperty(*key_string, JSObject::FORCE_DELETION);
3972}
3973
3974
3975static Object* Runtime_SetProperty(Arguments args) {
3976  NoHandleAllocation ha;
3977  RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
3978
3979  Handle<Object> object = args.at<Object>(0);
3980  Handle<Object> key = args.at<Object>(1);
3981  Handle<Object> value = args.at<Object>(2);
3982
3983  // Compute attributes.
3984  PropertyAttributes attributes = NONE;
3985  if (args.length() == 4) {
3986    CONVERT_CHECKED(Smi, value_obj, args[3]);
3987    int unchecked_value = value_obj->value();
3988    // Only attribute bits should be set.
3989    RUNTIME_ASSERT(
3990        (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
3991    attributes = static_cast<PropertyAttributes>(unchecked_value);
3992  }
3993  return Runtime::SetObjectProperty(object, key, value, attributes);
3994}
3995
3996
3997// Set a local property, even if it is READ_ONLY.  If the property does not
3998// exist, it will be added with attributes NONE.
3999static Object* Runtime_IgnoreAttributesAndSetProperty(Arguments args) {
4000  NoHandleAllocation ha;
4001  RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
4002  CONVERT_CHECKED(JSObject, object, args[0]);
4003  CONVERT_CHECKED(String, name, args[1]);
4004  // Compute attributes.
4005  PropertyAttributes attributes = NONE;
4006  if (args.length() == 4) {
4007    CONVERT_CHECKED(Smi, value_obj, args[3]);
4008    int unchecked_value = value_obj->value();
4009    // Only attribute bits should be set.
4010    RUNTIME_ASSERT(
4011        (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4012    attributes = static_cast<PropertyAttributes>(unchecked_value);
4013  }
4014
4015  return object->
4016      IgnoreAttributesAndSetLocalProperty(name, args[2], attributes);
4017}
4018
4019
4020static Object* Runtime_DeleteProperty(Arguments args) {
4021  NoHandleAllocation ha;
4022  ASSERT(args.length() == 2);
4023
4024  CONVERT_CHECKED(JSObject, object, args[0]);
4025  CONVERT_CHECKED(String, key, args[1]);
4026  return object->DeleteProperty(key, JSObject::NORMAL_DELETION);
4027}
4028
4029
4030static Object* HasLocalPropertyImplementation(Handle<JSObject> object,
4031                                              Handle<String> key) {
4032  if (object->HasLocalProperty(*key)) return Heap::true_value();
4033  // Handle hidden prototypes.  If there's a hidden prototype above this thing
4034  // then we have to check it for properties, because they are supposed to
4035  // look like they are on this object.
4036  Handle<Object> proto(object->GetPrototype());
4037  if (proto->IsJSObject() &&
4038      Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) {
4039    return HasLocalPropertyImplementation(Handle<JSObject>::cast(proto), key);
4040  }
4041  return Heap::false_value();
4042}
4043
4044
4045static Object* Runtime_HasLocalProperty(Arguments args) {
4046  NoHandleAllocation ha;
4047  ASSERT(args.length() == 2);
4048  CONVERT_CHECKED(String, key, args[1]);
4049
4050  Object* obj = args[0];
4051  // Only JS objects can have properties.
4052  if (obj->IsJSObject()) {
4053    JSObject* object = JSObject::cast(obj);
4054    // Fast case - no interceptors.
4055    if (object->HasRealNamedProperty(key)) return Heap::true_value();
4056    // Slow case.  Either it's not there or we have an interceptor.  We should
4057    // have handles for this kind of deal.
4058    HandleScope scope;
4059    return HasLocalPropertyImplementation(Handle<JSObject>(object),
4060                                          Handle<String>(key));
4061  } else if (obj->IsString()) {
4062    // Well, there is one exception:  Handle [] on strings.
4063    uint32_t index;
4064    if (key->AsArrayIndex(&index)) {
4065      String* string = String::cast(obj);
4066      if (index < static_cast<uint32_t>(string->length()))
4067        return Heap::true_value();
4068    }
4069  }
4070  return Heap::false_value();
4071}
4072
4073
4074static Object* Runtime_HasProperty(Arguments args) {
4075  NoHandleAllocation na;
4076  ASSERT(args.length() == 2);
4077
4078  // Only JS objects can have properties.
4079  if (args[0]->IsJSObject()) {
4080    JSObject* object = JSObject::cast(args[0]);
4081    CONVERT_CHECKED(String, key, args[1]);
4082    if (object->HasProperty(key)) return Heap::true_value();
4083  }
4084  return Heap::false_value();
4085}
4086
4087
4088static Object* Runtime_HasElement(Arguments args) {
4089  NoHandleAllocation na;
4090  ASSERT(args.length() == 2);
4091
4092  // Only JS objects can have elements.
4093  if (args[0]->IsJSObject()) {
4094    JSObject* object = JSObject::cast(args[0]);
4095    CONVERT_CHECKED(Smi, index_obj, args[1]);
4096    uint32_t index = index_obj->value();
4097    if (object->HasElement(index)) return Heap::true_value();
4098  }
4099  return Heap::false_value();
4100}
4101
4102
4103static Object* Runtime_IsPropertyEnumerable(Arguments args) {
4104  NoHandleAllocation ha;
4105  ASSERT(args.length() == 2);
4106
4107  CONVERT_CHECKED(JSObject, object, args[0]);
4108  CONVERT_CHECKED(String, key, args[1]);
4109
4110  uint32_t index;
4111  if (key->AsArrayIndex(&index)) {
4112    return Heap::ToBoolean(object->HasElement(index));
4113  }
4114
4115  PropertyAttributes att = object->GetLocalPropertyAttribute(key);
4116  return Heap::ToBoolean(att != ABSENT && (att & DONT_ENUM) == 0);
4117}
4118
4119
4120static Object* Runtime_GetPropertyNames(Arguments args) {
4121  HandleScope scope;
4122  ASSERT(args.length() == 1);
4123  CONVERT_ARG_CHECKED(JSObject, object, 0);
4124  return *GetKeysFor(object);
4125}
4126
4127
4128// Returns either a FixedArray as Runtime_GetPropertyNames,
4129// or, if the given object has an enum cache that contains
4130// all enumerable properties of the object and its prototypes
4131// have none, the map of the object. This is used to speed up
4132// the check for deletions during a for-in.
4133static Object* Runtime_GetPropertyNamesFast(Arguments args) {
4134  ASSERT(args.length() == 1);
4135
4136  CONVERT_CHECKED(JSObject, raw_object, args[0]);
4137
4138  if (raw_object->IsSimpleEnum()) return raw_object->map();
4139
4140  HandleScope scope;
4141  Handle<JSObject> object(raw_object);
4142  Handle<FixedArray> content = GetKeysInFixedArrayFor(object,
4143                                                      INCLUDE_PROTOS);
4144
4145  // Test again, since cache may have been built by preceding call.
4146  if (object->IsSimpleEnum()) return object->map();
4147
4148  return *content;
4149}
4150
4151
4152// Find the length of the prototype chain that is to to handled as one. If a
4153// prototype object is hidden it is to be viewed as part of the the object it
4154// is prototype for.
4155static int LocalPrototypeChainLength(JSObject* obj) {
4156  int count = 1;
4157  Object* proto = obj->GetPrototype();
4158  while (proto->IsJSObject() &&
4159         JSObject::cast(proto)->map()->is_hidden_prototype()) {
4160    count++;
4161    proto = JSObject::cast(proto)->GetPrototype();
4162  }
4163  return count;
4164}
4165
4166
4167// Return the names of the local named properties.
4168// args[0]: object
4169static Object* Runtime_GetLocalPropertyNames(Arguments args) {
4170  HandleScope scope;
4171  ASSERT(args.length() == 1);
4172  if (!args[0]->IsJSObject()) {
4173    return Heap::undefined_value();
4174  }
4175  CONVERT_ARG_CHECKED(JSObject, obj, 0);
4176
4177  // Skip the global proxy as it has no properties and always delegates to the
4178  // real global object.
4179  if (obj->IsJSGlobalProxy()) {
4180    // Only collect names if access is permitted.
4181    if (obj->IsAccessCheckNeeded() &&
4182        !Top::MayNamedAccess(*obj, Heap::undefined_value(), v8::ACCESS_KEYS)) {
4183      Top::ReportFailedAccessCheck(*obj, v8::ACCESS_KEYS);
4184      return *Factory::NewJSArray(0);
4185    }
4186    obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
4187  }
4188
4189  // Find the number of objects making up this.
4190  int length = LocalPrototypeChainLength(*obj);
4191
4192  // Find the number of local properties for each of the objects.
4193  ScopedVector<int> local_property_count(length);
4194  int total_property_count = 0;
4195  Handle<JSObject> jsproto = obj;
4196  for (int i = 0; i < length; i++) {
4197    // Only collect names if access is permitted.
4198    if (jsproto->IsAccessCheckNeeded() &&
4199        !Top::MayNamedAccess(*jsproto,
4200                             Heap::undefined_value(),
4201                             v8::ACCESS_KEYS)) {
4202      Top::ReportFailedAccessCheck(*jsproto, v8::ACCESS_KEYS);
4203      return *Factory::NewJSArray(0);
4204    }
4205    int n;
4206    n = jsproto->NumberOfLocalProperties(static_cast<PropertyAttributes>(NONE));
4207    local_property_count[i] = n;
4208    total_property_count += n;
4209    if (i < length - 1) {
4210      jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
4211    }
4212  }
4213
4214  // Allocate an array with storage for all the property names.
4215  Handle<FixedArray> names = Factory::NewFixedArray(total_property_count);
4216
4217  // Get the property names.
4218  jsproto = obj;
4219  int proto_with_hidden_properties = 0;
4220  for (int i = 0; i < length; i++) {
4221    jsproto->GetLocalPropertyNames(*names,
4222                                   i == 0 ? 0 : local_property_count[i - 1]);
4223    if (!GetHiddenProperties(jsproto, false)->IsUndefined()) {
4224      proto_with_hidden_properties++;
4225    }
4226    if (i < length - 1) {
4227      jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
4228    }
4229  }
4230
4231  // Filter out name of hidden propeties object.
4232  if (proto_with_hidden_properties > 0) {
4233    Handle<FixedArray> old_names = names;
4234    names = Factory::NewFixedArray(
4235        names->length() - proto_with_hidden_properties);
4236    int dest_pos = 0;
4237    for (int i = 0; i < total_property_count; i++) {
4238      Object* name = old_names->get(i);
4239      if (name == Heap::hidden_symbol()) {
4240        continue;
4241      }
4242      names->set(dest_pos++, name);
4243    }
4244  }
4245
4246  return *Factory::NewJSArrayWithElements(names);
4247}
4248
4249
4250// Return the names of the local indexed properties.
4251// args[0]: object
4252static Object* Runtime_GetLocalElementNames(Arguments args) {
4253  HandleScope scope;
4254  ASSERT(args.length() == 1);
4255  if (!args[0]->IsJSObject()) {
4256    return Heap::undefined_value();
4257  }
4258  CONVERT_ARG_CHECKED(JSObject, obj, 0);
4259
4260  int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
4261  Handle<FixedArray> names = Factory::NewFixedArray(n);
4262  obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
4263  return *Factory::NewJSArrayWithElements(names);
4264}
4265
4266
4267// Return information on whether an object has a named or indexed interceptor.
4268// args[0]: object
4269static Object* Runtime_GetInterceptorInfo(Arguments args) {
4270  HandleScope scope;
4271  ASSERT(args.length() == 1);
4272  if (!args[0]->IsJSObject()) {
4273    return Smi::FromInt(0);
4274  }
4275  CONVERT_ARG_CHECKED(JSObject, obj, 0);
4276
4277  int result = 0;
4278  if (obj->HasNamedInterceptor()) result |= 2;
4279  if (obj->HasIndexedInterceptor()) result |= 1;
4280
4281  return Smi::FromInt(result);
4282}
4283
4284
4285// Return property names from named interceptor.
4286// args[0]: object
4287static Object* Runtime_GetNamedInterceptorPropertyNames(Arguments args) {
4288  HandleScope scope;
4289  ASSERT(args.length() == 1);
4290  CONVERT_ARG_CHECKED(JSObject, obj, 0);
4291
4292  if (obj->HasNamedInterceptor()) {
4293    v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
4294    if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
4295  }
4296  return Heap::undefined_value();
4297}
4298
4299
4300// Return element names from indexed interceptor.
4301// args[0]: object
4302static Object* Runtime_GetIndexedInterceptorElementNames(Arguments args) {
4303  HandleScope scope;
4304  ASSERT(args.length() == 1);
4305  CONVERT_ARG_CHECKED(JSObject, obj, 0);
4306
4307  if (obj->HasIndexedInterceptor()) {
4308    v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
4309    if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
4310  }
4311  return Heap::undefined_value();
4312}
4313
4314
4315static Object* Runtime_LocalKeys(Arguments args) {
4316  ASSERT_EQ(args.length(), 1);
4317  CONVERT_CHECKED(JSObject, raw_object, args[0]);
4318  HandleScope scope;
4319  Handle<JSObject> object(raw_object);
4320  Handle<FixedArray> contents = GetKeysInFixedArrayFor(object,
4321                                                       LOCAL_ONLY);
4322  // Some fast paths through GetKeysInFixedArrayFor reuse a cached
4323  // property array and since the result is mutable we have to create
4324  // a fresh clone on each invocation.
4325  int length = contents->length();
4326  Handle<FixedArray> copy = Factory::NewFixedArray(length);
4327  for (int i = 0; i < length; i++) {
4328    Object* entry = contents->get(i);
4329    if (entry->IsString()) {
4330      copy->set(i, entry);
4331    } else {
4332      ASSERT(entry->IsNumber());
4333      HandleScope scope;
4334      Handle<Object> entry_handle(entry);
4335      Handle<Object> entry_str = Factory::NumberToString(entry_handle);
4336      copy->set(i, *entry_str);
4337    }
4338  }
4339  return *Factory::NewJSArrayWithElements(copy);
4340}
4341
4342
4343static Object* Runtime_GetArgumentsProperty(Arguments args) {
4344  NoHandleAllocation ha;
4345  ASSERT(args.length() == 1);
4346
4347  // Compute the frame holding the arguments.
4348  JavaScriptFrameIterator it;
4349  it.AdvanceToArgumentsFrame();
4350  JavaScriptFrame* frame = it.frame();
4351
4352  // Get the actual number of provided arguments.
4353  const uint32_t n = frame->GetProvidedParametersCount();
4354
4355  // Try to convert the key to an index. If successful and within
4356  // index return the the argument from the frame.
4357  uint32_t index;
4358  if (Array::IndexFromObject(args[0], &index) && index < n) {
4359    return frame->GetParameter(index);
4360  }
4361
4362  // Convert the key to a string.
4363  HandleScope scope;
4364  bool exception = false;
4365  Handle<Object> converted =
4366      Execution::ToString(args.at<Object>(0), &exception);
4367  if (exception) return Failure::Exception();
4368  Handle<String> key = Handle<String>::cast(converted);
4369
4370  // Try to convert the string key into an array index.
4371  if (key->AsArrayIndex(&index)) {
4372    if (index < n) {
4373      return frame->GetParameter(index);
4374    } else {
4375      return Top::initial_object_prototype()->GetElement(index);
4376    }
4377  }
4378
4379  // Handle special arguments properties.
4380  if (key->Equals(Heap::length_symbol())) return Smi::FromInt(n);
4381  if (key->Equals(Heap::callee_symbol())) return frame->function();
4382
4383  // Lookup in the initial Object.prototype object.
4384  return Top::initial_object_prototype()->GetProperty(*key);
4385}
4386
4387
4388static Object* Runtime_ToFastProperties(Arguments args) {
4389  HandleScope scope;
4390
4391  ASSERT(args.length() == 1);
4392  Handle<Object> object = args.at<Object>(0);
4393  if (object->IsJSObject()) {
4394    Handle<JSObject> js_object = Handle<JSObject>::cast(object);
4395    if (!js_object->HasFastProperties() && !js_object->IsGlobalObject()) {
4396      js_object->TransformToFastProperties(0);
4397    }
4398  }
4399  return *object;
4400}
4401
4402
4403static Object* Runtime_ToSlowProperties(Arguments args) {
4404  HandleScope scope;
4405
4406  ASSERT(args.length() == 1);
4407  Handle<Object> object = args.at<Object>(0);
4408  if (object->IsJSObject()) {
4409    Handle<JSObject> js_object = Handle<JSObject>::cast(object);
4410    js_object->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
4411  }
4412  return *object;
4413}
4414
4415
4416static Object* Runtime_ToBool(Arguments args) {
4417  NoHandleAllocation ha;
4418  ASSERT(args.length() == 1);
4419
4420  return args[0]->ToBoolean();
4421}
4422
4423
4424// Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
4425// Possible optimizations: put the type string into the oddballs.
4426static Object* Runtime_Typeof(Arguments args) {
4427  NoHandleAllocation ha;
4428
4429  Object* obj = args[0];
4430  if (obj->IsNumber()) return Heap::number_symbol();
4431  HeapObject* heap_obj = HeapObject::cast(obj);
4432
4433  // typeof an undetectable object is 'undefined'
4434  if (heap_obj->map()->is_undetectable()) return Heap::undefined_symbol();
4435
4436  InstanceType instance_type = heap_obj->map()->instance_type();
4437  if (instance_type < FIRST_NONSTRING_TYPE) {
4438    return Heap::string_symbol();
4439  }
4440
4441  switch (instance_type) {
4442    case ODDBALL_TYPE:
4443      if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
4444        return Heap::boolean_symbol();
4445      }
4446      if (heap_obj->IsNull()) {
4447        return Heap::object_symbol();
4448      }
4449      ASSERT(heap_obj->IsUndefined());
4450      return Heap::undefined_symbol();
4451    case JS_FUNCTION_TYPE: case JS_REGEXP_TYPE:
4452      return Heap::function_symbol();
4453    default:
4454      // For any kind of object not handled above, the spec rule for
4455      // host objects gives that it is okay to return "object"
4456      return Heap::object_symbol();
4457  }
4458}
4459
4460
4461static bool AreDigits(const char*s, int from, int to) {
4462  for (int i = from; i < to; i++) {
4463    if (s[i] < '0' || s[i] > '9') return false;
4464  }
4465
4466  return true;
4467}
4468
4469
4470static int ParseDecimalInteger(const char*s, int from, int to) {
4471  ASSERT(to - from < 10);  // Overflow is not possible.
4472  ASSERT(from < to);
4473  int d = s[from] - '0';
4474
4475  for (int i = from + 1; i < to; i++) {
4476    d = 10 * d + (s[i] - '0');
4477  }
4478
4479  return d;
4480}
4481
4482
4483static Object* Runtime_StringToNumber(Arguments args) {
4484  NoHandleAllocation ha;
4485  ASSERT(args.length() == 1);
4486  CONVERT_CHECKED(String, subject, args[0]);
4487  subject->TryFlatten();
4488
4489  // Fast case: short integer or some sorts of junk values.
4490  int len = subject->length();
4491  if (subject->IsSeqAsciiString()) {
4492    if (len == 0) return Smi::FromInt(0);
4493
4494    char const* data = SeqAsciiString::cast(subject)->GetChars();
4495    bool minus = (data[0] == '-');
4496    int start_pos = (minus ? 1 : 0);
4497
4498    if (start_pos == len) {
4499      return Heap::nan_value();
4500    } else if (data[start_pos] > '9') {
4501      // Fast check for a junk value. A valid string may start from a
4502      // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit or
4503      // the 'I' character ('Infinity'). All of that have codes not greater than
4504      // '9' except 'I'.
4505      if (data[start_pos] != 'I') {
4506        return Heap::nan_value();
4507      }
4508    } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
4509      // The maximal/minimal smi has 10 digits. If the string has less digits we
4510      // know it will fit into the smi-data type.
4511      int d = ParseDecimalInteger(data, start_pos, len);
4512      if (minus) {
4513        if (d == 0) return Heap::minus_zero_value();
4514        d = -d;
4515      }
4516      return Smi::FromInt(d);
4517    }
4518  }
4519
4520  // Slower case.
4521  return Heap::NumberFromDouble(StringToDouble(subject, ALLOW_HEX));
4522}
4523
4524
4525static Object* Runtime_StringFromCharCodeArray(Arguments args) {
4526  NoHandleAllocation ha;
4527  ASSERT(args.length() == 1);
4528
4529  CONVERT_CHECKED(JSArray, codes, args[0]);
4530  int length = Smi::cast(codes->length())->value();
4531
4532  // Check if the string can be ASCII.
4533  int i;
4534  for (i = 0; i < length; i++) {
4535    Object* element = codes->GetElement(i);
4536    CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
4537    if ((chr & 0xffff) > String::kMaxAsciiCharCode)
4538      break;
4539  }
4540
4541  Object* object = NULL;
4542  if (i == length) {  // The string is ASCII.
4543    object = Heap::AllocateRawAsciiString(length);
4544  } else {  // The string is not ASCII.
4545    object = Heap::AllocateRawTwoByteString(length);
4546  }
4547
4548  if (object->IsFailure()) return object;
4549  String* result = String::cast(object);
4550  for (int i = 0; i < length; i++) {
4551    Object* element = codes->GetElement(i);
4552    CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
4553    result->Set(i, chr & 0xffff);
4554  }
4555  return result;
4556}
4557
4558
4559// kNotEscaped is generated by the following:
4560//
4561// #!/bin/perl
4562// for (my $i = 0; $i < 256; $i++) {
4563//   print "\n" if $i % 16 == 0;
4564//   my $c = chr($i);
4565//   my $escaped = 1;
4566//   $escaped = 0 if $c =~ m#[A-Za-z0-9@*_+./-]#;
4567//   print $escaped ? "0, " : "1, ";
4568// }
4569
4570
4571static bool IsNotEscaped(uint16_t character) {
4572  // Only for 8 bit characters, the rest are always escaped (in a different way)
4573  ASSERT(character < 256);
4574  static const char kNotEscaped[256] = {
4575    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4576    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4577    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
4578    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
4579    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
4580    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
4581    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
4582    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
4583    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4584    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4585    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4586    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4587    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4588    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4589    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4590    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4591  };
4592  return kNotEscaped[character] != 0;
4593}
4594
4595
4596static Object* Runtime_URIEscape(Arguments args) {
4597  const char hex_chars[] = "0123456789ABCDEF";
4598  NoHandleAllocation ha;
4599  ASSERT(args.length() == 1);
4600  CONVERT_CHECKED(String, source, args[0]);
4601
4602  source->TryFlatten();
4603
4604  int escaped_length = 0;
4605  int length = source->length();
4606  {
4607    Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
4608    buffer->Reset(source);
4609    while (buffer->has_more()) {
4610      uint16_t character = buffer->GetNext();
4611      if (character >= 256) {
4612        escaped_length += 6;
4613      } else if (IsNotEscaped(character)) {
4614        escaped_length++;
4615      } else {
4616        escaped_length += 3;
4617      }
4618      // We don't allow strings that are longer than a maximal length.
4619      ASSERT(String::kMaxLength < 0x7fffffff - 6);  // Cannot overflow.
4620      if (escaped_length > String::kMaxLength) {
4621        Top::context()->mark_out_of_memory();
4622        return Failure::OutOfMemoryException();
4623      }
4624    }
4625  }
4626  // No length change implies no change.  Return original string if no change.
4627  if (escaped_length == length) {
4628    return source;
4629  }
4630  Object* o = Heap::AllocateRawAsciiString(escaped_length);
4631  if (o->IsFailure()) return o;
4632  String* destination = String::cast(o);
4633  int dest_position = 0;
4634
4635  Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
4636  buffer->Rewind();
4637  while (buffer->has_more()) {
4638    uint16_t chr = buffer->GetNext();
4639    if (chr >= 256) {
4640      destination->Set(dest_position, '%');
4641      destination->Set(dest_position+1, 'u');
4642      destination->Set(dest_position+2, hex_chars[chr >> 12]);
4643      destination->Set(dest_position+3, hex_chars[(chr >> 8) & 0xf]);
4644      destination->Set(dest_position+4, hex_chars[(chr >> 4) & 0xf]);
4645      destination->Set(dest_position+5, hex_chars[chr & 0xf]);
4646      dest_position += 6;
4647    } else if (IsNotEscaped(chr)) {
4648      destination->Set(dest_position, chr);
4649      dest_position++;
4650    } else {
4651      destination->Set(dest_position, '%');
4652      destination->Set(dest_position+1, hex_chars[chr >> 4]);
4653      destination->Set(dest_position+2, hex_chars[chr & 0xf]);
4654      dest_position += 3;
4655    }
4656  }
4657  return destination;
4658}
4659
4660
4661static inline int TwoDigitHex(uint16_t character1, uint16_t character2) {
4662  static const signed char kHexValue['g'] = {
4663    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
4664    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
4665    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
4666    0,  1,  2,   3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
4667    -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
4668    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
4669    -1, 10, 11, 12, 13, 14, 15 };
4670
4671  if (character1 > 'f') return -1;
4672  int hi = kHexValue[character1];
4673  if (hi == -1) return -1;
4674  if (character2 > 'f') return -1;
4675  int lo = kHexValue[character2];
4676  if (lo == -1) return -1;
4677  return (hi << 4) + lo;
4678}
4679
4680
4681static inline int Unescape(String* source,
4682                           int i,
4683                           int length,
4684                           int* step) {
4685  uint16_t character = source->Get(i);
4686  int32_t hi = 0;
4687  int32_t lo = 0;
4688  if (character == '%' &&
4689      i <= length - 6 &&
4690      source->Get(i + 1) == 'u' &&
4691      (hi = TwoDigitHex(source->Get(i + 2),
4692                        source->Get(i + 3))) != -1 &&
4693      (lo = TwoDigitHex(source->Get(i + 4),
4694                        source->Get(i + 5))) != -1) {
4695    *step = 6;
4696    return (hi << 8) + lo;
4697  } else if (character == '%' &&
4698      i <= length - 3 &&
4699      (lo = TwoDigitHex(source->Get(i + 1),
4700                        source->Get(i + 2))) != -1) {
4701    *step = 3;
4702    return lo;
4703  } else {
4704    *step = 1;
4705    return character;
4706  }
4707}
4708
4709
4710static Object* Runtime_URIUnescape(Arguments args) {
4711  NoHandleAllocation ha;
4712  ASSERT(args.length() == 1);
4713  CONVERT_CHECKED(String, source, args[0]);
4714
4715  source->TryFlatten();
4716
4717  bool ascii = true;
4718  int length = source->length();
4719
4720  int unescaped_length = 0;
4721  for (int i = 0; i < length; unescaped_length++) {
4722    int step;
4723    if (Unescape(source, i, length, &step) > String::kMaxAsciiCharCode) {
4724      ascii = false;
4725    }
4726    i += step;
4727  }
4728
4729  // No length change implies no change.  Return original string if no change.
4730  if (unescaped_length == length)
4731    return source;
4732
4733  Object* o = ascii ?
4734              Heap::AllocateRawAsciiString(unescaped_length) :
4735              Heap::AllocateRawTwoByteString(unescaped_length);
4736  if (o->IsFailure()) return o;
4737  String* destination = String::cast(o);
4738
4739  int dest_position = 0;
4740  for (int i = 0; i < length; dest_position++) {
4741    int step;
4742    destination->Set(dest_position, Unescape(source, i, length, &step));
4743    i += step;
4744  }
4745  return destination;
4746}
4747
4748
4749static Object* Runtime_StringParseInt(Arguments args) {
4750  NoHandleAllocation ha;
4751
4752  CONVERT_CHECKED(String, s, args[0]);
4753  CONVERT_SMI_CHECKED(radix, args[1]);
4754
4755  s->TryFlatten();
4756
4757  RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
4758  double value = StringToInt(s, radix);
4759  return Heap::NumberFromDouble(value);
4760  return Heap::nan_value();
4761}
4762
4763
4764static Object* Runtime_StringParseFloat(Arguments args) {
4765  NoHandleAllocation ha;
4766  CONVERT_CHECKED(String, str, args[0]);
4767
4768  // ECMA-262 section 15.1.2.3, empty string is NaN
4769  double value = StringToDouble(str, ALLOW_TRAILING_JUNK, OS::nan_value());
4770
4771  // Create a number object from the value.
4772  return Heap::NumberFromDouble(value);
4773}
4774
4775
4776static unibrow::Mapping<unibrow::ToUppercase, 128> to_upper_mapping;
4777static unibrow::Mapping<unibrow::ToLowercase, 128> to_lower_mapping;
4778
4779
4780template <class Converter>
4781static Object* ConvertCaseHelper(String* s,
4782                                 int length,
4783                                 int input_string_length,
4784                                 unibrow::Mapping<Converter, 128>* mapping) {
4785  // We try this twice, once with the assumption that the result is no longer
4786  // than the input and, if that assumption breaks, again with the exact
4787  // length.  This may not be pretty, but it is nicer than what was here before
4788  // and I hereby claim my vaffel-is.
4789  //
4790  // Allocate the resulting string.
4791  //
4792  // NOTE: This assumes that the upper/lower case of an ascii
4793  // character is also ascii.  This is currently the case, but it
4794  // might break in the future if we implement more context and locale
4795  // dependent upper/lower conversions.
4796  Object* o = s->IsAsciiRepresentation()
4797      ? Heap::AllocateRawAsciiString(length)
4798      : Heap::AllocateRawTwoByteString(length);
4799  if (o->IsFailure()) return o;
4800  String* result = String::cast(o);
4801  bool has_changed_character = false;
4802
4803  // Convert all characters to upper case, assuming that they will fit
4804  // in the buffer
4805  Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
4806  buffer->Reset(s);
4807  unibrow::uchar chars[Converter::kMaxWidth];
4808  // We can assume that the string is not empty
4809  uc32 current = buffer->GetNext();
4810  for (int i = 0; i < length;) {
4811    bool has_next = buffer->has_more();
4812    uc32 next = has_next ? buffer->GetNext() : 0;
4813    int char_length = mapping->get(current, next, chars);
4814    if (char_length == 0) {
4815      // The case conversion of this character is the character itself.
4816      result->Set(i, current);
4817      i++;
4818    } else if (char_length == 1) {
4819      // Common case: converting the letter resulted in one character.
4820      ASSERT(static_cast<uc32>(chars[0]) != current);
4821      result->Set(i, chars[0]);
4822      has_changed_character = true;
4823      i++;
4824    } else if (length == input_string_length) {
4825      // We've assumed that the result would be as long as the
4826      // input but here is a character that converts to several
4827      // characters.  No matter, we calculate the exact length
4828      // of the result and try the whole thing again.
4829      //
4830      // Note that this leaves room for optimization.  We could just
4831      // memcpy what we already have to the result string.  Also,
4832      // the result string is the last object allocated we could
4833      // "realloc" it and probably, in the vast majority of cases,
4834      // extend the existing string to be able to hold the full
4835      // result.
4836      int next_length = 0;
4837      if (has_next) {
4838        next_length = mapping->get(next, 0, chars);
4839        if (next_length == 0) next_length = 1;
4840      }
4841      int current_length = i + char_length + next_length;
4842      while (buffer->has_more()) {
4843        current = buffer->GetNext();
4844        // NOTE: we use 0 as the next character here because, while
4845        // the next character may affect what a character converts to,
4846        // it does not in any case affect the length of what it convert
4847        // to.
4848        int char_length = mapping->get(current, 0, chars);
4849        if (char_length == 0) char_length = 1;
4850        current_length += char_length;
4851        if (current_length > Smi::kMaxValue) {
4852          Top::context()->mark_out_of_memory();
4853          return Failure::OutOfMemoryException();
4854        }
4855      }
4856      // Try again with the real length.
4857      return Smi::FromInt(current_length);
4858    } else {
4859      for (int j = 0; j < char_length; j++) {
4860        result->Set(i, chars[j]);
4861        i++;
4862      }
4863      has_changed_character = true;
4864    }
4865    current = next;
4866  }
4867  if (has_changed_character) {
4868    return result;
4869  } else {
4870    // If we didn't actually change anything in doing the conversion
4871    // we simple return the result and let the converted string
4872    // become garbage; there is no reason to keep two identical strings
4873    // alive.
4874    return s;
4875  }
4876}
4877
4878
4879static inline SeqAsciiString* TryGetSeqAsciiString(String* s) {
4880  if (!s->IsFlat() || !s->IsAsciiRepresentation()) return NULL;
4881  if (s->IsConsString()) {
4882    ASSERT(ConsString::cast(s)->second()->length() == 0);
4883    return SeqAsciiString::cast(ConsString::cast(s)->first());
4884  }
4885  return SeqAsciiString::cast(s);
4886}
4887
4888
4889namespace {
4890
4891struct ToLowerTraits {
4892  typedef unibrow::ToLowercase UnibrowConverter;
4893
4894  static bool ConvertAscii(char* dst, char* src, int length) {
4895    bool changed = false;
4896    for (int i = 0; i < length; ++i) {
4897      char c = src[i];
4898      if ('A' <= c && c <= 'Z') {
4899        c += ('a' - 'A');
4900        changed = true;
4901      }
4902      dst[i] = c;
4903    }
4904    return changed;
4905  }
4906};
4907
4908
4909struct ToUpperTraits {
4910  typedef unibrow::ToUppercase UnibrowConverter;
4911
4912  static bool ConvertAscii(char* dst, char* src, int length) {
4913    bool changed = false;
4914    for (int i = 0; i < length; ++i) {
4915      char c = src[i];
4916      if ('a' <= c && c <= 'z') {
4917        c -= ('a' - 'A');
4918        changed = true;
4919      }
4920      dst[i] = c;
4921    }
4922    return changed;
4923  }
4924};
4925
4926}  // namespace
4927
4928
4929template <typename ConvertTraits>
4930static Object* ConvertCase(
4931    Arguments args,
4932    unibrow::Mapping<typename ConvertTraits::UnibrowConverter, 128>* mapping) {
4933  NoHandleAllocation ha;
4934  CONVERT_CHECKED(String, s, args[0]);
4935  s->TryFlatten();
4936
4937  const int length = s->length();
4938  // Assume that the string is not empty; we need this assumption later
4939  if (length == 0) return s;
4940
4941  // Simpler handling of ascii strings.
4942  //
4943  // NOTE: This assumes that the upper/lower case of an ascii
4944  // character is also ascii.  This is currently the case, but it
4945  // might break in the future if we implement more context and locale
4946  // dependent upper/lower conversions.
4947  SeqAsciiString* seq_ascii = TryGetSeqAsciiString(s);
4948  if (seq_ascii != NULL) {
4949    Object* o = Heap::AllocateRawAsciiString(length);
4950    if (o->IsFailure()) return o;
4951    SeqAsciiString* result = SeqAsciiString::cast(o);
4952    bool has_changed_character = ConvertTraits::ConvertAscii(
4953        result->GetChars(), seq_ascii->GetChars(), length);
4954    return has_changed_character ? result : s;
4955  }
4956
4957  Object* answer = ConvertCaseHelper(s, length, length, mapping);
4958  if (answer->IsSmi()) {
4959    // Retry with correct length.
4960    answer = ConvertCaseHelper(s, Smi::cast(answer)->value(), length, mapping);
4961  }
4962  return answer;  // This may be a failure.
4963}
4964
4965
4966static Object* Runtime_StringToLowerCase(Arguments args) {
4967  return ConvertCase<ToLowerTraits>(args, &to_lower_mapping);
4968}
4969
4970
4971static Object* Runtime_StringToUpperCase(Arguments args) {
4972  return ConvertCase<ToUpperTraits>(args, &to_upper_mapping);
4973}
4974
4975
4976static inline bool IsTrimWhiteSpace(unibrow::uchar c) {
4977  return unibrow::WhiteSpace::Is(c) || c == 0x200b;
4978}
4979
4980
4981static Object* Runtime_StringTrim(Arguments args) {
4982  NoHandleAllocation ha;
4983  ASSERT(args.length() == 3);
4984
4985  CONVERT_CHECKED(String, s, args[0]);
4986  CONVERT_BOOLEAN_CHECKED(trimLeft, args[1]);
4987  CONVERT_BOOLEAN_CHECKED(trimRight, args[2]);
4988
4989  s->TryFlatten();
4990  int length = s->length();
4991
4992  int left = 0;
4993  if (trimLeft) {
4994    while (left < length && IsTrimWhiteSpace(s->Get(left))) {
4995      left++;
4996    }
4997  }
4998
4999  int right = length;
5000  if (trimRight) {
5001    while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) {
5002      right--;
5003    }
5004  }
5005  return s->SubString(left, right);
5006}
5007
5008
5009template <typename schar, typename pchar>
5010void FindStringIndices(Vector<const schar> subject,
5011                       Vector<const pchar> pattern,
5012                       ZoneList<int>* indices,
5013                       unsigned int limit) {
5014  ASSERT(limit > 0);
5015  // Collect indices of pattern in subject, and the end-of-string index.
5016  // Stop after finding at most limit values.
5017  StringSearchStrategy strategy =
5018      InitializeStringSearch(pattern, sizeof(schar) == 1);
5019  switch (strategy) {
5020    case SEARCH_FAIL: return;
5021    case SEARCH_SHORT: {
5022      int pattern_length = pattern.length();
5023      int index = 0;
5024      while (limit > 0) {
5025        index = SimpleIndexOf(subject, pattern, index);
5026        if (index < 0) return;
5027        indices->Add(index);
5028        index += pattern_length;
5029        limit--;
5030      }
5031      return;
5032    }
5033    case SEARCH_LONG: {
5034      int pattern_length = pattern.length();
5035      int index = 0;
5036      while (limit > 0) {
5037        index = ComplexIndexOf(subject, pattern, index);
5038        if (index < 0) return;
5039        indices->Add(index);
5040        index += pattern_length;
5041        limit--;
5042      }
5043      return;
5044    }
5045    default:
5046      UNREACHABLE();
5047      return;
5048  }
5049}
5050
5051template <typename schar>
5052inline void FindCharIndices(Vector<const schar> subject,
5053                            const schar pattern_char,
5054                            ZoneList<int>* indices,
5055                            unsigned int limit) {
5056  // Collect indices of pattern_char in subject, and the end-of-string index.
5057  // Stop after finding at most limit values.
5058  int index = 0;
5059  while (limit > 0) {
5060    index = SingleCharIndexOf(subject, pattern_char, index);
5061    if (index < 0) return;
5062    indices->Add(index);
5063    index++;
5064    limit--;
5065  }
5066}
5067
5068
5069static Object* Runtime_StringSplit(Arguments args) {
5070  ASSERT(args.length() == 3);
5071  HandleScope handle_scope;
5072  CONVERT_ARG_CHECKED(String, subject, 0);
5073  CONVERT_ARG_CHECKED(String, pattern, 1);
5074  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]);
5075
5076  int subject_length = subject->length();
5077  int pattern_length = pattern->length();
5078  RUNTIME_ASSERT(pattern_length > 0);
5079
5080  // The limit can be very large (0xffffffffu), but since the pattern
5081  // isn't empty, we can never create more parts than ~half the length
5082  // of the subject.
5083
5084  if (!subject->IsFlat()) FlattenString(subject);
5085
5086  static const int kMaxInitialListCapacity = 16;
5087
5088  ZoneScope scope(DELETE_ON_EXIT);
5089
5090  // Find (up to limit) indices of separator and end-of-string in subject
5091  int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit);
5092  ZoneList<int> indices(initial_capacity);
5093  if (pattern_length == 1) {
5094    // Special case, go directly to fast single-character split.
5095    AssertNoAllocation nogc;
5096    uc16 pattern_char = pattern->Get(0);
5097    if (subject->IsTwoByteRepresentation()) {
5098      FindCharIndices(subject->ToUC16Vector(), pattern_char,
5099                      &indices,
5100                      limit);
5101    } else if (pattern_char <= String::kMaxAsciiCharCode) {
5102      FindCharIndices(subject->ToAsciiVector(),
5103                      static_cast<char>(pattern_char),
5104                      &indices,
5105                      limit);
5106    }
5107  } else {
5108    if (!pattern->IsFlat()) FlattenString(pattern);
5109    AssertNoAllocation nogc;
5110    if (subject->IsAsciiRepresentation()) {
5111      Vector<const char> subject_vector = subject->ToAsciiVector();
5112      if (pattern->IsAsciiRepresentation()) {
5113        FindStringIndices(subject_vector,
5114                          pattern->ToAsciiVector(),
5115                          &indices,
5116                          limit);
5117      } else {
5118        FindStringIndices(subject_vector,
5119                          pattern->ToUC16Vector(),
5120                          &indices,
5121                          limit);
5122      }
5123    } else {
5124      Vector<const uc16> subject_vector = subject->ToUC16Vector();
5125      if (pattern->IsAsciiRepresentation()) {
5126        FindStringIndices(subject_vector,
5127                          pattern->ToAsciiVector(),
5128                          &indices,
5129                          limit);
5130      } else {
5131        FindStringIndices(subject_vector,
5132                          pattern->ToUC16Vector(),
5133                          &indices,
5134                          limit);
5135      }
5136    }
5137  }
5138  if (static_cast<uint32_t>(indices.length()) < limit) {
5139    indices.Add(subject_length);
5140  }
5141  // The list indices now contains the end of each part to create.
5142
5143
5144  // Create JSArray of substrings separated by separator.
5145  int part_count = indices.length();
5146
5147  Handle<JSArray> result = Factory::NewJSArray(part_count);
5148  result->set_length(Smi::FromInt(part_count));
5149
5150  ASSERT(result->HasFastElements());
5151
5152  if (part_count == 1 && indices.at(0) == subject_length) {
5153    FixedArray::cast(result->elements())->set(0, *subject);
5154    return *result;
5155  }
5156
5157  Handle<FixedArray> elements(FixedArray::cast(result->elements()));
5158  int part_start = 0;
5159  for (int i = 0; i < part_count; i++) {
5160    HandleScope local_loop_handle;
5161    int part_end = indices.at(i);
5162    Handle<String> substring =
5163        Factory::NewSubString(subject, part_start, part_end);
5164    elements->set(i, *substring);
5165    part_start = part_end + pattern_length;
5166  }
5167
5168  return *result;
5169}
5170
5171
5172// Copies ascii characters to the given fixed array looking up
5173// one-char strings in the cache. Gives up on the first char that is
5174// not in the cache and fills the remainder with smi zeros. Returns
5175// the length of the successfully copied prefix.
5176static int CopyCachedAsciiCharsToArray(const char* chars,
5177                                       FixedArray* elements,
5178                                       int length) {
5179  AssertNoAllocation nogc;
5180  FixedArray* ascii_cache = Heap::single_character_string_cache();
5181  Object* undefined = Heap::undefined_value();
5182  int i;
5183  for (i = 0; i < length; ++i) {
5184    Object* value = ascii_cache->get(chars[i]);
5185    if (value == undefined) break;
5186    ASSERT(!Heap::InNewSpace(value));
5187    elements->set(i, value, SKIP_WRITE_BARRIER);
5188  }
5189  if (i < length) {
5190    ASSERT(Smi::FromInt(0) == 0);
5191    memset(elements->data_start() + i, 0, kPointerSize * (length - i));
5192  }
5193#ifdef DEBUG
5194  for (int j = 0; j < length; ++j) {
5195    Object* element = elements->get(j);
5196    ASSERT(element == Smi::FromInt(0) ||
5197           (element->IsString() && String::cast(element)->LooksValid()));
5198  }
5199#endif
5200  return i;
5201}
5202
5203
5204// Converts a String to JSArray.
5205// For example, "foo" => ["f", "o", "o"].
5206static Object* Runtime_StringToArray(Arguments args) {
5207  HandleScope scope;
5208  ASSERT(args.length() == 1);
5209  CONVERT_ARG_CHECKED(String, s, 0);
5210
5211  s->TryFlatten();
5212  const int length = s->length();
5213
5214  Handle<FixedArray> elements;
5215  if (s->IsFlat() && s->IsAsciiRepresentation()) {
5216    Object* obj = Heap::AllocateUninitializedFixedArray(length);
5217    if (obj->IsFailure()) return obj;
5218    elements = Handle<FixedArray>(FixedArray::cast(obj));
5219
5220    Vector<const char> chars = s->ToAsciiVector();
5221    // Note, this will initialize all elements (not only the prefix)
5222    // to prevent GC from seeing partially initialized array.
5223    int num_copied_from_cache = CopyCachedAsciiCharsToArray(chars.start(),
5224                                                            *elements,
5225                                                            length);
5226
5227    for (int i = num_copied_from_cache; i < length; ++i) {
5228      elements->set(i, *LookupSingleCharacterStringFromCode(chars[i]));
5229    }
5230  } else {
5231    elements = Factory::NewFixedArray(length);
5232    for (int i = 0; i < length; ++i) {
5233      elements->set(i, *LookupSingleCharacterStringFromCode(s->Get(i)));
5234    }
5235  }
5236
5237#ifdef DEBUG
5238  for (int i = 0; i < length; ++i) {
5239    ASSERT(String::cast(elements->get(i))->length() == 1);
5240  }
5241#endif
5242
5243  return *Factory::NewJSArrayWithElements(elements);
5244}
5245
5246
5247bool Runtime::IsUpperCaseChar(uint16_t ch) {
5248  unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth];
5249  int char_length = to_upper_mapping.get(ch, 0, chars);
5250  return char_length == 0;
5251}
5252
5253
5254static Object* Runtime_NumberToString(Arguments args) {
5255  NoHandleAllocation ha;
5256  ASSERT(args.length() == 1);
5257
5258  Object* number = args[0];
5259  RUNTIME_ASSERT(number->IsNumber());
5260
5261  return Heap::NumberToString(number);
5262}
5263
5264
5265static Object* Runtime_NumberToStringSkipCache(Arguments args) {
5266  NoHandleAllocation ha;
5267  ASSERT(args.length() == 1);
5268
5269  Object* number = args[0];
5270  RUNTIME_ASSERT(number->IsNumber());
5271
5272  return Heap::NumberToString(number, false);
5273}
5274
5275
5276static Object* Runtime_NumberToInteger(Arguments args) {
5277  NoHandleAllocation ha;
5278  ASSERT(args.length() == 1);
5279
5280  CONVERT_DOUBLE_CHECKED(number, args[0]);
5281
5282  // We do not include 0 so that we don't have to treat +0 / -0 cases.
5283  if (number > 0 && number <= Smi::kMaxValue) {
5284    return Smi::FromInt(static_cast<int>(number));
5285  }
5286  return Heap::NumberFromDouble(DoubleToInteger(number));
5287}
5288
5289
5290static Object* Runtime_NumberToJSUint32(Arguments args) {
5291  NoHandleAllocation ha;
5292  ASSERT(args.length() == 1);
5293
5294  CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]);
5295  return Heap::NumberFromUint32(number);
5296}
5297
5298
5299static Object* Runtime_NumberToJSInt32(Arguments args) {
5300  NoHandleAllocation ha;
5301  ASSERT(args.length() == 1);
5302
5303  CONVERT_DOUBLE_CHECKED(number, args[0]);
5304
5305  // We do not include 0 so that we don't have to treat +0 / -0 cases.
5306  if (number > 0 && number <= Smi::kMaxValue) {
5307    return Smi::FromInt(static_cast<int>(number));
5308  }
5309  return Heap::NumberFromInt32(DoubleToInt32(number));
5310}
5311
5312
5313// Converts a Number to a Smi, if possible. Returns NaN if the number is not
5314// a small integer.
5315static Object* Runtime_NumberToSmi(Arguments args) {
5316  NoHandleAllocation ha;
5317  ASSERT(args.length() == 1);
5318
5319  Object* obj = args[0];
5320  if (obj->IsSmi()) {
5321    return obj;
5322  }
5323  if (obj->IsHeapNumber()) {
5324    double value = HeapNumber::cast(obj)->value();
5325    int int_value = FastD2I(value);
5326    if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
5327      return Smi::FromInt(int_value);
5328    }
5329  }
5330  return Heap::nan_value();
5331}
5332
5333
5334static Object* Runtime_NumberAdd(Arguments args) {
5335  NoHandleAllocation ha;
5336  ASSERT(args.length() == 2);
5337
5338  CONVERT_DOUBLE_CHECKED(x, args[0]);
5339  CONVERT_DOUBLE_CHECKED(y, args[1]);
5340  return Heap::AllocateHeapNumber(x + y);
5341}
5342
5343
5344static Object* Runtime_NumberSub(Arguments args) {
5345  NoHandleAllocation ha;
5346  ASSERT(args.length() == 2);
5347
5348  CONVERT_DOUBLE_CHECKED(x, args[0]);
5349  CONVERT_DOUBLE_CHECKED(y, args[1]);
5350  return Heap::AllocateHeapNumber(x - y);
5351}
5352
5353
5354static Object* Runtime_NumberMul(Arguments args) {
5355  NoHandleAllocation ha;
5356  ASSERT(args.length() == 2);
5357
5358  CONVERT_DOUBLE_CHECKED(x, args[0]);
5359  CONVERT_DOUBLE_CHECKED(y, args[1]);
5360  return Heap::AllocateHeapNumber(x * y);
5361}
5362
5363
5364static Object* Runtime_NumberUnaryMinus(Arguments args) {
5365  NoHandleAllocation ha;
5366  ASSERT(args.length() == 1);
5367
5368  CONVERT_DOUBLE_CHECKED(x, args[0]);
5369  return Heap::AllocateHeapNumber(-x);
5370}
5371
5372
5373static Object* Runtime_NumberDiv(Arguments args) {
5374  NoHandleAllocation ha;
5375  ASSERT(args.length() == 2);
5376
5377  CONVERT_DOUBLE_CHECKED(x, args[0]);
5378  CONVERT_DOUBLE_CHECKED(y, args[1]);
5379  return Heap::NumberFromDouble(x / y);
5380}
5381
5382
5383static Object* Runtime_NumberMod(Arguments args) {
5384  NoHandleAllocation ha;
5385  ASSERT(args.length() == 2);
5386
5387  CONVERT_DOUBLE_CHECKED(x, args[0]);
5388  CONVERT_DOUBLE_CHECKED(y, args[1]);
5389
5390  x = modulo(x, y);
5391  // NumberFromDouble may return a Smi instead of a Number object
5392  return Heap::NumberFromDouble(x);
5393}
5394
5395
5396static Object* Runtime_StringAdd(Arguments args) {
5397  NoHandleAllocation ha;
5398  ASSERT(args.length() == 2);
5399  CONVERT_CHECKED(String, str1, args[0]);
5400  CONVERT_CHECKED(String, str2, args[1]);
5401  Counters::string_add_runtime.Increment();
5402  return Heap::AllocateConsString(str1, str2);
5403}
5404
5405
5406template <typename sinkchar>
5407static inline void StringBuilderConcatHelper(String* special,
5408                                             sinkchar* sink,
5409                                             FixedArray* fixed_array,
5410                                             int array_length) {
5411  int position = 0;
5412  for (int i = 0; i < array_length; i++) {
5413    Object* element = fixed_array->get(i);
5414    if (element->IsSmi()) {
5415      // Smi encoding of position and length.
5416      int encoded_slice = Smi::cast(element)->value();
5417      int pos;
5418      int len;
5419      if (encoded_slice > 0) {
5420        // Position and length encoded in one smi.
5421        pos = StringBuilderSubstringPosition::decode(encoded_slice);
5422        len = StringBuilderSubstringLength::decode(encoded_slice);
5423      } else {
5424        // Position and length encoded in two smis.
5425        Object* obj = fixed_array->get(++i);
5426        ASSERT(obj->IsSmi());
5427        pos = Smi::cast(obj)->value();
5428        len = -encoded_slice;
5429      }
5430      String::WriteToFlat(special,
5431                          sink + position,
5432                          pos,
5433                          pos + len);
5434      position += len;
5435    } else {
5436      String* string = String::cast(element);
5437      int element_length = string->length();
5438      String::WriteToFlat(string, sink + position, 0, element_length);
5439      position += element_length;
5440    }
5441  }
5442}
5443
5444
5445static Object* Runtime_StringBuilderConcat(Arguments args) {
5446  NoHandleAllocation ha;
5447  ASSERT(args.length() == 3);
5448  CONVERT_CHECKED(JSArray, array, args[0]);
5449  if (!args[1]->IsSmi()) {
5450    Top::context()->mark_out_of_memory();
5451    return Failure::OutOfMemoryException();
5452  }
5453  int array_length = Smi::cast(args[1])->value();
5454  CONVERT_CHECKED(String, special, args[2]);
5455
5456  // This assumption is used by the slice encoding in one or two smis.
5457  ASSERT(Smi::kMaxValue >= String::kMaxLength);
5458
5459  int special_length = special->length();
5460  if (!array->HasFastElements()) {
5461    return Top::Throw(Heap::illegal_argument_symbol());
5462  }
5463  FixedArray* fixed_array = FixedArray::cast(array->elements());
5464  if (fixed_array->length() < array_length) {
5465    array_length = fixed_array->length();
5466  }
5467
5468  if (array_length == 0) {
5469    return Heap::empty_string();
5470  } else if (array_length == 1) {
5471    Object* first = fixed_array->get(0);
5472    if (first->IsString()) return first;
5473  }
5474
5475  bool ascii = special->IsAsciiRepresentation();
5476  int position = 0;
5477  for (int i = 0; i < array_length; i++) {
5478    int increment = 0;
5479    Object* elt = fixed_array->get(i);
5480    if (elt->IsSmi()) {
5481      // Smi encoding of position and length.
5482      int smi_value = Smi::cast(elt)->value();
5483      int pos;
5484      int len;
5485      if (smi_value > 0) {
5486        // Position and length encoded in one smi.
5487        pos = StringBuilderSubstringPosition::decode(smi_value);
5488        len = StringBuilderSubstringLength::decode(smi_value);
5489      } else {
5490        // Position and length encoded in two smis.
5491        len = -smi_value;
5492        // Get the position and check that it is a positive smi.
5493        i++;
5494        if (i >= array_length) {
5495          return Top::Throw(Heap::illegal_argument_symbol());
5496        }
5497        Object* next_smi = fixed_array->get(i);
5498        if (!next_smi->IsSmi()) {
5499          return Top::Throw(Heap::illegal_argument_symbol());
5500        }
5501        pos = Smi::cast(next_smi)->value();
5502        if (pos < 0) {
5503          return Top::Throw(Heap::illegal_argument_symbol());
5504        }
5505      }
5506      ASSERT(pos >= 0);
5507      ASSERT(len >= 0);
5508      if (pos > special_length || len > special_length - pos) {
5509        return Top::Throw(Heap::illegal_argument_symbol());
5510      }
5511      increment = len;
5512    } else if (elt->IsString()) {
5513      String* element = String::cast(elt);
5514      int element_length = element->length();
5515      increment = element_length;
5516      if (ascii && !element->IsAsciiRepresentation()) {
5517        ascii = false;
5518      }
5519    } else {
5520      return Top::Throw(Heap::illegal_argument_symbol());
5521    }
5522    if (increment > String::kMaxLength - position) {
5523      Top::context()->mark_out_of_memory();
5524      return Failure::OutOfMemoryException();
5525    }
5526    position += increment;
5527  }
5528
5529  int length = position;
5530  Object* object;
5531
5532  if (ascii) {
5533    object = Heap::AllocateRawAsciiString(length);
5534    if (object->IsFailure()) return object;
5535    SeqAsciiString* answer = SeqAsciiString::cast(object);
5536    StringBuilderConcatHelper(special,
5537                              answer->GetChars(),
5538                              fixed_array,
5539                              array_length);
5540    return answer;
5541  } else {
5542    object = Heap::AllocateRawTwoByteString(length);
5543    if (object->IsFailure()) return object;
5544    SeqTwoByteString* answer = SeqTwoByteString::cast(object);
5545    StringBuilderConcatHelper(special,
5546                              answer->GetChars(),
5547                              fixed_array,
5548                              array_length);
5549    return answer;
5550  }
5551}
5552
5553
5554static Object* Runtime_NumberOr(Arguments args) {
5555  NoHandleAllocation ha;
5556  ASSERT(args.length() == 2);
5557
5558  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
5559  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
5560  return Heap::NumberFromInt32(x | y);
5561}
5562
5563
5564static Object* Runtime_NumberAnd(Arguments args) {
5565  NoHandleAllocation ha;
5566  ASSERT(args.length() == 2);
5567
5568  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
5569  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
5570  return Heap::NumberFromInt32(x & y);
5571}
5572
5573
5574static Object* Runtime_NumberXor(Arguments args) {
5575  NoHandleAllocation ha;
5576  ASSERT(args.length() == 2);
5577
5578  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
5579  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
5580  return Heap::NumberFromInt32(x ^ y);
5581}
5582
5583
5584static Object* Runtime_NumberNot(Arguments args) {
5585  NoHandleAllocation ha;
5586  ASSERT(args.length() == 1);
5587
5588  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
5589  return Heap::NumberFromInt32(~x);
5590}
5591
5592
5593static Object* Runtime_NumberShl(Arguments args) {
5594  NoHandleAllocation ha;
5595  ASSERT(args.length() == 2);
5596
5597  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
5598  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
5599  return Heap::NumberFromInt32(x << (y & 0x1f));
5600}
5601
5602
5603static Object* Runtime_NumberShr(Arguments args) {
5604  NoHandleAllocation ha;
5605  ASSERT(args.length() == 2);
5606
5607  CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
5608  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
5609  return Heap::NumberFromUint32(x >> (y & 0x1f));
5610}
5611
5612
5613static Object* Runtime_NumberSar(Arguments args) {
5614  NoHandleAllocation ha;
5615  ASSERT(args.length() == 2);
5616
5617  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
5618  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
5619  return Heap::NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f));
5620}
5621
5622
5623static Object* Runtime_NumberEquals(Arguments args) {
5624  NoHandleAllocation ha;
5625  ASSERT(args.length() == 2);
5626
5627  CONVERT_DOUBLE_CHECKED(x, args[0]);
5628  CONVERT_DOUBLE_CHECKED(y, args[1]);
5629  if (isnan(x)) return Smi::FromInt(NOT_EQUAL);
5630  if (isnan(y)) return Smi::FromInt(NOT_EQUAL);
5631  if (x == y) return Smi::FromInt(EQUAL);
5632  Object* result;
5633  if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
5634    result = Smi::FromInt(EQUAL);
5635  } else {
5636    result = Smi::FromInt(NOT_EQUAL);
5637  }
5638  return result;
5639}
5640
5641
5642static Object* Runtime_StringEquals(Arguments args) {
5643  NoHandleAllocation ha;
5644  ASSERT(args.length() == 2);
5645
5646  CONVERT_CHECKED(String, x, args[0]);
5647  CONVERT_CHECKED(String, y, args[1]);
5648
5649  bool not_equal = !x->Equals(y);
5650  // This is slightly convoluted because the value that signifies
5651  // equality is 0 and inequality is 1 so we have to negate the result
5652  // from String::Equals.
5653  ASSERT(not_equal == 0 || not_equal == 1);
5654  STATIC_CHECK(EQUAL == 0);
5655  STATIC_CHECK(NOT_EQUAL == 1);
5656  return Smi::FromInt(not_equal);
5657}
5658
5659
5660static Object* Runtime_NumberCompare(Arguments args) {
5661  NoHandleAllocation ha;
5662  ASSERT(args.length() == 3);
5663
5664  CONVERT_DOUBLE_CHECKED(x, args[0]);
5665  CONVERT_DOUBLE_CHECKED(y, args[1]);
5666  if (isnan(x) || isnan(y)) return args[2];
5667  if (x == y) return Smi::FromInt(EQUAL);
5668  if (isless(x, y)) return Smi::FromInt(LESS);
5669  return Smi::FromInt(GREATER);
5670}
5671
5672
5673// Compare two Smis as if they were converted to strings and then
5674// compared lexicographically.
5675static Object* Runtime_SmiLexicographicCompare(Arguments args) {
5676  NoHandleAllocation ha;
5677  ASSERT(args.length() == 2);
5678
5679  // Arrays for the individual characters of the two Smis.  Smis are
5680  // 31 bit integers and 10 decimal digits are therefore enough.
5681  static int x_elms[10];
5682  static int y_elms[10];
5683
5684  // Extract the integer values from the Smis.
5685  CONVERT_CHECKED(Smi, x, args[0]);
5686  CONVERT_CHECKED(Smi, y, args[1]);
5687  int x_value = x->value();
5688  int y_value = y->value();
5689
5690  // If the integers are equal so are the string representations.
5691  if (x_value == y_value) return Smi::FromInt(EQUAL);
5692
5693  // If one of the integers are zero the normal integer order is the
5694  // same as the lexicographic order of the string representations.
5695  if (x_value == 0 || y_value == 0) return Smi::FromInt(x_value - y_value);
5696
5697  // If only one of the integers is negative the negative number is
5698  // smallest because the char code of '-' is less than the char code
5699  // of any digit.  Otherwise, we make both values positive.
5700  if (x_value < 0 || y_value < 0) {
5701    if (y_value >= 0) return Smi::FromInt(LESS);
5702    if (x_value >= 0) return Smi::FromInt(GREATER);
5703    x_value = -x_value;
5704    y_value = -y_value;
5705  }
5706
5707  // Convert the integers to arrays of their decimal digits.
5708  int x_index = 0;
5709  int y_index = 0;
5710  while (x_value > 0) {
5711    x_elms[x_index++] = x_value % 10;
5712    x_value /= 10;
5713  }
5714  while (y_value > 0) {
5715    y_elms[y_index++] = y_value % 10;
5716    y_value /= 10;
5717  }
5718
5719  // Loop through the arrays of decimal digits finding the first place
5720  // where they differ.
5721  while (--x_index >= 0 && --y_index >= 0) {
5722    int diff = x_elms[x_index] - y_elms[y_index];
5723    if (diff != 0) return Smi::FromInt(diff);
5724  }
5725
5726  // If one array is a suffix of the other array, the longest array is
5727  // the representation of the largest of the Smis in the
5728  // lexicographic ordering.
5729  return Smi::FromInt(x_index - y_index);
5730}
5731
5732
5733static Object* StringInputBufferCompare(String* x, String* y) {
5734  static StringInputBuffer bufx;
5735  static StringInputBuffer bufy;
5736  bufx.Reset(x);
5737  bufy.Reset(y);
5738  while (bufx.has_more() && bufy.has_more()) {
5739    int d = bufx.GetNext() - bufy.GetNext();
5740    if (d < 0) return Smi::FromInt(LESS);
5741    else if (d > 0) return Smi::FromInt(GREATER);
5742  }
5743
5744  // x is (non-trivial) prefix of y:
5745  if (bufy.has_more()) return Smi::FromInt(LESS);
5746  // y is prefix of x:
5747  return Smi::FromInt(bufx.has_more() ? GREATER : EQUAL);
5748}
5749
5750
5751static Object* FlatStringCompare(String* x, String* y) {
5752  ASSERT(x->IsFlat());
5753  ASSERT(y->IsFlat());
5754  Object* equal_prefix_result = Smi::FromInt(EQUAL);
5755  int prefix_length = x->length();
5756  if (y->length() < prefix_length) {
5757    prefix_length = y->length();
5758    equal_prefix_result = Smi::FromInt(GREATER);
5759  } else if (y->length() > prefix_length) {
5760    equal_prefix_result = Smi::FromInt(LESS);
5761  }
5762  int r;
5763  if (x->IsAsciiRepresentation()) {
5764    Vector<const char> x_chars = x->ToAsciiVector();
5765    if (y->IsAsciiRepresentation()) {
5766      Vector<const char> y_chars = y->ToAsciiVector();
5767      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
5768    } else {
5769      Vector<const uc16> y_chars = y->ToUC16Vector();
5770      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
5771    }
5772  } else {
5773    Vector<const uc16> x_chars = x->ToUC16Vector();
5774    if (y->IsAsciiRepresentation()) {
5775      Vector<const char> y_chars = y->ToAsciiVector();
5776      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
5777    } else {
5778      Vector<const uc16> y_chars = y->ToUC16Vector();
5779      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
5780    }
5781  }
5782  Object* result;
5783  if (r == 0) {
5784    result = equal_prefix_result;
5785  } else {
5786    result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
5787  }
5788  ASSERT(result == StringInputBufferCompare(x, y));
5789  return result;
5790}
5791
5792
5793static Object* Runtime_StringCompare(Arguments args) {
5794  NoHandleAllocation ha;
5795  ASSERT(args.length() == 2);
5796
5797  CONVERT_CHECKED(String, x, args[0]);
5798  CONVERT_CHECKED(String, y, args[1]);
5799
5800  Counters::string_compare_runtime.Increment();
5801
5802  // A few fast case tests before we flatten.
5803  if (x == y) return Smi::FromInt(EQUAL);
5804  if (y->length() == 0) {
5805    if (x->length() == 0) return Smi::FromInt(EQUAL);
5806    return Smi::FromInt(GREATER);
5807  } else if (x->length() == 0) {
5808    return Smi::FromInt(LESS);
5809  }
5810
5811  int d = x->Get(0) - y->Get(0);
5812  if (d < 0) return Smi::FromInt(LESS);
5813  else if (d > 0) return Smi::FromInt(GREATER);
5814
5815  Object* obj = Heap::PrepareForCompare(x);
5816  if (obj->IsFailure()) return obj;
5817  obj = Heap::PrepareForCompare(y);
5818  if (obj->IsFailure()) return obj;
5819
5820  return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
5821                                      : StringInputBufferCompare(x, y);
5822}
5823
5824
5825static Object* Runtime_Math_acos(Arguments args) {
5826  NoHandleAllocation ha;
5827  ASSERT(args.length() == 1);
5828  Counters::math_acos.Increment();
5829
5830  CONVERT_DOUBLE_CHECKED(x, args[0]);
5831  return TranscendentalCache::Get(TranscendentalCache::ACOS, x);
5832}
5833
5834
5835static Object* Runtime_Math_asin(Arguments args) {
5836  NoHandleAllocation ha;
5837  ASSERT(args.length() == 1);
5838  Counters::math_asin.Increment();
5839
5840  CONVERT_DOUBLE_CHECKED(x, args[0]);
5841  return TranscendentalCache::Get(TranscendentalCache::ASIN, x);
5842}
5843
5844
5845static Object* Runtime_Math_atan(Arguments args) {
5846  NoHandleAllocation ha;
5847  ASSERT(args.length() == 1);
5848  Counters::math_atan.Increment();
5849
5850  CONVERT_DOUBLE_CHECKED(x, args[0]);
5851  return TranscendentalCache::Get(TranscendentalCache::ATAN, x);
5852}
5853
5854
5855static Object* Runtime_Math_atan2(Arguments args) {
5856  NoHandleAllocation ha;
5857  ASSERT(args.length() == 2);
5858  Counters::math_atan2.Increment();
5859
5860  CONVERT_DOUBLE_CHECKED(x, args[0]);
5861  CONVERT_DOUBLE_CHECKED(y, args[1]);
5862  double result;
5863  if (isinf(x) && isinf(y)) {
5864    // Make sure that the result in case of two infinite arguments
5865    // is a multiple of Pi / 4. The sign of the result is determined
5866    // by the first argument (x) and the sign of the second argument
5867    // determines the multiplier: one or three.
5868    static double kPiDividedBy4 = 0.78539816339744830962;
5869    int multiplier = (x < 0) ? -1 : 1;
5870    if (y < 0) multiplier *= 3;
5871    result = multiplier * kPiDividedBy4;
5872  } else {
5873    result = atan2(x, y);
5874  }
5875  return Heap::AllocateHeapNumber(result);
5876}
5877
5878
5879static Object* Runtime_Math_ceil(Arguments args) {
5880  NoHandleAllocation ha;
5881  ASSERT(args.length() == 1);
5882  Counters::math_ceil.Increment();
5883
5884  CONVERT_DOUBLE_CHECKED(x, args[0]);
5885  return Heap::NumberFromDouble(ceiling(x));
5886}
5887
5888
5889static Object* Runtime_Math_cos(Arguments args) {
5890  NoHandleAllocation ha;
5891  ASSERT(args.length() == 1);
5892  Counters::math_cos.Increment();
5893
5894  CONVERT_DOUBLE_CHECKED(x, args[0]);
5895  return TranscendentalCache::Get(TranscendentalCache::COS, x);
5896}
5897
5898
5899static Object* Runtime_Math_exp(Arguments args) {
5900  NoHandleAllocation ha;
5901  ASSERT(args.length() == 1);
5902  Counters::math_exp.Increment();
5903
5904  CONVERT_DOUBLE_CHECKED(x, args[0]);
5905  return TranscendentalCache::Get(TranscendentalCache::EXP, x);
5906}
5907
5908
5909static Object* Runtime_Math_floor(Arguments args) {
5910  NoHandleAllocation ha;
5911  ASSERT(args.length() == 1);
5912  Counters::math_floor.Increment();
5913
5914  CONVERT_DOUBLE_CHECKED(x, args[0]);
5915  return Heap::NumberFromDouble(floor(x));
5916}
5917
5918
5919static Object* Runtime_Math_log(Arguments args) {
5920  NoHandleAllocation ha;
5921  ASSERT(args.length() == 1);
5922  Counters::math_log.Increment();
5923
5924  CONVERT_DOUBLE_CHECKED(x, args[0]);
5925  return TranscendentalCache::Get(TranscendentalCache::LOG, x);
5926}
5927
5928
5929// Helper function to compute x^y, where y is known to be an
5930// integer. Uses binary decomposition to limit the number of
5931// multiplications; see the discussion in "Hacker's Delight" by Henry
5932// S. Warren, Jr., figure 11-6, page 213.
5933static double powi(double x, int y) {
5934  ASSERT(y != kMinInt);
5935  unsigned n = (y < 0) ? -y : y;
5936  double m = x;
5937  double p = 1;
5938  while (true) {
5939    if ((n & 1) != 0) p *= m;
5940    n >>= 1;
5941    if (n == 0) {
5942      if (y < 0) {
5943        // Unfortunately, we have to be careful when p has reached
5944        // infinity in the computation, because sometimes the higher
5945        // internal precision in the pow() implementation would have
5946        // given us a finite p. This happens very rarely.
5947        double result = 1.0 / p;
5948        return (result == 0 && isinf(p))
5949            ? pow(x, static_cast<double>(y))  // Avoid pow(double, int).
5950            : result;
5951      } else {
5952        return p;
5953      }
5954    }
5955    m *= m;
5956  }
5957}
5958
5959
5960static Object* Runtime_Math_pow(Arguments args) {
5961  NoHandleAllocation ha;
5962  ASSERT(args.length() == 2);
5963  Counters::math_pow.Increment();
5964
5965  CONVERT_DOUBLE_CHECKED(x, args[0]);
5966
5967  // If the second argument is a smi, it is much faster to call the
5968  // custom powi() function than the generic pow().
5969  if (args[1]->IsSmi()) {
5970    int y = Smi::cast(args[1])->value();
5971    return Heap::AllocateHeapNumber(powi(x, y));
5972  }
5973
5974  CONVERT_DOUBLE_CHECKED(y, args[1]);
5975
5976  if (!isinf(x)) {
5977    if (y == 0.5) {
5978      // It's not uncommon to use Math.pow(x, 0.5) to compute the
5979      // square root of a number. To speed up such computations, we
5980      // explictly check for this case and use the sqrt() function
5981      // which is faster than pow().
5982      return Heap::AllocateHeapNumber(sqrt(x));
5983    } else if (y == -0.5) {
5984      // Optimized using Math.pow(x, -0.5) == 1 / Math.pow(x, 0.5).
5985      return Heap::AllocateHeapNumber(1.0 / sqrt(x));
5986    }
5987  }
5988
5989  if (y == 0) {
5990    return Smi::FromInt(1);
5991  } else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
5992    return Heap::nan_value();
5993  } else {
5994    return Heap::AllocateHeapNumber(pow(x, y));
5995  }
5996}
5997
5998// Fast version of Math.pow if we know that y is not an integer and
5999// y is not -0.5 or 0.5. Used as slowcase from codegen.
6000static Object* Runtime_Math_pow_cfunction(Arguments args) {
6001  NoHandleAllocation ha;
6002  ASSERT(args.length() == 2);
6003  CONVERT_DOUBLE_CHECKED(x, args[0]);
6004  CONVERT_DOUBLE_CHECKED(y, args[1]);
6005  if (y == 0) {
6006      return Smi::FromInt(1);
6007  } else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
6008      return Heap::nan_value();
6009  } else {
6010      return Heap::AllocateHeapNumber(pow(x, y));
6011  }
6012}
6013
6014
6015static Object* Runtime_RoundNumber(Arguments args) {
6016  NoHandleAllocation ha;
6017  ASSERT(args.length() == 1);
6018  Counters::math_round.Increment();
6019
6020  if (!args[0]->IsHeapNumber()) {
6021    // Must be smi. Return the argument unchanged for all the other types
6022    // to make fuzz-natives test happy.
6023    return args[0];
6024  }
6025
6026  HeapNumber* number = reinterpret_cast<HeapNumber*>(args[0]);
6027
6028  double value = number->value();
6029  int exponent = number->get_exponent();
6030  int sign = number->get_sign();
6031
6032  // We compare with kSmiValueSize - 3 because (2^30 - 0.1) has exponent 29 and
6033  // should be rounded to 2^30, which is not smi.
6034  if (!sign && exponent <= kSmiValueSize - 3) {
6035    return Smi::FromInt(static_cast<int>(value + 0.5));
6036  }
6037
6038  // If the magnitude is big enough, there's no place for fraction part. If we
6039  // try to add 0.5 to this number, 1.0 will be added instead.
6040  if (exponent >= 52) {
6041    return number;
6042  }
6043
6044  if (sign && value >= -0.5) return Heap::minus_zero_value();
6045
6046  // Do not call NumberFromDouble() to avoid extra checks.
6047  return Heap::AllocateHeapNumber(floor(value + 0.5));
6048}
6049
6050
6051static Object* Runtime_Math_sin(Arguments args) {
6052  NoHandleAllocation ha;
6053  ASSERT(args.length() == 1);
6054  Counters::math_sin.Increment();
6055
6056  CONVERT_DOUBLE_CHECKED(x, args[0]);
6057  return TranscendentalCache::Get(TranscendentalCache::SIN, x);
6058}
6059
6060
6061static Object* Runtime_Math_sqrt(Arguments args) {
6062  NoHandleAllocation ha;
6063  ASSERT(args.length() == 1);
6064  Counters::math_sqrt.Increment();
6065
6066  CONVERT_DOUBLE_CHECKED(x, args[0]);
6067  return Heap::AllocateHeapNumber(sqrt(x));
6068}
6069
6070
6071static Object* Runtime_Math_tan(Arguments args) {
6072  NoHandleAllocation ha;
6073  ASSERT(args.length() == 1);
6074  Counters::math_tan.Increment();
6075
6076  CONVERT_DOUBLE_CHECKED(x, args[0]);
6077  return TranscendentalCache::Get(TranscendentalCache::TAN, x);
6078}
6079
6080
6081static int MakeDay(int year, int month, int day) {
6082  static const int day_from_month[] = {0, 31, 59, 90, 120, 151,
6083                                       181, 212, 243, 273, 304, 334};
6084  static const int day_from_month_leap[] = {0, 31, 60, 91, 121, 152,
6085                                            182, 213, 244, 274, 305, 335};
6086
6087  year += month / 12;
6088  month %= 12;
6089  if (month < 0) {
6090    year--;
6091    month += 12;
6092  }
6093
6094  ASSERT(month >= 0);
6095  ASSERT(month < 12);
6096
6097  // year_delta is an arbitrary number such that:
6098  // a) year_delta = -1 (mod 400)
6099  // b) year + year_delta > 0 for years in the range defined by
6100  //    ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of
6101  //    Jan 1 1970. This is required so that we don't run into integer
6102  //    division of negative numbers.
6103  // c) there shouldn't be an overflow for 32-bit integers in the following
6104  //    operations.
6105  static const int year_delta = 399999;
6106  static const int base_day = 365 * (1970 + year_delta) +
6107                              (1970 + year_delta) / 4 -
6108                              (1970 + year_delta) / 100 +
6109                              (1970 + year_delta) / 400;
6110
6111  int year1 = year + year_delta;
6112  int day_from_year = 365 * year1 +
6113                      year1 / 4 -
6114                      year1 / 100 +
6115                      year1 / 400 -
6116                      base_day;
6117
6118  if (year % 4 || (year % 100 == 0 && year % 400 != 0)) {
6119    return day_from_year + day_from_month[month] + day - 1;
6120  }
6121
6122  return day_from_year + day_from_month_leap[month] + day - 1;
6123}
6124
6125
6126static Object* Runtime_DateMakeDay(Arguments args) {
6127  NoHandleAllocation ha;
6128  ASSERT(args.length() == 3);
6129
6130  CONVERT_SMI_CHECKED(year, args[0]);
6131  CONVERT_SMI_CHECKED(month, args[1]);
6132  CONVERT_SMI_CHECKED(date, args[2]);
6133
6134  return Smi::FromInt(MakeDay(year, month, date));
6135}
6136
6137
6138static const int kDays4Years[] = {0, 365, 2 * 365, 3 * 365 + 1};
6139static const int kDaysIn4Years = 4 * 365 + 1;
6140static const int kDaysIn100Years = 25 * kDaysIn4Years - 1;
6141static const int kDaysIn400Years = 4 * kDaysIn100Years + 1;
6142static const int kDays1970to2000 = 30 * 365 + 7;
6143static const int kDaysOffset = 1000 * kDaysIn400Years + 5 * kDaysIn400Years -
6144                               kDays1970to2000;
6145static const int kYearsOffset = 400000;
6146
6147static const char kDayInYear[] = {
6148      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6149      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6150      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6151      22, 23, 24, 25, 26, 27, 28,
6152      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6153      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6154      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6155      22, 23, 24, 25, 26, 27, 28, 29, 30,
6156      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6157      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6158      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6159      22, 23, 24, 25, 26, 27, 28, 29, 30,
6160      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6161      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6162      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6163      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6164      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6165      22, 23, 24, 25, 26, 27, 28, 29, 30,
6166      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6167      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6168      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6169      22, 23, 24, 25, 26, 27, 28, 29, 30,
6170      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6171      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6172
6173      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6174      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6175      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6176      22, 23, 24, 25, 26, 27, 28,
6177      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6178      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6179      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6180      22, 23, 24, 25, 26, 27, 28, 29, 30,
6181      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6182      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6183      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6184      22, 23, 24, 25, 26, 27, 28, 29, 30,
6185      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6186      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6187      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6188      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6189      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6190      22, 23, 24, 25, 26, 27, 28, 29, 30,
6191      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6192      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6193      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6194      22, 23, 24, 25, 26, 27, 28, 29, 30,
6195      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6196      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6197
6198      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6199      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6200      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6201      22, 23, 24, 25, 26, 27, 28, 29,
6202      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6203      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6204      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6205      22, 23, 24, 25, 26, 27, 28, 29, 30,
6206      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6207      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6208      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6209      22, 23, 24, 25, 26, 27, 28, 29, 30,
6210      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6211      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6212      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6213      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6214      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6215      22, 23, 24, 25, 26, 27, 28, 29, 30,
6216      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6217      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6218      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6219      22, 23, 24, 25, 26, 27, 28, 29, 30,
6220      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6221      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6222
6223      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6224      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6225      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6226      22, 23, 24, 25, 26, 27, 28,
6227      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6228      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6229      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6230      22, 23, 24, 25, 26, 27, 28, 29, 30,
6231      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6232      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6233      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6234      22, 23, 24, 25, 26, 27, 28, 29, 30,
6235      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6236      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6237      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6238      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6239      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6240      22, 23, 24, 25, 26, 27, 28, 29, 30,
6241      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6242      22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6243      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6244      22, 23, 24, 25, 26, 27, 28, 29, 30,
6245      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6246      22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
6247
6248static const char kMonthInYear[] = {
6249      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6250      0, 0, 0, 0, 0, 0,
6251      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
6252      1, 1, 1,
6253      2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
6254      2, 2, 2, 2, 2, 2,
6255      3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
6256      3, 3, 3, 3, 3,
6257      4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
6258      4, 4, 4, 4, 4, 4,
6259      5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6260      5, 5, 5, 5, 5,
6261      6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6262      6, 6, 6, 6, 6, 6,
6263      7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
6264      7, 7, 7, 7, 7, 7,
6265      8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
6266      8, 8, 8, 8, 8,
6267      9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
6268      9, 9, 9, 9, 9, 9,
6269      10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
6270      10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
6271      11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
6272      11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
6273
6274      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6275      0, 0, 0, 0, 0, 0,
6276      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
6277      1, 1, 1,
6278      2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
6279      2, 2, 2, 2, 2, 2,
6280      3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
6281      3, 3, 3, 3, 3,
6282      4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
6283      4, 4, 4, 4, 4, 4,
6284      5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6285      5, 5, 5, 5, 5,
6286      6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6287      6, 6, 6, 6, 6, 6,
6288      7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
6289      7, 7, 7, 7, 7, 7,
6290      8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
6291      8, 8, 8, 8, 8,
6292      9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
6293      9, 9, 9, 9, 9, 9,
6294      10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
6295      10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
6296      11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
6297      11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
6298
6299      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6300      0, 0, 0, 0, 0, 0,
6301      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
6302      1, 1, 1, 1,
6303      2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
6304      2, 2, 2, 2, 2, 2,
6305      3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
6306      3, 3, 3, 3, 3,
6307      4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
6308      4, 4, 4, 4, 4, 4,
6309      5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6310      5, 5, 5, 5, 5,
6311      6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6312      6, 6, 6, 6, 6, 6,
6313      7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
6314      7, 7, 7, 7, 7, 7,
6315      8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
6316      8, 8, 8, 8, 8,
6317      9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
6318      9, 9, 9, 9, 9, 9,
6319      10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
6320      10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
6321      11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
6322      11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
6323
6324      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6325      0, 0, 0, 0, 0, 0,
6326      1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
6327      1, 1, 1,
6328      2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
6329      2, 2, 2, 2, 2, 2,
6330      3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
6331      3, 3, 3, 3, 3,
6332      4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
6333      4, 4, 4, 4, 4, 4,
6334      5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6335      5, 5, 5, 5, 5,
6336      6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6337      6, 6, 6, 6, 6, 6,
6338      7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
6339      7, 7, 7, 7, 7, 7,
6340      8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
6341      8, 8, 8, 8, 8,
6342      9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
6343      9, 9, 9, 9, 9, 9,
6344      10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
6345      10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
6346      11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
6347      11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11};
6348
6349
6350// This function works for dates from 1970 to 2099.
6351static inline void DateYMDFromTimeAfter1970(int date,
6352                                            int& year, int& month, int& day) {
6353#ifdef DEBUG
6354  int save_date = date;  // Need this for ASSERT in the end.
6355#endif
6356
6357  year = 1970 + (4 * date + 2) / kDaysIn4Years;
6358  date %= kDaysIn4Years;
6359
6360  month = kMonthInYear[date];
6361  day = kDayInYear[date];
6362
6363  ASSERT(MakeDay(year, month, day) == save_date);
6364}
6365
6366
6367static inline void DateYMDFromTimeSlow(int date,
6368                                       int& year, int& month, int& day) {
6369#ifdef DEBUG
6370  int save_date = date;  // Need this for ASSERT in the end.
6371#endif
6372
6373  date += kDaysOffset;
6374  year = 400 * (date / kDaysIn400Years) - kYearsOffset;
6375  date %= kDaysIn400Years;
6376
6377  ASSERT(MakeDay(year, 0, 1) + date == save_date);
6378
6379  date--;
6380  int yd1 = date / kDaysIn100Years;
6381  date %= kDaysIn100Years;
6382  year += 100 * yd1;
6383
6384  date++;
6385  int yd2 = date / kDaysIn4Years;
6386  date %= kDaysIn4Years;
6387  year += 4 * yd2;
6388
6389  date--;
6390  int yd3 = date / 365;
6391  date %= 365;
6392  year += yd3;
6393
6394  bool is_leap = (!yd1 || yd2) && !yd3;
6395
6396  ASSERT(date >= -1);
6397  ASSERT(is_leap || (date >= 0));
6398  ASSERT((date < 365) || (is_leap && (date < 366)));
6399  ASSERT(is_leap == ((year % 4 == 0) && (year % 100 || (year % 400 == 0))));
6400  ASSERT(is_leap || ((MakeDay(year, 0, 1) + date) == save_date));
6401  ASSERT(!is_leap || ((MakeDay(year, 0, 1) + date + 1) == save_date));
6402
6403  if (is_leap) {
6404    day = kDayInYear[2*365 + 1 + date];
6405    month = kMonthInYear[2*365 + 1 + date];
6406  } else {
6407    day = kDayInYear[date];
6408    month = kMonthInYear[date];
6409  }
6410
6411  ASSERT(MakeDay(year, month, day) == save_date);
6412}
6413
6414
6415static inline void DateYMDFromTime(int date,
6416                                   int& year, int& month, int& day) {
6417  if (date >= 0 && date < 32 * kDaysIn4Years) {
6418    DateYMDFromTimeAfter1970(date, year, month, day);
6419  } else {
6420    DateYMDFromTimeSlow(date, year, month, day);
6421  }
6422}
6423
6424
6425static Object* Runtime_DateYMDFromTime(Arguments args) {
6426  NoHandleAllocation ha;
6427  ASSERT(args.length() == 2);
6428
6429  CONVERT_DOUBLE_CHECKED(t, args[0]);
6430  CONVERT_CHECKED(JSArray, res_array, args[1]);
6431
6432  int year, month, day;
6433  DateYMDFromTime(static_cast<int>(floor(t / 86400000)), year, month, day);
6434
6435  res_array->SetElement(0, Smi::FromInt(year));
6436  res_array->SetElement(1, Smi::FromInt(month));
6437  res_array->SetElement(2, Smi::FromInt(day));
6438
6439  return Heap::undefined_value();
6440}
6441
6442
6443static Object* Runtime_NewArgumentsFast(Arguments args) {
6444  NoHandleAllocation ha;
6445  ASSERT(args.length() == 3);
6446
6447  JSFunction* callee = JSFunction::cast(args[0]);
6448  Object** parameters = reinterpret_cast<Object**>(args[1]);
6449  const int length = Smi::cast(args[2])->value();
6450
6451  Object* result = Heap::AllocateArgumentsObject(callee, length);
6452  if (result->IsFailure()) return result;
6453  // Allocate the elements if needed.
6454  if (length > 0) {
6455    // Allocate the fixed array.
6456    Object* obj = Heap::AllocateRawFixedArray(length);
6457    if (obj->IsFailure()) return obj;
6458
6459    AssertNoAllocation no_gc;
6460    reinterpret_cast<Array*>(obj)->set_map(Heap::fixed_array_map());
6461    FixedArray* array = FixedArray::cast(obj);
6462    array->set_length(length);
6463
6464    WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
6465    for (int i = 0; i < length; i++) {
6466      array->set(i, *--parameters, mode);
6467    }
6468    JSObject::cast(result)->set_elements(FixedArray::cast(obj));
6469  }
6470  return result;
6471}
6472
6473
6474static Object* Runtime_NewClosure(Arguments args) {
6475  HandleScope scope;
6476  ASSERT(args.length() == 2);
6477  CONVERT_ARG_CHECKED(Context, context, 0);
6478  CONVERT_ARG_CHECKED(SharedFunctionInfo, shared, 1);
6479
6480  PretenureFlag pretenure = (context->global_context() == *context)
6481      ? TENURED       // Allocate global closures in old space.
6482      : NOT_TENURED;  // Allocate local closures in new space.
6483  Handle<JSFunction> result =
6484      Factory::NewFunctionFromSharedFunctionInfo(shared, context, pretenure);
6485  return *result;
6486}
6487
6488
6489static Code* ComputeConstructStub(Handle<JSFunction> function) {
6490  Handle<Object> prototype = Factory::null_value();
6491  if (function->has_instance_prototype()) {
6492    prototype = Handle<Object>(function->instance_prototype());
6493  }
6494  if (function->shared()->CanGenerateInlineConstructor(*prototype)) {
6495    ConstructStubCompiler compiler;
6496    Object* code = compiler.CompileConstructStub(function->shared());
6497    if (code->IsFailure()) {
6498      return Builtins::builtin(Builtins::JSConstructStubGeneric);
6499    }
6500    return Code::cast(code);
6501  }
6502
6503  return function->shared()->construct_stub();
6504}
6505
6506
6507static Object* Runtime_NewObject(Arguments args) {
6508  HandleScope scope;
6509  ASSERT(args.length() == 1);
6510
6511  Handle<Object> constructor = args.at<Object>(0);
6512
6513  // If the constructor isn't a proper function we throw a type error.
6514  if (!constructor->IsJSFunction()) {
6515    Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
6516    Handle<Object> type_error =
6517        Factory::NewTypeError("not_constructor", arguments);
6518    return Top::Throw(*type_error);
6519  }
6520
6521  Handle<JSFunction> function = Handle<JSFunction>::cast(constructor);
6522
6523  // If function should not have prototype, construction is not allowed. In this
6524  // case generated code bailouts here, since function has no initial_map.
6525  if (!function->should_have_prototype()) {
6526    Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
6527    Handle<Object> type_error =
6528        Factory::NewTypeError("not_constructor", arguments);
6529    return Top::Throw(*type_error);
6530  }
6531
6532#ifdef ENABLE_DEBUGGER_SUPPORT
6533  // Handle stepping into constructors if step into is active.
6534  if (Debug::StepInActive()) {
6535    Debug::HandleStepIn(function, Handle<Object>::null(), 0, true);
6536  }
6537#endif
6538
6539  if (function->has_initial_map()) {
6540    if (function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
6541      // The 'Function' function ignores the receiver object when
6542      // called using 'new' and creates a new JSFunction object that
6543      // is returned.  The receiver object is only used for error
6544      // reporting if an error occurs when constructing the new
6545      // JSFunction. Factory::NewJSObject() should not be used to
6546      // allocate JSFunctions since it does not properly initialize
6547      // the shared part of the function. Since the receiver is
6548      // ignored anyway, we use the global object as the receiver
6549      // instead of a new JSFunction object. This way, errors are
6550      // reported the same way whether or not 'Function' is called
6551      // using 'new'.
6552      return Top::context()->global();
6553    }
6554  }
6555
6556  // The function should be compiled for the optimization hints to be available.
6557  Handle<SharedFunctionInfo> shared(function->shared());
6558  EnsureCompiled(shared, CLEAR_EXCEPTION);
6559
6560  bool first_allocation = !function->has_initial_map();
6561  Handle<JSObject> result = Factory::NewJSObject(function);
6562  if (first_allocation) {
6563    Handle<Code> stub = Handle<Code>(
6564        ComputeConstructStub(Handle<JSFunction>(function)));
6565    shared->set_construct_stub(*stub);
6566  }
6567
6568  Counters::constructed_objects.Increment();
6569  Counters::constructed_objects_runtime.Increment();
6570
6571  return *result;
6572}
6573
6574
6575static Object* Runtime_LazyCompile(Arguments args) {
6576  HandleScope scope;
6577  ASSERT(args.length() == 1);
6578
6579  Handle<JSFunction> function = args.at<JSFunction>(0);
6580#ifdef DEBUG
6581  if (FLAG_trace_lazy) {
6582    PrintF("[lazy: ");
6583    function->shared()->name()->Print();
6584    PrintF("]\n");
6585  }
6586#endif
6587
6588  // Compile the target function.  Here we compile using CompileLazyInLoop in
6589  // order to get the optimized version.  This helps code like delta-blue
6590  // that calls performance-critical routines through constructors.  A
6591  // constructor call doesn't use a CallIC, it uses a LoadIC followed by a
6592  // direct call.  Since the in-loop tracking takes place through CallICs
6593  // this means that things called through constructors are never known to
6594  // be in loops.  We compile them as if they are in loops here just in case.
6595  ASSERT(!function->is_compiled());
6596  if (!CompileLazyInLoop(function, Handle<Object>::null(), KEEP_EXCEPTION)) {
6597    return Failure::Exception();
6598  }
6599
6600  return function->code();
6601}
6602
6603
6604static Object* Runtime_GetFunctionDelegate(Arguments args) {
6605  HandleScope scope;
6606  ASSERT(args.length() == 1);
6607  RUNTIME_ASSERT(!args[0]->IsJSFunction());
6608  return *Execution::GetFunctionDelegate(args.at<Object>(0));
6609}
6610
6611
6612static Object* Runtime_GetConstructorDelegate(Arguments args) {
6613  HandleScope scope;
6614  ASSERT(args.length() == 1);
6615  RUNTIME_ASSERT(!args[0]->IsJSFunction());
6616  return *Execution::GetConstructorDelegate(args.at<Object>(0));
6617}
6618
6619
6620static Object* Runtime_NewContext(Arguments args) {
6621  NoHandleAllocation ha;
6622  ASSERT(args.length() == 1);
6623
6624  CONVERT_CHECKED(JSFunction, function, args[0]);
6625  int length = ScopeInfo<>::NumberOfContextSlots(function->code());
6626  Object* result = Heap::AllocateFunctionContext(length, function);
6627  if (result->IsFailure()) return result;
6628
6629  Top::set_context(Context::cast(result));
6630
6631  return result;  // non-failure
6632}
6633
6634static Object* PushContextHelper(Object* object, bool is_catch_context) {
6635  // Convert the object to a proper JavaScript object.
6636  Object* js_object = object;
6637  if (!js_object->IsJSObject()) {
6638    js_object = js_object->ToObject();
6639    if (js_object->IsFailure()) {
6640      if (!Failure::cast(js_object)->IsInternalError()) return js_object;
6641      HandleScope scope;
6642      Handle<Object> handle(object);
6643      Handle<Object> result =
6644          Factory::NewTypeError("with_expression", HandleVector(&handle, 1));
6645      return Top::Throw(*result);
6646    }
6647  }
6648
6649  Object* result =
6650      Heap::AllocateWithContext(Top::context(),
6651                                JSObject::cast(js_object),
6652                                is_catch_context);
6653  if (result->IsFailure()) return result;
6654
6655  Context* context = Context::cast(result);
6656  Top::set_context(context);
6657
6658  return result;
6659}
6660
6661
6662static Object* Runtime_PushContext(Arguments args) {
6663  NoHandleAllocation ha;
6664  ASSERT(args.length() == 1);
6665  return PushContextHelper(args[0], false);
6666}
6667
6668
6669static Object* Runtime_PushCatchContext(Arguments args) {
6670  NoHandleAllocation ha;
6671  ASSERT(args.length() == 1);
6672  return PushContextHelper(args[0], true);
6673}
6674
6675
6676static Object* Runtime_LookupContext(Arguments args) {
6677  HandleScope scope;
6678  ASSERT(args.length() == 2);
6679
6680  CONVERT_ARG_CHECKED(Context, context, 0);
6681  CONVERT_ARG_CHECKED(String, name, 1);
6682
6683  int index;
6684  PropertyAttributes attributes;
6685  ContextLookupFlags flags = FOLLOW_CHAINS;
6686  Handle<Object> holder =
6687      context->Lookup(name, flags, &index, &attributes);
6688
6689  if (index < 0 && !holder.is_null()) {
6690    ASSERT(holder->IsJSObject());
6691    return *holder;
6692  }
6693
6694  // No intermediate context found. Use global object by default.
6695  return Top::context()->global();
6696}
6697
6698
6699// A mechanism to return a pair of Object pointers in registers (if possible).
6700// How this is achieved is calling convention-dependent.
6701// All currently supported x86 compiles uses calling conventions that are cdecl
6702// variants where a 64-bit value is returned in two 32-bit registers
6703// (edx:eax on ia32, r1:r0 on ARM).
6704// In AMD-64 calling convention a struct of two pointers is returned in rdx:rax.
6705// In Win64 calling convention, a struct of two pointers is returned in memory,
6706// allocated by the caller, and passed as a pointer in a hidden first parameter.
6707#ifdef V8_HOST_ARCH_64_BIT
6708struct ObjectPair {
6709  Object* x;
6710  Object* y;
6711};
6712
6713static inline ObjectPair MakePair(Object* x, Object* y) {
6714  ObjectPair result = {x, y};
6715  // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
6716  // In Win64 they are assigned to a hidden first argument.
6717  return result;
6718}
6719#else
6720typedef uint64_t ObjectPair;
6721static inline ObjectPair MakePair(Object* x, Object* y) {
6722  return reinterpret_cast<uint32_t>(x) |
6723      (reinterpret_cast<ObjectPair>(y) << 32);
6724}
6725#endif
6726
6727
6728static inline Object* Unhole(Object* x, PropertyAttributes attributes) {
6729  ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
6730  USE(attributes);
6731  return x->IsTheHole() ? Heap::undefined_value() : x;
6732}
6733
6734
6735static JSObject* ComputeReceiverForNonGlobal(JSObject* holder) {
6736  ASSERT(!holder->IsGlobalObject());
6737  Context* top = Top::context();
6738  // Get the context extension function.
6739  JSFunction* context_extension_function =
6740      top->global_context()->context_extension_function();
6741  // If the holder isn't a context extension object, we just return it
6742  // as the receiver. This allows arguments objects to be used as
6743  // receivers, but only if they are put in the context scope chain
6744  // explicitly via a with-statement.
6745  Object* constructor = holder->map()->constructor();
6746  if (constructor != context_extension_function) return holder;
6747  // Fall back to using the global object as the receiver if the
6748  // property turns out to be a local variable allocated in a context
6749  // extension object - introduced via eval.
6750  return top->global()->global_receiver();
6751}
6752
6753
6754static ObjectPair LoadContextSlotHelper(Arguments args, bool throw_error) {
6755  HandleScope scope;
6756  ASSERT_EQ(2, args.length());
6757
6758  if (!args[0]->IsContext() || !args[1]->IsString()) {
6759    return MakePair(Top::ThrowIllegalOperation(), NULL);
6760  }
6761  Handle<Context> context = args.at<Context>(0);
6762  Handle<String> name = args.at<String>(1);
6763
6764  int index;
6765  PropertyAttributes attributes;
6766  ContextLookupFlags flags = FOLLOW_CHAINS;
6767  Handle<Object> holder =
6768      context->Lookup(name, flags, &index, &attributes);
6769
6770  // If the index is non-negative, the slot has been found in a local
6771  // variable or a parameter. Read it from the context object or the
6772  // arguments object.
6773  if (index >= 0) {
6774    // If the "property" we were looking for is a local variable or an
6775    // argument in a context, the receiver is the global object; see
6776    // ECMA-262, 3rd., 10.1.6 and 10.2.3.
6777    JSObject* receiver = Top::context()->global()->global_receiver();
6778    Object* value = (holder->IsContext())
6779        ? Context::cast(*holder)->get(index)
6780        : JSObject::cast(*holder)->GetElement(index);
6781    return MakePair(Unhole(value, attributes), receiver);
6782  }
6783
6784  // If the holder is found, we read the property from it.
6785  if (!holder.is_null() && holder->IsJSObject()) {
6786    ASSERT(Handle<JSObject>::cast(holder)->HasProperty(*name));
6787    JSObject* object = JSObject::cast(*holder);
6788    JSObject* receiver;
6789    if (object->IsGlobalObject()) {
6790      receiver = GlobalObject::cast(object)->global_receiver();
6791    } else if (context->is_exception_holder(*holder)) {
6792      receiver = Top::context()->global()->global_receiver();
6793    } else {
6794      receiver = ComputeReceiverForNonGlobal(object);
6795    }
6796    // No need to unhole the value here. This is taken care of by the
6797    // GetProperty function.
6798    Object* value = object->GetProperty(*name);
6799    return MakePair(value, receiver);
6800  }
6801
6802  if (throw_error) {
6803    // The property doesn't exist - throw exception.
6804    Handle<Object> reference_error =
6805        Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
6806    return MakePair(Top::Throw(*reference_error), NULL);
6807  } else {
6808    // The property doesn't exist - return undefined
6809    return MakePair(Heap::undefined_value(), Heap::undefined_value());
6810  }
6811}
6812
6813
6814static ObjectPair Runtime_LoadContextSlot(Arguments args) {
6815  return LoadContextSlotHelper(args, true);
6816}
6817
6818
6819static ObjectPair Runtime_LoadContextSlotNoReferenceError(Arguments args) {
6820  return LoadContextSlotHelper(args, false);
6821}
6822
6823
6824static Object* Runtime_StoreContextSlot(Arguments args) {
6825  HandleScope scope;
6826  ASSERT(args.length() == 3);
6827
6828  Handle<Object> value(args[0]);
6829  CONVERT_ARG_CHECKED(Context, context, 1);
6830  CONVERT_ARG_CHECKED(String, name, 2);
6831
6832  int index;
6833  PropertyAttributes attributes;
6834  ContextLookupFlags flags = FOLLOW_CHAINS;
6835  Handle<Object> holder =
6836      context->Lookup(name, flags, &index, &attributes);
6837
6838  if (index >= 0) {
6839    if (holder->IsContext()) {
6840      // Ignore if read_only variable.
6841      if ((attributes & READ_ONLY) == 0) {
6842        Handle<Context>::cast(holder)->set(index, *value);
6843      }
6844    } else {
6845      ASSERT((attributes & READ_ONLY) == 0);
6846      Object* result =
6847          Handle<JSObject>::cast(holder)->SetElement(index, *value);
6848      USE(result);
6849      ASSERT(!result->IsFailure());
6850    }
6851    return *value;
6852  }
6853
6854  // Slow case: The property is not in a FixedArray context.
6855  // It is either in an JSObject extension context or it was not found.
6856  Handle<JSObject> context_ext;
6857
6858  if (!holder.is_null()) {
6859    // The property exists in the extension context.
6860    context_ext = Handle<JSObject>::cast(holder);
6861  } else {
6862    // The property was not found. It needs to be stored in the global context.
6863    ASSERT(attributes == ABSENT);
6864    attributes = NONE;
6865    context_ext = Handle<JSObject>(Top::context()->global());
6866  }
6867
6868  // Set the property, but ignore if read_only variable on the context
6869  // extension object itself.
6870  if ((attributes & READ_ONLY) == 0 ||
6871      (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) {
6872    Handle<Object> set = SetProperty(context_ext, name, value, attributes);
6873    if (set.is_null()) {
6874      // Failure::Exception is converted to a null handle in the
6875      // handle-based methods such as SetProperty.  We therefore need
6876      // to convert null handles back to exceptions.
6877      ASSERT(Top::has_pending_exception());
6878      return Failure::Exception();
6879    }
6880  }
6881  return *value;
6882}
6883
6884
6885static Object* Runtime_Throw(Arguments args) {
6886  HandleScope scope;
6887  ASSERT(args.length() == 1);
6888
6889  return Top::Throw(args[0]);
6890}
6891
6892
6893static Object* Runtime_ReThrow(Arguments args) {
6894  HandleScope scope;
6895  ASSERT(args.length() == 1);
6896
6897  return Top::ReThrow(args[0]);
6898}
6899
6900
6901static Object* Runtime_PromoteScheduledException(Arguments args) {
6902  ASSERT_EQ(0, args.length());
6903  return Top::PromoteScheduledException();
6904}
6905
6906
6907static Object* Runtime_ThrowReferenceError(Arguments args) {
6908  HandleScope scope;
6909  ASSERT(args.length() == 1);
6910
6911  Handle<Object> name(args[0]);
6912  Handle<Object> reference_error =
6913    Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
6914  return Top::Throw(*reference_error);
6915}
6916
6917
6918static Object* Runtime_StackOverflow(Arguments args) {
6919  NoHandleAllocation na;
6920  return Top::StackOverflow();
6921}
6922
6923
6924static Object* Runtime_StackGuard(Arguments args) {
6925  ASSERT(args.length() == 1);
6926
6927  // First check if this is a real stack overflow.
6928  if (StackGuard::IsStackOverflow()) {
6929    return Runtime_StackOverflow(args);
6930  }
6931
6932  return Execution::HandleStackGuardInterrupt();
6933}
6934
6935
6936// NOTE: These PrintXXX functions are defined for all builds (not just
6937// DEBUG builds) because we may want to be able to trace function
6938// calls in all modes.
6939static void PrintString(String* str) {
6940  // not uncommon to have empty strings
6941  if (str->length() > 0) {
6942    SmartPointer<char> s =
6943        str->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
6944    PrintF("%s", *s);
6945  }
6946}
6947
6948
6949static void PrintObject(Object* obj) {
6950  if (obj->IsSmi()) {
6951    PrintF("%d", Smi::cast(obj)->value());
6952  } else if (obj->IsString() || obj->IsSymbol()) {
6953    PrintString(String::cast(obj));
6954  } else if (obj->IsNumber()) {
6955    PrintF("%g", obj->Number());
6956  } else if (obj->IsFailure()) {
6957    PrintF("<failure>");
6958  } else if (obj->IsUndefined()) {
6959    PrintF("<undefined>");
6960  } else if (obj->IsNull()) {
6961    PrintF("<null>");
6962  } else if (obj->IsTrue()) {
6963    PrintF("<true>");
6964  } else if (obj->IsFalse()) {
6965    PrintF("<false>");
6966  } else {
6967    PrintF("%p", obj);
6968  }
6969}
6970
6971
6972static int StackSize() {
6973  int n = 0;
6974  for (JavaScriptFrameIterator it; !it.done(); it.Advance()) n++;
6975  return n;
6976}
6977
6978
6979static void PrintTransition(Object* result) {
6980  // indentation
6981  { const int nmax = 80;
6982    int n = StackSize();
6983    if (n <= nmax)
6984      PrintF("%4d:%*s", n, n, "");
6985    else
6986      PrintF("%4d:%*s", n, nmax, "...");
6987  }
6988
6989  if (result == NULL) {
6990    // constructor calls
6991    JavaScriptFrameIterator it;
6992    JavaScriptFrame* frame = it.frame();
6993    if (frame->IsConstructor()) PrintF("new ");
6994    // function name
6995    Object* fun = frame->function();
6996    if (fun->IsJSFunction()) {
6997      PrintObject(JSFunction::cast(fun)->shared()->name());
6998    } else {
6999      PrintObject(fun);
7000    }
7001    // function arguments
7002    // (we are intentionally only printing the actually
7003    // supplied parameters, not all parameters required)
7004    PrintF("(this=");
7005    PrintObject(frame->receiver());
7006    const int length = frame->GetProvidedParametersCount();
7007    for (int i = 0; i < length; i++) {
7008      PrintF(", ");
7009      PrintObject(frame->GetParameter(i));
7010    }
7011    PrintF(") {\n");
7012
7013  } else {
7014    // function result
7015    PrintF("} -> ");
7016    PrintObject(result);
7017    PrintF("\n");
7018  }
7019}
7020
7021
7022static Object* Runtime_TraceEnter(Arguments args) {
7023  ASSERT(args.length() == 0);
7024  NoHandleAllocation ha;
7025  PrintTransition(NULL);
7026  return Heap::undefined_value();
7027}
7028
7029
7030static Object* Runtime_TraceExit(Arguments args) {
7031  NoHandleAllocation ha;
7032  PrintTransition(args[0]);
7033  return args[0];  // return TOS
7034}
7035
7036
7037static Object* Runtime_DebugPrint(Arguments args) {
7038  NoHandleAllocation ha;
7039  ASSERT(args.length() == 1);
7040
7041#ifdef DEBUG
7042  if (args[0]->IsString()) {
7043    // If we have a string, assume it's a code "marker"
7044    // and print some interesting cpu debugging info.
7045    JavaScriptFrameIterator it;
7046    JavaScriptFrame* frame = it.frame();
7047    PrintF("fp = %p, sp = %p, caller_sp = %p: ",
7048           frame->fp(), frame->sp(), frame->caller_sp());
7049  } else {
7050    PrintF("DebugPrint: ");
7051  }
7052  args[0]->Print();
7053  if (args[0]->IsHeapObject()) {
7054    PrintF("\n");
7055    HeapObject::cast(args[0])->map()->Print();
7056  }
7057#else
7058  // ShortPrint is available in release mode. Print is not.
7059  args[0]->ShortPrint();
7060#endif
7061  PrintF("\n");
7062  Flush();
7063
7064  return args[0];  // return TOS
7065}
7066
7067
7068static Object* Runtime_DebugTrace(Arguments args) {
7069  ASSERT(args.length() == 0);
7070  NoHandleAllocation ha;
7071  Top::PrintStack();
7072  return Heap::undefined_value();
7073}
7074
7075
7076static Object* Runtime_DateCurrentTime(Arguments args) {
7077  NoHandleAllocation ha;
7078  ASSERT(args.length() == 0);
7079
7080  // According to ECMA-262, section 15.9.1, page 117, the precision of
7081  // the number in a Date object representing a particular instant in
7082  // time is milliseconds. Therefore, we floor the result of getting
7083  // the OS time.
7084  double millis = floor(OS::TimeCurrentMillis());
7085  return Heap::NumberFromDouble(millis);
7086}
7087
7088
7089static Object* Runtime_DateParseString(Arguments args) {
7090  HandleScope scope;
7091  ASSERT(args.length() == 2);
7092
7093  CONVERT_ARG_CHECKED(String, str, 0);
7094  FlattenString(str);
7095
7096  CONVERT_ARG_CHECKED(JSArray, output, 1);
7097  RUNTIME_ASSERT(output->HasFastElements());
7098
7099  AssertNoAllocation no_allocation;
7100
7101  FixedArray* output_array = FixedArray::cast(output->elements());
7102  RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
7103  bool result;
7104  if (str->IsAsciiRepresentation()) {
7105    result = DateParser::Parse(str->ToAsciiVector(), output_array);
7106  } else {
7107    ASSERT(str->IsTwoByteRepresentation());
7108    result = DateParser::Parse(str->ToUC16Vector(), output_array);
7109  }
7110
7111  if (result) {
7112    return *output;
7113  } else {
7114    return Heap::null_value();
7115  }
7116}
7117
7118
7119static Object* Runtime_DateLocalTimezone(Arguments args) {
7120  NoHandleAllocation ha;
7121  ASSERT(args.length() == 1);
7122
7123  CONVERT_DOUBLE_CHECKED(x, args[0]);
7124  const char* zone = OS::LocalTimezone(x);
7125  return Heap::AllocateStringFromUtf8(CStrVector(zone));
7126}
7127
7128
7129static Object* Runtime_DateLocalTimeOffset(Arguments args) {
7130  NoHandleAllocation ha;
7131  ASSERT(args.length() == 0);
7132
7133  return Heap::NumberFromDouble(OS::LocalTimeOffset());
7134}
7135
7136
7137static Object* Runtime_DateDaylightSavingsOffset(Arguments args) {
7138  NoHandleAllocation ha;
7139  ASSERT(args.length() == 1);
7140
7141  CONVERT_DOUBLE_CHECKED(x, args[0]);
7142  return Heap::NumberFromDouble(OS::DaylightSavingsOffset(x));
7143}
7144
7145
7146static Object* Runtime_GlobalReceiver(Arguments args) {
7147  ASSERT(args.length() == 1);
7148  Object* global = args[0];
7149  if (!global->IsJSGlobalObject()) return Heap::null_value();
7150  return JSGlobalObject::cast(global)->global_receiver();
7151}
7152
7153
7154static Object* Runtime_CompileString(Arguments args) {
7155  HandleScope scope;
7156  ASSERT_EQ(2, args.length());
7157  CONVERT_ARG_CHECKED(String, source, 0);
7158  CONVERT_ARG_CHECKED(Oddball, is_json, 1)
7159
7160  // Compile source string in the global context.
7161  Handle<Context> context(Top::context()->global_context());
7162  Compiler::ValidationState validate = (is_json->IsTrue())
7163    ? Compiler::VALIDATE_JSON : Compiler::DONT_VALIDATE_JSON;
7164  Handle<SharedFunctionInfo> shared = Compiler::CompileEval(source,
7165                                                            context,
7166                                                            true,
7167                                                            validate);
7168  if (shared.is_null()) return Failure::Exception();
7169  Handle<JSFunction> fun =
7170      Factory::NewFunctionFromSharedFunctionInfo(shared, context, NOT_TENURED);
7171  return *fun;
7172}
7173
7174
7175static ObjectPair Runtime_ResolvePossiblyDirectEval(Arguments args) {
7176  ASSERT(args.length() == 3);
7177  if (!args[0]->IsJSFunction()) {
7178    return MakePair(Top::ThrowIllegalOperation(), NULL);
7179  }
7180
7181  HandleScope scope;
7182  Handle<JSFunction> callee = args.at<JSFunction>(0);
7183  Handle<Object> receiver;  // Will be overwritten.
7184
7185  // Compute the calling context.
7186  Handle<Context> context = Handle<Context>(Top::context());
7187#ifdef DEBUG
7188  // Make sure Top::context() agrees with the old code that traversed
7189  // the stack frames to compute the context.
7190  StackFrameLocator locator;
7191  JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
7192  ASSERT(Context::cast(frame->context()) == *context);
7193#endif
7194
7195  // Find where the 'eval' symbol is bound. It is unaliased only if
7196  // it is bound in the global context.
7197  int index = -1;
7198  PropertyAttributes attributes = ABSENT;
7199  while (true) {
7200    receiver = context->Lookup(Factory::eval_symbol(), FOLLOW_PROTOTYPE_CHAIN,
7201                               &index, &attributes);
7202    // Stop search when eval is found or when the global context is
7203    // reached.
7204    if (attributes != ABSENT || context->IsGlobalContext()) break;
7205    if (context->is_function_context()) {
7206      context = Handle<Context>(Context::cast(context->closure()->context()));
7207    } else {
7208      context = Handle<Context>(context->previous());
7209    }
7210  }
7211
7212  // If eval could not be resolved, it has been deleted and we need to
7213  // throw a reference error.
7214  if (attributes == ABSENT) {
7215    Handle<Object> name = Factory::eval_symbol();
7216    Handle<Object> reference_error =
7217        Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
7218    return MakePair(Top::Throw(*reference_error), NULL);
7219  }
7220
7221  if (!context->IsGlobalContext()) {
7222    // 'eval' is not bound in the global context. Just call the function
7223    // with the given arguments. This is not necessarily the global eval.
7224    if (receiver->IsContext()) {
7225      context = Handle<Context>::cast(receiver);
7226      receiver = Handle<Object>(context->get(index));
7227    } else if (receiver->IsJSContextExtensionObject()) {
7228      receiver = Handle<JSObject>(Top::context()->global()->global_receiver());
7229    }
7230    return MakePair(*callee, *receiver);
7231  }
7232
7233  // 'eval' is bound in the global context, but it may have been overwritten.
7234  // Compare it to the builtin 'GlobalEval' function to make sure.
7235  if (*callee != Top::global_context()->global_eval_fun() ||
7236      !args[1]->IsString()) {
7237    return MakePair(*callee, Top::context()->global()->global_receiver());
7238  }
7239
7240  // Deal with a normal eval call with a string argument. Compile it
7241  // and return the compiled function bound in the local context.
7242  Handle<String> source = args.at<String>(1);
7243  Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
7244      source,
7245      Handle<Context>(Top::context()),
7246      Top::context()->IsGlobalContext(),
7247      Compiler::DONT_VALIDATE_JSON);
7248  if (shared.is_null()) return MakePair(Failure::Exception(), NULL);
7249  callee = Factory::NewFunctionFromSharedFunctionInfo(
7250      shared,
7251      Handle<Context>(Top::context()),
7252      NOT_TENURED);
7253  return MakePair(*callee, args[2]);
7254}
7255
7256
7257static Object* Runtime_SetNewFunctionAttributes(Arguments args) {
7258  // This utility adjusts the property attributes for newly created Function
7259  // object ("new Function(...)") by changing the map.
7260  // All it does is changing the prototype property to enumerable
7261  // as specified in ECMA262, 15.3.5.2.
7262  HandleScope scope;
7263  ASSERT(args.length() == 1);
7264  CONVERT_ARG_CHECKED(JSFunction, func, 0);
7265  ASSERT(func->map()->instance_type() ==
7266         Top::function_instance_map()->instance_type());
7267  ASSERT(func->map()->instance_size() ==
7268         Top::function_instance_map()->instance_size());
7269  func->set_map(*Top::function_instance_map());
7270  return *func;
7271}
7272
7273
7274// Push an array unto an array of arrays if it is not already in the
7275// array.  Returns true if the element was pushed on the stack and
7276// false otherwise.
7277static Object* Runtime_PushIfAbsent(Arguments args) {
7278  ASSERT(args.length() == 2);
7279  CONVERT_CHECKED(JSArray, array, args[0]);
7280  CONVERT_CHECKED(JSArray, element, args[1]);
7281  RUNTIME_ASSERT(array->HasFastElements());
7282  int length = Smi::cast(array->length())->value();
7283  FixedArray* elements = FixedArray::cast(array->elements());
7284  for (int i = 0; i < length; i++) {
7285    if (elements->get(i) == element) return Heap::false_value();
7286  }
7287  Object* obj = array->SetFastElement(length, element);
7288  if (obj->IsFailure()) return obj;
7289  return Heap::true_value();
7290}
7291
7292
7293/**
7294 * A simple visitor visits every element of Array's.
7295 * The backend storage can be a fixed array for fast elements case,
7296 * or a dictionary for sparse array. Since Dictionary is a subtype
7297 * of FixedArray, the class can be used by both fast and slow cases.
7298 * The second parameter of the constructor, fast_elements, specifies
7299 * whether the storage is a FixedArray or Dictionary.
7300 *
7301 * An index limit is used to deal with the situation that a result array
7302 * length overflows 32-bit non-negative integer.
7303 */
7304class ArrayConcatVisitor {
7305 public:
7306  ArrayConcatVisitor(Handle<FixedArray> storage,
7307                     uint32_t index_limit,
7308                     bool fast_elements) :
7309      storage_(storage), index_limit_(index_limit),
7310      index_offset_(0), fast_elements_(fast_elements) { }
7311
7312  void visit(uint32_t i, Handle<Object> elm) {
7313    if (i >= index_limit_ - index_offset_) return;
7314    uint32_t index = index_offset_ + i;
7315
7316    if (fast_elements_) {
7317      ASSERT(index < static_cast<uint32_t>(storage_->length()));
7318      storage_->set(index, *elm);
7319
7320    } else {
7321      Handle<NumberDictionary> dict = Handle<NumberDictionary>::cast(storage_);
7322      Handle<NumberDictionary> result =
7323          Factory::DictionaryAtNumberPut(dict, index, elm);
7324      if (!result.is_identical_to(dict))
7325        storage_ = result;
7326    }
7327  }
7328
7329  void increase_index_offset(uint32_t delta) {
7330    if (index_limit_ - index_offset_ < delta) {
7331      index_offset_ = index_limit_;
7332    } else {
7333      index_offset_ += delta;
7334    }
7335  }
7336
7337  Handle<FixedArray> storage() { return storage_; }
7338
7339 private:
7340  Handle<FixedArray> storage_;
7341  // Limit on the accepted indices. Elements with indices larger than the
7342  // limit are ignored by the visitor.
7343  uint32_t index_limit_;
7344  // Index after last seen index. Always less than or equal to index_limit_.
7345  uint32_t index_offset_;
7346  bool fast_elements_;
7347};
7348
7349
7350template<class ExternalArrayClass, class ElementType>
7351static uint32_t IterateExternalArrayElements(Handle<JSObject> receiver,
7352                                             bool elements_are_ints,
7353                                             bool elements_are_guaranteed_smis,
7354                                             uint32_t range,
7355                                             ArrayConcatVisitor* visitor) {
7356  Handle<ExternalArrayClass> array(
7357      ExternalArrayClass::cast(receiver->elements()));
7358  uint32_t len = Min(static_cast<uint32_t>(array->length()), range);
7359
7360  if (visitor != NULL) {
7361    if (elements_are_ints) {
7362      if (elements_are_guaranteed_smis) {
7363        for (uint32_t j = 0; j < len; j++) {
7364          Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get(j))));
7365          visitor->visit(j, e);
7366        }
7367      } else {
7368        for (uint32_t j = 0; j < len; j++) {
7369          int64_t val = static_cast<int64_t>(array->get(j));
7370          if (Smi::IsValid(static_cast<intptr_t>(val))) {
7371            Handle<Smi> e(Smi::FromInt(static_cast<int>(val)));
7372            visitor->visit(j, e);
7373          } else {
7374            Handle<Object> e(
7375                Heap::AllocateHeapNumber(static_cast<ElementType>(val)));
7376            visitor->visit(j, e);
7377          }
7378        }
7379      }
7380    } else {
7381      for (uint32_t j = 0; j < len; j++) {
7382        Handle<Object> e(Heap::AllocateHeapNumber(array->get(j)));
7383        visitor->visit(j, e);
7384      }
7385    }
7386  }
7387
7388  return len;
7389}
7390
7391/**
7392 * A helper function that visits elements of a JSObject. Only elements
7393 * whose index between 0 and range (exclusive) are visited.
7394 *
7395 * If the third parameter, visitor, is not NULL, the visitor is called
7396 * with parameters, 'visitor_index_offset + element index' and the element.
7397 *
7398 * It returns the number of visisted elements.
7399 */
7400static uint32_t IterateElements(Handle<JSObject> receiver,
7401                                uint32_t range,
7402                                ArrayConcatVisitor* visitor) {
7403  uint32_t num_of_elements = 0;
7404
7405  switch (receiver->GetElementsKind()) {
7406    case JSObject::FAST_ELEMENTS: {
7407      Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
7408      uint32_t len = elements->length();
7409      if (range < len) {
7410        len = range;
7411      }
7412
7413      for (uint32_t j = 0; j < len; j++) {
7414        Handle<Object> e(elements->get(j));
7415        if (!e->IsTheHole()) {
7416          num_of_elements++;
7417          if (visitor) {
7418            visitor->visit(j, e);
7419          }
7420        }
7421      }
7422      break;
7423    }
7424    case JSObject::PIXEL_ELEMENTS: {
7425      Handle<PixelArray> pixels(PixelArray::cast(receiver->elements()));
7426      uint32_t len = pixels->length();
7427      if (range < len) {
7428        len = range;
7429      }
7430
7431      for (uint32_t j = 0; j < len; j++) {
7432        num_of_elements++;
7433        if (visitor != NULL) {
7434          Handle<Smi> e(Smi::FromInt(pixels->get(j)));
7435          visitor->visit(j, e);
7436        }
7437      }
7438      break;
7439    }
7440    case JSObject::EXTERNAL_BYTE_ELEMENTS: {
7441      num_of_elements =
7442          IterateExternalArrayElements<ExternalByteArray, int8_t>(
7443              receiver, true, true, range, visitor);
7444      break;
7445    }
7446    case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
7447      num_of_elements =
7448          IterateExternalArrayElements<ExternalUnsignedByteArray, uint8_t>(
7449              receiver, true, true, range, visitor);
7450      break;
7451    }
7452    case JSObject::EXTERNAL_SHORT_ELEMENTS: {
7453      num_of_elements =
7454          IterateExternalArrayElements<ExternalShortArray, int16_t>(
7455              receiver, true, true, range, visitor);
7456      break;
7457    }
7458    case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
7459      num_of_elements =
7460          IterateExternalArrayElements<ExternalUnsignedShortArray, uint16_t>(
7461              receiver, true, true, range, visitor);
7462      break;
7463    }
7464    case JSObject::EXTERNAL_INT_ELEMENTS: {
7465      num_of_elements =
7466          IterateExternalArrayElements<ExternalIntArray, int32_t>(
7467              receiver, true, false, range, visitor);
7468      break;
7469    }
7470    case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: {
7471      num_of_elements =
7472          IterateExternalArrayElements<ExternalUnsignedIntArray, uint32_t>(
7473              receiver, true, false, range, visitor);
7474      break;
7475    }
7476    case JSObject::EXTERNAL_FLOAT_ELEMENTS: {
7477      num_of_elements =
7478          IterateExternalArrayElements<ExternalFloatArray, float>(
7479              receiver, false, false, range, visitor);
7480      break;
7481    }
7482    case JSObject::DICTIONARY_ELEMENTS: {
7483      Handle<NumberDictionary> dict(receiver->element_dictionary());
7484      uint32_t capacity = dict->Capacity();
7485      for (uint32_t j = 0; j < capacity; j++) {
7486        Handle<Object> k(dict->KeyAt(j));
7487        if (dict->IsKey(*k)) {
7488          ASSERT(k->IsNumber());
7489          uint32_t index = static_cast<uint32_t>(k->Number());
7490          if (index < range) {
7491            num_of_elements++;
7492            if (visitor) {
7493              visitor->visit(index, Handle<Object>(dict->ValueAt(j)));
7494            }
7495          }
7496        }
7497      }
7498      break;
7499    }
7500    default:
7501      UNREACHABLE();
7502      break;
7503  }
7504
7505  return num_of_elements;
7506}
7507
7508
7509/**
7510 * A helper function that visits elements of an Array object, and elements
7511 * on its prototypes.
7512 *
7513 * Elements on prototypes are visited first, and only elements whose indices
7514 * less than Array length are visited.
7515 *
7516 * If a ArrayConcatVisitor object is given, the visitor is called with
7517 * parameters, element's index + visitor_index_offset and the element.
7518 *
7519 * The returned number of elements is an upper bound on the actual number
7520 * of elements added. If the same element occurs in more than one object
7521 * in the array's prototype chain, it will be counted more than once, but
7522 * will only occur once in the result.
7523 */
7524static uint32_t IterateArrayAndPrototypeElements(Handle<JSArray> array,
7525                                                 ArrayConcatVisitor* visitor) {
7526  uint32_t range = static_cast<uint32_t>(array->length()->Number());
7527  Handle<Object> obj = array;
7528
7529  static const int kEstimatedPrototypes = 3;
7530  List< Handle<JSObject> > objects(kEstimatedPrototypes);
7531
7532  // Visit prototype first. If an element on the prototype is shadowed by
7533  // the inheritor using the same index, the ArrayConcatVisitor visits
7534  // the prototype element before the shadowing element.
7535  // The visitor can simply overwrite the old value by new value using
7536  // the same index.  This follows Array::concat semantics.
7537  while (!obj->IsNull()) {
7538    objects.Add(Handle<JSObject>::cast(obj));
7539    obj = Handle<Object>(obj->GetPrototype());
7540  }
7541
7542  uint32_t nof_elements = 0;
7543  for (int i = objects.length() - 1; i >= 0; i--) {
7544    Handle<JSObject> obj = objects[i];
7545    uint32_t encountered_elements =
7546        IterateElements(Handle<JSObject>::cast(obj), range, visitor);
7547
7548    if (encountered_elements > JSObject::kMaxElementCount - nof_elements) {
7549      nof_elements = JSObject::kMaxElementCount;
7550    } else {
7551      nof_elements += encountered_elements;
7552    }
7553  }
7554
7555  return nof_elements;
7556}
7557
7558
7559/**
7560 * A helper function of Runtime_ArrayConcat.
7561 *
7562 * The first argument is an Array of arrays and objects. It is the
7563 * same as the arguments array of Array::concat JS function.
7564 *
7565 * If an argument is an Array object, the function visits array
7566 * elements.  If an argument is not an Array object, the function
7567 * visits the object as if it is an one-element array.
7568 *
7569 * If the result array index overflows 32-bit unsigned integer, the rounded
7570 * non-negative number is used as new length. For example, if one
7571 * array length is 2^32 - 1, second array length is 1, the
7572 * concatenated array length is 0.
7573 * TODO(lrn) Change length behavior to ECMAScript 5 specification (length
7574 * is one more than the last array index to get a value assigned).
7575 */
7576static uint32_t IterateArguments(Handle<JSArray> arguments,
7577                                 ArrayConcatVisitor* visitor) {
7578  uint32_t visited_elements = 0;
7579  uint32_t num_of_args = static_cast<uint32_t>(arguments->length()->Number());
7580
7581  for (uint32_t i = 0; i < num_of_args; i++) {
7582    Handle<Object> obj(arguments->GetElement(i));
7583    if (obj->IsJSArray()) {
7584      Handle<JSArray> array = Handle<JSArray>::cast(obj);
7585      uint32_t len = static_cast<uint32_t>(array->length()->Number());
7586      uint32_t nof_elements =
7587          IterateArrayAndPrototypeElements(array, visitor);
7588      // Total elements of array and its prototype chain can be more than
7589      // the array length, but ArrayConcat can only concatenate at most
7590      // the array length number of elements. We use the length as an estimate
7591      // for the actual number of elements added.
7592      uint32_t added_elements = (nof_elements > len) ? len : nof_elements;
7593      if (JSArray::kMaxElementCount - visited_elements < added_elements) {
7594        visited_elements = JSArray::kMaxElementCount;
7595      } else {
7596        visited_elements += added_elements;
7597      }
7598      if (visitor) visitor->increase_index_offset(len);
7599    } else {
7600      if (visitor) {
7601        visitor->visit(0, obj);
7602        visitor->increase_index_offset(1);
7603      }
7604      if (visited_elements < JSArray::kMaxElementCount) {
7605        visited_elements++;
7606      }
7607    }
7608  }
7609  return visited_elements;
7610}
7611
7612
7613/**
7614 * Array::concat implementation.
7615 * See ECMAScript 262, 15.4.4.4.
7616 * TODO(lrn): Fix non-compliance for very large concatenations and update to
7617 * following the ECMAScript 5 specification.
7618 */
7619static Object* Runtime_ArrayConcat(Arguments args) {
7620  ASSERT(args.length() == 1);
7621  HandleScope handle_scope;
7622
7623  CONVERT_CHECKED(JSArray, arg_arrays, args[0]);
7624  Handle<JSArray> arguments(arg_arrays);
7625
7626  // Pass 1: estimate the number of elements of the result
7627  // (it could be more than real numbers if prototype has elements).
7628  uint32_t result_length = 0;
7629  uint32_t num_of_args = static_cast<uint32_t>(arguments->length()->Number());
7630
7631  { AssertNoAllocation nogc;
7632    for (uint32_t i = 0; i < num_of_args; i++) {
7633      Object* obj = arguments->GetElement(i);
7634      uint32_t length_estimate;
7635      if (obj->IsJSArray()) {
7636        length_estimate =
7637            static_cast<uint32_t>(JSArray::cast(obj)->length()->Number());
7638      } else {
7639        length_estimate = 1;
7640      }
7641      if (JSObject::kMaxElementCount - result_length < length_estimate) {
7642        result_length = JSObject::kMaxElementCount;
7643        break;
7644      }
7645      result_length += length_estimate;
7646    }
7647  }
7648
7649  // Allocate an empty array, will set length and content later.
7650  Handle<JSArray> result = Factory::NewJSArray(0);
7651
7652  uint32_t estimate_nof_elements = IterateArguments(arguments, NULL);
7653  // If estimated number of elements is more than half of length, a
7654  // fixed array (fast case) is more time and space-efficient than a
7655  // dictionary.
7656  bool fast_case = (estimate_nof_elements * 2) >= result_length;
7657
7658  Handle<FixedArray> storage;
7659  if (fast_case) {
7660    // The backing storage array must have non-existing elements to
7661    // preserve holes across concat operations.
7662    storage = Factory::NewFixedArrayWithHoles(result_length);
7663
7664  } else {
7665    // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
7666    uint32_t at_least_space_for = estimate_nof_elements +
7667                                  (estimate_nof_elements >> 2);
7668    storage = Handle<FixedArray>::cast(
7669                  Factory::NewNumberDictionary(at_least_space_for));
7670  }
7671
7672  Handle<Object> len = Factory::NewNumber(static_cast<double>(result_length));
7673
7674  ArrayConcatVisitor visitor(storage, result_length, fast_case);
7675
7676  IterateArguments(arguments, &visitor);
7677
7678  result->set_length(*len);
7679  // Please note the storage might have changed in the visitor.
7680  result->set_elements(*visitor.storage());
7681
7682  return *result;
7683}
7684
7685
7686// This will not allocate (flatten the string), but it may run
7687// very slowly for very deeply nested ConsStrings.  For debugging use only.
7688static Object* Runtime_GlobalPrint(Arguments args) {
7689  NoHandleAllocation ha;
7690  ASSERT(args.length() == 1);
7691
7692  CONVERT_CHECKED(String, string, args[0]);
7693  StringInputBuffer buffer(string);
7694  while (buffer.has_more()) {
7695    uint16_t character = buffer.GetNext();
7696    PrintF("%c", character);
7697  }
7698  return string;
7699}
7700
7701// Moves all own elements of an object, that are below a limit, to positions
7702// starting at zero. All undefined values are placed after non-undefined values,
7703// and are followed by non-existing element. Does not change the length
7704// property.
7705// Returns the number of non-undefined elements collected.
7706static Object* Runtime_RemoveArrayHoles(Arguments args) {
7707  ASSERT(args.length() == 2);
7708  CONVERT_CHECKED(JSObject, object, args[0]);
7709  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
7710  return object->PrepareElementsForSort(limit);
7711}
7712
7713
7714// Move contents of argument 0 (an array) to argument 1 (an array)
7715static Object* Runtime_MoveArrayContents(Arguments args) {
7716  ASSERT(args.length() == 2);
7717  CONVERT_CHECKED(JSArray, from, args[0]);
7718  CONVERT_CHECKED(JSArray, to, args[1]);
7719  to->SetContent(FixedArray::cast(from->elements()));
7720  to->set_length(from->length());
7721  from->SetContent(Heap::empty_fixed_array());
7722  from->set_length(Smi::FromInt(0));
7723  return to;
7724}
7725
7726
7727// How many elements does this array have?
7728static Object* Runtime_EstimateNumberOfElements(Arguments args) {
7729  ASSERT(args.length() == 1);
7730  CONVERT_CHECKED(JSArray, array, args[0]);
7731  HeapObject* elements = array->elements();
7732  if (elements->IsDictionary()) {
7733    return Smi::FromInt(NumberDictionary::cast(elements)->NumberOfElements());
7734  } else {
7735    return array->length();
7736  }
7737}
7738
7739
7740static Object* Runtime_SwapElements(Arguments args) {
7741  HandleScope handle_scope;
7742
7743  ASSERT_EQ(3, args.length());
7744
7745  CONVERT_ARG_CHECKED(JSObject, object, 0);
7746  Handle<Object> key1 = args.at<Object>(1);
7747  Handle<Object> key2 = args.at<Object>(2);
7748
7749  uint32_t index1, index2;
7750  if (!Array::IndexFromObject(*key1, &index1)
7751      || !Array::IndexFromObject(*key2, &index2)) {
7752    return Top::ThrowIllegalOperation();
7753  }
7754
7755  Handle<JSObject> jsobject = Handle<JSObject>::cast(object);
7756  Handle<Object> tmp1 = GetElement(jsobject, index1);
7757  Handle<Object> tmp2 = GetElement(jsobject, index2);
7758
7759  SetElement(jsobject, index1, tmp2);
7760  SetElement(jsobject, index2, tmp1);
7761
7762  return Heap::undefined_value();
7763}
7764
7765
7766// Returns an array that tells you where in the [0, length) interval an array
7767// might have elements.  Can either return keys or intervals.  Keys can have
7768// gaps in (undefined).  Intervals can also span over some undefined keys.
7769static Object* Runtime_GetArrayKeys(Arguments args) {
7770  ASSERT(args.length() == 2);
7771  HandleScope scope;
7772  CONVERT_ARG_CHECKED(JSObject, array, 0);
7773  CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
7774  if (array->elements()->IsDictionary()) {
7775    // Create an array and get all the keys into it, then remove all the
7776    // keys that are not integers in the range 0 to length-1.
7777    Handle<FixedArray> keys = GetKeysInFixedArrayFor(array, INCLUDE_PROTOS);
7778    int keys_length = keys->length();
7779    for (int i = 0; i < keys_length; i++) {
7780      Object* key = keys->get(i);
7781      uint32_t index;
7782      if (!Array::IndexFromObject(key, &index) || index >= length) {
7783        // Zap invalid keys.
7784        keys->set_undefined(i);
7785      }
7786    }
7787    return *Factory::NewJSArrayWithElements(keys);
7788  } else {
7789    Handle<FixedArray> single_interval = Factory::NewFixedArray(2);
7790    // -1 means start of array.
7791    single_interval->set(0, Smi::FromInt(-1));
7792    uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
7793    uint32_t min_length = actual_length < length ? actual_length : length;
7794    Handle<Object> length_object =
7795        Factory::NewNumber(static_cast<double>(min_length));
7796    single_interval->set(1, *length_object);
7797    return *Factory::NewJSArrayWithElements(single_interval);
7798  }
7799}
7800
7801
7802// DefineAccessor takes an optional final argument which is the
7803// property attributes (eg, DONT_ENUM, DONT_DELETE).  IMPORTANT: due
7804// to the way accessors are implemented, it is set for both the getter
7805// and setter on the first call to DefineAccessor and ignored on
7806// subsequent calls.
7807static Object* Runtime_DefineAccessor(Arguments args) {
7808  RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
7809  // Compute attributes.
7810  PropertyAttributes attributes = NONE;
7811  if (args.length() == 5) {
7812    CONVERT_CHECKED(Smi, attrs, args[4]);
7813    int value = attrs->value();
7814    // Only attribute bits should be set.
7815    ASSERT((value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
7816    attributes = static_cast<PropertyAttributes>(value);
7817  }
7818
7819  CONVERT_CHECKED(JSObject, obj, args[0]);
7820  CONVERT_CHECKED(String, name, args[1]);
7821  CONVERT_CHECKED(Smi, flag, args[2]);
7822  CONVERT_CHECKED(JSFunction, fun, args[3]);
7823  return obj->DefineAccessor(name, flag->value() == 0, fun, attributes);
7824}
7825
7826
7827static Object* Runtime_LookupAccessor(Arguments args) {
7828  ASSERT(args.length() == 3);
7829  CONVERT_CHECKED(JSObject, obj, args[0]);
7830  CONVERT_CHECKED(String, name, args[1]);
7831  CONVERT_CHECKED(Smi, flag, args[2]);
7832  return obj->LookupAccessor(name, flag->value() == 0);
7833}
7834
7835
7836#ifdef ENABLE_DEBUGGER_SUPPORT
7837static Object* Runtime_DebugBreak(Arguments args) {
7838  ASSERT(args.length() == 0);
7839  return Execution::DebugBreakHelper();
7840}
7841
7842
7843// Helper functions for wrapping and unwrapping stack frame ids.
7844static Smi* WrapFrameId(StackFrame::Id id) {
7845  ASSERT(IsAligned(OffsetFrom(id), static_cast<intptr_t>(4)));
7846  return Smi::FromInt(id >> 2);
7847}
7848
7849
7850static StackFrame::Id UnwrapFrameId(Smi* wrapped) {
7851  return static_cast<StackFrame::Id>(wrapped->value() << 2);
7852}
7853
7854
7855// Adds a JavaScript function as a debug event listener.
7856// args[0]: debug event listener function to set or null or undefined for
7857//          clearing the event listener function
7858// args[1]: object supplied during callback
7859static Object* Runtime_SetDebugEventListener(Arguments args) {
7860  ASSERT(args.length() == 2);
7861  RUNTIME_ASSERT(args[0]->IsJSFunction() ||
7862                 args[0]->IsUndefined() ||
7863                 args[0]->IsNull());
7864  Handle<Object> callback = args.at<Object>(0);
7865  Handle<Object> data = args.at<Object>(1);
7866  Debugger::SetEventListener(callback, data);
7867
7868  return Heap::undefined_value();
7869}
7870
7871
7872static Object* Runtime_Break(Arguments args) {
7873  ASSERT(args.length() == 0);
7874  StackGuard::DebugBreak();
7875  return Heap::undefined_value();
7876}
7877
7878
7879static Object* DebugLookupResultValue(Object* receiver, String* name,
7880                                      LookupResult* result,
7881                                      bool* caught_exception) {
7882  Object* value;
7883  switch (result->type()) {
7884    case NORMAL:
7885      value = result->holder()->GetNormalizedProperty(result);
7886      if (value->IsTheHole()) {
7887        return Heap::undefined_value();
7888      }
7889      return value;
7890    case FIELD:
7891      value =
7892          JSObject::cast(
7893              result->holder())->FastPropertyAt(result->GetFieldIndex());
7894      if (value->IsTheHole()) {
7895        return Heap::undefined_value();
7896      }
7897      return value;
7898    case CONSTANT_FUNCTION:
7899      return result->GetConstantFunction();
7900    case CALLBACKS: {
7901      Object* structure = result->GetCallbackObject();
7902      if (structure->IsProxy() || structure->IsAccessorInfo()) {
7903        value = receiver->GetPropertyWithCallback(
7904            receiver, structure, name, result->holder());
7905        if (value->IsException()) {
7906          value = Top::pending_exception();
7907          Top::clear_pending_exception();
7908          if (caught_exception != NULL) {
7909            *caught_exception = true;
7910          }
7911        }
7912        return value;
7913      } else {
7914        return Heap::undefined_value();
7915      }
7916    }
7917    case INTERCEPTOR:
7918    case MAP_TRANSITION:
7919    case CONSTANT_TRANSITION:
7920    case NULL_DESCRIPTOR:
7921      return Heap::undefined_value();
7922    default:
7923      UNREACHABLE();
7924  }
7925  UNREACHABLE();
7926  return Heap::undefined_value();
7927}
7928
7929
7930// Get debugger related details for an object property.
7931// args[0]: object holding property
7932// args[1]: name of the property
7933//
7934// The array returned contains the following information:
7935// 0: Property value
7936// 1: Property details
7937// 2: Property value is exception
7938// 3: Getter function if defined
7939// 4: Setter function if defined
7940// Items 2-4 are only filled if the property has either a getter or a setter
7941// defined through __defineGetter__ and/or __defineSetter__.
7942static Object* Runtime_DebugGetPropertyDetails(Arguments args) {
7943  HandleScope scope;
7944
7945  ASSERT(args.length() == 2);
7946
7947  CONVERT_ARG_CHECKED(JSObject, obj, 0);
7948  CONVERT_ARG_CHECKED(String, name, 1);
7949
7950  // Make sure to set the current context to the context before the debugger was
7951  // entered (if the debugger is entered). The reason for switching context here
7952  // is that for some property lookups (accessors and interceptors) callbacks
7953  // into the embedding application can occour, and the embedding application
7954  // could have the assumption that its own global context is the current
7955  // context and not some internal debugger context.
7956  SaveContext save;
7957  if (Debug::InDebugger()) {
7958    Top::set_context(*Debug::debugger_entry()->GetContext());
7959  }
7960
7961  // Skip the global proxy as it has no properties and always delegates to the
7962  // real global object.
7963  if (obj->IsJSGlobalProxy()) {
7964    obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
7965  }
7966
7967
7968  // Check if the name is trivially convertible to an index and get the element
7969  // if so.
7970  uint32_t index;
7971  if (name->AsArrayIndex(&index)) {
7972    Handle<FixedArray> details = Factory::NewFixedArray(2);
7973    details->set(0, Runtime::GetElementOrCharAt(obj, index));
7974    details->set(1, PropertyDetails(NONE, NORMAL).AsSmi());
7975    return *Factory::NewJSArrayWithElements(details);
7976  }
7977
7978  // Find the number of objects making up this.
7979  int length = LocalPrototypeChainLength(*obj);
7980
7981  // Try local lookup on each of the objects.
7982  Handle<JSObject> jsproto = obj;
7983  for (int i = 0; i < length; i++) {
7984    LookupResult result;
7985    jsproto->LocalLookup(*name, &result);
7986    if (result.IsProperty()) {
7987      // LookupResult is not GC safe as it holds raw object pointers.
7988      // GC can happen later in this code so put the required fields into
7989      // local variables using handles when required for later use.
7990      PropertyType result_type = result.type();
7991      Handle<Object> result_callback_obj;
7992      if (result_type == CALLBACKS) {
7993        result_callback_obj = Handle<Object>(result.GetCallbackObject());
7994      }
7995      Smi* property_details = result.GetPropertyDetails().AsSmi();
7996      // DebugLookupResultValue can cause GC so details from LookupResult needs
7997      // to be copied to handles before this.
7998      bool caught_exception = false;
7999      Object* raw_value = DebugLookupResultValue(*obj, *name, &result,
8000                                                 &caught_exception);
8001      if (raw_value->IsFailure()) return raw_value;
8002      Handle<Object> value(raw_value);
8003
8004      // If the callback object is a fixed array then it contains JavaScript
8005      // getter and/or setter.
8006      bool hasJavaScriptAccessors = result_type == CALLBACKS &&
8007                                    result_callback_obj->IsFixedArray();
8008      Handle<FixedArray> details =
8009          Factory::NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
8010      details->set(0, *value);
8011      details->set(1, property_details);
8012      if (hasJavaScriptAccessors) {
8013        details->set(2,
8014                     caught_exception ? Heap::true_value()
8015                                      : Heap::false_value());
8016        details->set(3, FixedArray::cast(*result_callback_obj)->get(0));
8017        details->set(4, FixedArray::cast(*result_callback_obj)->get(1));
8018      }
8019
8020      return *Factory::NewJSArrayWithElements(details);
8021    }
8022    if (i < length - 1) {
8023      jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
8024    }
8025  }
8026
8027  return Heap::undefined_value();
8028}
8029
8030
8031static Object* Runtime_DebugGetProperty(Arguments args) {
8032  HandleScope scope;
8033
8034  ASSERT(args.length() == 2);
8035
8036  CONVERT_ARG_CHECKED(JSObject, obj, 0);
8037  CONVERT_ARG_CHECKED(String, name, 1);
8038
8039  LookupResult result;
8040  obj->Lookup(*name, &result);
8041  if (result.IsProperty()) {
8042    return DebugLookupResultValue(*obj, *name, &result, NULL);
8043  }
8044  return Heap::undefined_value();
8045}
8046
8047
8048// Return the property type calculated from the property details.
8049// args[0]: smi with property details.
8050static Object* Runtime_DebugPropertyTypeFromDetails(Arguments args) {
8051  ASSERT(args.length() == 1);
8052  CONVERT_CHECKED(Smi, details, args[0]);
8053  PropertyType type = PropertyDetails(details).type();
8054  return Smi::FromInt(static_cast<int>(type));
8055}
8056
8057
8058// Return the property attribute calculated from the property details.
8059// args[0]: smi with property details.
8060static Object* Runtime_DebugPropertyAttributesFromDetails(Arguments args) {
8061  ASSERT(args.length() == 1);
8062  CONVERT_CHECKED(Smi, details, args[0]);
8063  PropertyAttributes attributes = PropertyDetails(details).attributes();
8064  return Smi::FromInt(static_cast<int>(attributes));
8065}
8066
8067
8068// Return the property insertion index calculated from the property details.
8069// args[0]: smi with property details.
8070static Object* Runtime_DebugPropertyIndexFromDetails(Arguments args) {
8071  ASSERT(args.length() == 1);
8072  CONVERT_CHECKED(Smi, details, args[0]);
8073  int index = PropertyDetails(details).index();
8074  return Smi::FromInt(index);
8075}
8076
8077
8078// Return property value from named interceptor.
8079// args[0]: object
8080// args[1]: property name
8081static Object* Runtime_DebugNamedInterceptorPropertyValue(Arguments args) {
8082  HandleScope scope;
8083  ASSERT(args.length() == 2);
8084  CONVERT_ARG_CHECKED(JSObject, obj, 0);
8085  RUNTIME_ASSERT(obj->HasNamedInterceptor());
8086  CONVERT_ARG_CHECKED(String, name, 1);
8087
8088  PropertyAttributes attributes;
8089  return obj->GetPropertyWithInterceptor(*obj, *name, &attributes);
8090}
8091
8092
8093// Return element value from indexed interceptor.
8094// args[0]: object
8095// args[1]: index
8096static Object* Runtime_DebugIndexedInterceptorElementValue(Arguments args) {
8097  HandleScope scope;
8098  ASSERT(args.length() == 2);
8099  CONVERT_ARG_CHECKED(JSObject, obj, 0);
8100  RUNTIME_ASSERT(obj->HasIndexedInterceptor());
8101  CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
8102
8103  return obj->GetElementWithInterceptor(*obj, index);
8104}
8105
8106
8107static Object* Runtime_CheckExecutionState(Arguments args) {
8108  ASSERT(args.length() >= 1);
8109  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
8110  // Check that the break id is valid.
8111  if (Debug::break_id() == 0 || break_id != Debug::break_id()) {
8112    return Top::Throw(Heap::illegal_execution_state_symbol());
8113  }
8114
8115  return Heap::true_value();
8116}
8117
8118
8119static Object* Runtime_GetFrameCount(Arguments args) {
8120  HandleScope scope;
8121  ASSERT(args.length() == 1);
8122
8123  // Check arguments.
8124  Object* result = Runtime_CheckExecutionState(args);
8125  if (result->IsFailure()) return result;
8126
8127  // Count all frames which are relevant to debugging stack trace.
8128  int n = 0;
8129  StackFrame::Id id = Debug::break_frame_id();
8130  if (id == StackFrame::NO_ID) {
8131    // If there is no JavaScript stack frame count is 0.
8132    return Smi::FromInt(0);
8133  }
8134  for (JavaScriptFrameIterator it(id); !it.done(); it.Advance()) n++;
8135  return Smi::FromInt(n);
8136}
8137
8138
8139static const int kFrameDetailsFrameIdIndex = 0;
8140static const int kFrameDetailsReceiverIndex = 1;
8141static const int kFrameDetailsFunctionIndex = 2;
8142static const int kFrameDetailsArgumentCountIndex = 3;
8143static const int kFrameDetailsLocalCountIndex = 4;
8144static const int kFrameDetailsSourcePositionIndex = 5;
8145static const int kFrameDetailsConstructCallIndex = 6;
8146static const int kFrameDetailsDebuggerFrameIndex = 7;
8147static const int kFrameDetailsFirstDynamicIndex = 8;
8148
8149// Return an array with frame details
8150// args[0]: number: break id
8151// args[1]: number: frame index
8152//
8153// The array returned contains the following information:
8154// 0: Frame id
8155// 1: Receiver
8156// 2: Function
8157// 3: Argument count
8158// 4: Local count
8159// 5: Source position
8160// 6: Constructor call
8161// 7: Debugger frame
8162// Arguments name, value
8163// Locals name, value
8164static Object* Runtime_GetFrameDetails(Arguments args) {
8165  HandleScope scope;
8166  ASSERT(args.length() == 2);
8167
8168  // Check arguments.
8169  Object* check = Runtime_CheckExecutionState(args);
8170  if (check->IsFailure()) return check;
8171  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
8172
8173  // Find the relevant frame with the requested index.
8174  StackFrame::Id id = Debug::break_frame_id();
8175  if (id == StackFrame::NO_ID) {
8176    // If there are no JavaScript stack frames return undefined.
8177    return Heap::undefined_value();
8178  }
8179  int count = 0;
8180  JavaScriptFrameIterator it(id);
8181  for (; !it.done(); it.Advance()) {
8182    if (count == index) break;
8183    count++;
8184  }
8185  if (it.done()) return Heap::undefined_value();
8186
8187  // Traverse the saved contexts chain to find the active context for the
8188  // selected frame.
8189  SaveContext* save = Top::save_context();
8190  while (save != NULL && !save->below(it.frame())) {
8191    save = save->prev();
8192  }
8193  ASSERT(save != NULL);
8194
8195  // Get the frame id.
8196  Handle<Object> frame_id(WrapFrameId(it.frame()->id()));
8197
8198  // Find source position.
8199  int position = it.frame()->code()->SourcePosition(it.frame()->pc());
8200
8201  // Check for constructor frame.
8202  bool constructor = it.frame()->IsConstructor();
8203
8204  // Get code and read scope info from it for local variable information.
8205  Handle<Code> code(it.frame()->code());
8206  ScopeInfo<> info(*code);
8207
8208  // Get the context.
8209  Handle<Context> context(Context::cast(it.frame()->context()));
8210
8211  // Get the locals names and values into a temporary array.
8212  //
8213  // TODO(1240907): Hide compiler-introduced stack variables
8214  // (e.g. .result)?  For users of the debugger, they will probably be
8215  // confusing.
8216  Handle<FixedArray> locals = Factory::NewFixedArray(info.NumberOfLocals() * 2);
8217  for (int i = 0; i < info.NumberOfLocals(); i++) {
8218    // Name of the local.
8219    locals->set(i * 2, *info.LocalName(i));
8220
8221    // Fetch the value of the local - either from the stack or from a
8222    // heap-allocated context.
8223    if (i < info.number_of_stack_slots()) {
8224      locals->set(i * 2 + 1, it.frame()->GetExpression(i));
8225    } else {
8226      Handle<String> name = info.LocalName(i);
8227      // Traverse the context chain to the function context as all local
8228      // variables stored in the context will be on the function context.
8229      while (!context->is_function_context()) {
8230        context = Handle<Context>(context->previous());
8231      }
8232      ASSERT(context->is_function_context());
8233      locals->set(i * 2 + 1,
8234                  context->get(ScopeInfo<>::ContextSlotIndex(*code, *name,
8235                                                             NULL)));
8236    }
8237  }
8238
8239  // Now advance to the arguments adapter frame (if any). If contains all
8240  // the provided parameters and
8241
8242  // Now advance to the arguments adapter frame (if any). It contains all
8243  // the provided parameters whereas the function frame always have the number
8244  // of arguments matching the functions parameters. The rest of the
8245  // information (except for what is collected above) is the same.
8246  it.AdvanceToArgumentsFrame();
8247
8248  // Find the number of arguments to fill. At least fill the number of
8249  // parameters for the function and fill more if more parameters are provided.
8250  int argument_count = info.number_of_parameters();
8251  if (argument_count < it.frame()->GetProvidedParametersCount()) {
8252    argument_count = it.frame()->GetProvidedParametersCount();
8253  }
8254
8255  // Calculate the size of the result.
8256  int details_size = kFrameDetailsFirstDynamicIndex +
8257                     2 * (argument_count + info.NumberOfLocals());
8258  Handle<FixedArray> details = Factory::NewFixedArray(details_size);
8259
8260  // Add the frame id.
8261  details->set(kFrameDetailsFrameIdIndex, *frame_id);
8262
8263  // Add the function (same as in function frame).
8264  details->set(kFrameDetailsFunctionIndex, it.frame()->function());
8265
8266  // Add the arguments count.
8267  details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
8268
8269  // Add the locals count
8270  details->set(kFrameDetailsLocalCountIndex,
8271               Smi::FromInt(info.NumberOfLocals()));
8272
8273  // Add the source position.
8274  if (position != RelocInfo::kNoPosition) {
8275    details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
8276  } else {
8277    details->set(kFrameDetailsSourcePositionIndex, Heap::undefined_value());
8278  }
8279
8280  // Add the constructor information.
8281  details->set(kFrameDetailsConstructCallIndex, Heap::ToBoolean(constructor));
8282
8283  // Add information on whether this frame is invoked in the debugger context.
8284  details->set(kFrameDetailsDebuggerFrameIndex,
8285               Heap::ToBoolean(*save->context() == *Debug::debug_context()));
8286
8287  // Fill the dynamic part.
8288  int details_index = kFrameDetailsFirstDynamicIndex;
8289
8290  // Add arguments name and value.
8291  for (int i = 0; i < argument_count; i++) {
8292    // Name of the argument.
8293    if (i < info.number_of_parameters()) {
8294      details->set(details_index++, *info.parameter_name(i));
8295    } else {
8296      details->set(details_index++, Heap::undefined_value());
8297    }
8298
8299    // Parameter value.
8300    if (i < it.frame()->GetProvidedParametersCount()) {
8301      details->set(details_index++, it.frame()->GetParameter(i));
8302    } else {
8303      details->set(details_index++, Heap::undefined_value());
8304    }
8305  }
8306
8307  // Add locals name and value from the temporary copy from the function frame.
8308  for (int i = 0; i < info.NumberOfLocals() * 2; i++) {
8309    details->set(details_index++, locals->get(i));
8310  }
8311
8312  // Add the receiver (same as in function frame).
8313  // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
8314  // THE FRAME ITERATOR TO WRAP THE RECEIVER.
8315  Handle<Object> receiver(it.frame()->receiver());
8316  if (!receiver->IsJSObject()) {
8317    // If the receiver is NOT a JSObject we have hit an optimization
8318    // where a value object is not converted into a wrapped JS objects.
8319    // To hide this optimization from the debugger, we wrap the receiver
8320    // by creating correct wrapper object based on the calling frame's
8321    // global context.
8322    it.Advance();
8323    Handle<Context> calling_frames_global_context(
8324        Context::cast(Context::cast(it.frame()->context())->global_context()));
8325    receiver = Factory::ToObject(receiver, calling_frames_global_context);
8326  }
8327  details->set(kFrameDetailsReceiverIndex, *receiver);
8328
8329  ASSERT_EQ(details_size, details_index);
8330  return *Factory::NewJSArrayWithElements(details);
8331}
8332
8333
8334// Copy all the context locals into an object used to materialize a scope.
8335static void CopyContextLocalsToScopeObject(Handle<Code> code,
8336                                           ScopeInfo<>& scope_info,
8337                                           Handle<Context> context,
8338                                           Handle<JSObject> scope_object) {
8339  // Fill all context locals to the context extension.
8340  for (int i = Context::MIN_CONTEXT_SLOTS;
8341       i < scope_info.number_of_context_slots();
8342       i++) {
8343    int context_index =
8344        ScopeInfo<>::ContextSlotIndex(*code,
8345                                      *scope_info.context_slot_name(i),
8346                                      NULL);
8347
8348    // Don't include the arguments shadow (.arguments) context variable.
8349    if (*scope_info.context_slot_name(i) != Heap::arguments_shadow_symbol()) {
8350      SetProperty(scope_object,
8351                  scope_info.context_slot_name(i),
8352                  Handle<Object>(context->get(context_index)), NONE);
8353    }
8354  }
8355}
8356
8357
8358// Create a plain JSObject which materializes the local scope for the specified
8359// frame.
8360static Handle<JSObject> MaterializeLocalScope(JavaScriptFrame* frame) {
8361  Handle<JSFunction> function(JSFunction::cast(frame->function()));
8362  Handle<Code> code(function->code());
8363  ScopeInfo<> scope_info(*code);
8364
8365  // Allocate and initialize a JSObject with all the arguments, stack locals
8366  // heap locals and extension properties of the debugged function.
8367  Handle<JSObject> local_scope = Factory::NewJSObject(Top::object_function());
8368
8369  // First fill all parameters.
8370  for (int i = 0; i < scope_info.number_of_parameters(); ++i) {
8371    SetProperty(local_scope,
8372                scope_info.parameter_name(i),
8373                Handle<Object>(frame->GetParameter(i)), NONE);
8374  }
8375
8376  // Second fill all stack locals.
8377  for (int i = 0; i < scope_info.number_of_stack_slots(); i++) {
8378    SetProperty(local_scope,
8379                scope_info.stack_slot_name(i),
8380                Handle<Object>(frame->GetExpression(i)), NONE);
8381  }
8382
8383  // Third fill all context locals.
8384  Handle<Context> frame_context(Context::cast(frame->context()));
8385  Handle<Context> function_context(frame_context->fcontext());
8386  CopyContextLocalsToScopeObject(code, scope_info,
8387                                 function_context, local_scope);
8388
8389  // Finally copy any properties from the function context extension. This will
8390  // be variables introduced by eval.
8391  if (function_context->closure() == *function) {
8392    if (function_context->has_extension() &&
8393        !function_context->IsGlobalContext()) {
8394      Handle<JSObject> ext(JSObject::cast(function_context->extension()));
8395      Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS);
8396      for (int i = 0; i < keys->length(); i++) {
8397        // Names of variables introduced by eval are strings.
8398        ASSERT(keys->get(i)->IsString());
8399        Handle<String> key(String::cast(keys->get(i)));
8400        SetProperty(local_scope, key, GetProperty(ext, key), NONE);
8401      }
8402    }
8403  }
8404  return local_scope;
8405}
8406
8407
8408// Create a plain JSObject which materializes the closure content for the
8409// context.
8410static Handle<JSObject> MaterializeClosure(Handle<Context> context) {
8411  ASSERT(context->is_function_context());
8412
8413  Handle<Code> code(context->closure()->code());
8414  ScopeInfo<> scope_info(*code);
8415
8416  // Allocate and initialize a JSObject with all the content of theis function
8417  // closure.
8418  Handle<JSObject> closure_scope = Factory::NewJSObject(Top::object_function());
8419
8420  // Check whether the arguments shadow object exists.
8421  int arguments_shadow_index =
8422      ScopeInfo<>::ContextSlotIndex(*code,
8423                                    Heap::arguments_shadow_symbol(),
8424                                    NULL);
8425  if (arguments_shadow_index >= 0) {
8426    // In this case all the arguments are available in the arguments shadow
8427    // object.
8428    Handle<JSObject> arguments_shadow(
8429        JSObject::cast(context->get(arguments_shadow_index)));
8430    for (int i = 0; i < scope_info.number_of_parameters(); ++i) {
8431      SetProperty(closure_scope,
8432                  scope_info.parameter_name(i),
8433                  Handle<Object>(arguments_shadow->GetElement(i)), NONE);
8434    }
8435  }
8436
8437  // Fill all context locals to the context extension.
8438  CopyContextLocalsToScopeObject(code, scope_info, context, closure_scope);
8439
8440  // Finally copy any properties from the function context extension. This will
8441  // be variables introduced by eval.
8442  if (context->has_extension()) {
8443    Handle<JSObject> ext(JSObject::cast(context->extension()));
8444    Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS);
8445    for (int i = 0; i < keys->length(); i++) {
8446      // Names of variables introduced by eval are strings.
8447      ASSERT(keys->get(i)->IsString());
8448      Handle<String> key(String::cast(keys->get(i)));
8449      SetProperty(closure_scope, key, GetProperty(ext, key), NONE);
8450    }
8451  }
8452
8453  return closure_scope;
8454}
8455
8456
8457// Iterate over the actual scopes visible from a stack frame. All scopes are
8458// backed by an actual context except the local scope, which is inserted
8459// "artifically" in the context chain.
8460class ScopeIterator {
8461 public:
8462  enum ScopeType {
8463    ScopeTypeGlobal = 0,
8464    ScopeTypeLocal,
8465    ScopeTypeWith,
8466    ScopeTypeClosure,
8467    // Every catch block contains an implicit with block (its parameter is
8468    // a JSContextExtensionObject) that extends current scope with a variable
8469    // holding exception object. Such with blocks are treated as scopes of their
8470    // own type.
8471    ScopeTypeCatch
8472  };
8473
8474  explicit ScopeIterator(JavaScriptFrame* frame)
8475    : frame_(frame),
8476      function_(JSFunction::cast(frame->function())),
8477      context_(Context::cast(frame->context())),
8478      local_done_(false),
8479      at_local_(false) {
8480
8481    // Check whether the first scope is actually a local scope.
8482    if (context_->IsGlobalContext()) {
8483      // If there is a stack slot for .result then this local scope has been
8484      // created for evaluating top level code and it is not a real local scope.
8485      // Checking for the existence of .result seems fragile, but the scope info
8486      // saved with the code object does not otherwise have that information.
8487      Handle<Code> code(function_->code());
8488      int index = ScopeInfo<>::StackSlotIndex(*code, Heap::result_symbol());
8489      at_local_ = index < 0;
8490    } else if (context_->is_function_context()) {
8491      at_local_ = true;
8492    }
8493  }
8494
8495  // More scopes?
8496  bool Done() { return context_.is_null(); }
8497
8498  // Move to the next scope.
8499  void Next() {
8500    // If at a local scope mark the local scope as passed.
8501    if (at_local_) {
8502      at_local_ = false;
8503      local_done_ = true;
8504
8505      // If the current context is not associated with the local scope the
8506      // current context is the next real scope, so don't move to the next
8507      // context in this case.
8508      if (context_->closure() != *function_) {
8509        return;
8510      }
8511    }
8512
8513    // The global scope is always the last in the chain.
8514    if (context_->IsGlobalContext()) {
8515      context_ = Handle<Context>();
8516      return;
8517    }
8518
8519    // Move to the next context.
8520    if (context_->is_function_context()) {
8521      context_ = Handle<Context>(Context::cast(context_->closure()->context()));
8522    } else {
8523      context_ = Handle<Context>(context_->previous());
8524    }
8525
8526    // If passing the local scope indicate that the current scope is now the
8527    // local scope.
8528    if (!local_done_ &&
8529        (context_->IsGlobalContext() || (context_->is_function_context()))) {
8530      at_local_ = true;
8531    }
8532  }
8533
8534  // Return the type of the current scope.
8535  int Type() {
8536    if (at_local_) {
8537      return ScopeTypeLocal;
8538    }
8539    if (context_->IsGlobalContext()) {
8540      ASSERT(context_->global()->IsGlobalObject());
8541      return ScopeTypeGlobal;
8542    }
8543    if (context_->is_function_context()) {
8544      return ScopeTypeClosure;
8545    }
8546    ASSERT(context_->has_extension());
8547    // Current scope is either an explicit with statement or a with statement
8548    // implicitely generated for a catch block.
8549    // If the extension object here is a JSContextExtensionObject then
8550    // current with statement is one frome a catch block otherwise it's a
8551    // regular with statement.
8552    if (context_->extension()->IsJSContextExtensionObject()) {
8553      return ScopeTypeCatch;
8554    }
8555    return ScopeTypeWith;
8556  }
8557
8558  // Return the JavaScript object with the content of the current scope.
8559  Handle<JSObject> ScopeObject() {
8560    switch (Type()) {
8561      case ScopeIterator::ScopeTypeGlobal:
8562        return Handle<JSObject>(CurrentContext()->global());
8563        break;
8564      case ScopeIterator::ScopeTypeLocal:
8565        // Materialize the content of the local scope into a JSObject.
8566        return MaterializeLocalScope(frame_);
8567        break;
8568      case ScopeIterator::ScopeTypeWith:
8569      case ScopeIterator::ScopeTypeCatch:
8570        // Return the with object.
8571        return Handle<JSObject>(CurrentContext()->extension());
8572        break;
8573      case ScopeIterator::ScopeTypeClosure:
8574        // Materialize the content of the closure scope into a JSObject.
8575        return MaterializeClosure(CurrentContext());
8576        break;
8577    }
8578    UNREACHABLE();
8579    return Handle<JSObject>();
8580  }
8581
8582  // Return the context for this scope. For the local context there might not
8583  // be an actual context.
8584  Handle<Context> CurrentContext() {
8585    if (at_local_ && context_->closure() != *function_) {
8586      return Handle<Context>();
8587    }
8588    return context_;
8589  }
8590
8591#ifdef DEBUG
8592  // Debug print of the content of the current scope.
8593  void DebugPrint() {
8594    switch (Type()) {
8595      case ScopeIterator::ScopeTypeGlobal:
8596        PrintF("Global:\n");
8597        CurrentContext()->Print();
8598        break;
8599
8600      case ScopeIterator::ScopeTypeLocal: {
8601        PrintF("Local:\n");
8602        Handle<Code> code(function_->code());
8603        ScopeInfo<> scope_info(*code);
8604        scope_info.Print();
8605        if (!CurrentContext().is_null()) {
8606          CurrentContext()->Print();
8607          if (CurrentContext()->has_extension()) {
8608            Handle<JSObject> extension =
8609                Handle<JSObject>(CurrentContext()->extension());
8610            if (extension->IsJSContextExtensionObject()) {
8611              extension->Print();
8612            }
8613          }
8614        }
8615        break;
8616      }
8617
8618      case ScopeIterator::ScopeTypeWith: {
8619        PrintF("With:\n");
8620        Handle<JSObject> extension =
8621            Handle<JSObject>(CurrentContext()->extension());
8622        extension->Print();
8623        break;
8624      }
8625
8626      case ScopeIterator::ScopeTypeCatch: {
8627        PrintF("Catch:\n");
8628        Handle<JSObject> extension =
8629            Handle<JSObject>(CurrentContext()->extension());
8630        extension->Print();
8631        break;
8632      }
8633
8634      case ScopeIterator::ScopeTypeClosure: {
8635        PrintF("Closure:\n");
8636        CurrentContext()->Print();
8637        if (CurrentContext()->has_extension()) {
8638          Handle<JSObject> extension =
8639              Handle<JSObject>(CurrentContext()->extension());
8640          if (extension->IsJSContextExtensionObject()) {
8641            extension->Print();
8642          }
8643        }
8644        break;
8645      }
8646
8647      default:
8648        UNREACHABLE();
8649    }
8650    PrintF("\n");
8651  }
8652#endif
8653
8654 private:
8655  JavaScriptFrame* frame_;
8656  Handle<JSFunction> function_;
8657  Handle<Context> context_;
8658  bool local_done_;
8659  bool at_local_;
8660
8661  DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
8662};
8663
8664
8665static Object* Runtime_GetScopeCount(Arguments args) {
8666  HandleScope scope;
8667  ASSERT(args.length() == 2);
8668
8669  // Check arguments.
8670  Object* check = Runtime_CheckExecutionState(args);
8671  if (check->IsFailure()) return check;
8672  CONVERT_CHECKED(Smi, wrapped_id, args[1]);
8673
8674  // Get the frame where the debugging is performed.
8675  StackFrame::Id id = UnwrapFrameId(wrapped_id);
8676  JavaScriptFrameIterator it(id);
8677  JavaScriptFrame* frame = it.frame();
8678
8679  // Count the visible scopes.
8680  int n = 0;
8681  for (ScopeIterator it(frame); !it.Done(); it.Next()) {
8682    n++;
8683  }
8684
8685  return Smi::FromInt(n);
8686}
8687
8688
8689static const int kScopeDetailsTypeIndex = 0;
8690static const int kScopeDetailsObjectIndex = 1;
8691static const int kScopeDetailsSize = 2;
8692
8693// Return an array with scope details
8694// args[0]: number: break id
8695// args[1]: number: frame index
8696// args[2]: number: scope index
8697//
8698// The array returned contains the following information:
8699// 0: Scope type
8700// 1: Scope object
8701static Object* Runtime_GetScopeDetails(Arguments args) {
8702  HandleScope scope;
8703  ASSERT(args.length() == 3);
8704
8705  // Check arguments.
8706  Object* check = Runtime_CheckExecutionState(args);
8707  if (check->IsFailure()) return check;
8708  CONVERT_CHECKED(Smi, wrapped_id, args[1]);
8709  CONVERT_NUMBER_CHECKED(int, index, Int32, args[2]);
8710
8711  // Get the frame where the debugging is performed.
8712  StackFrame::Id id = UnwrapFrameId(wrapped_id);
8713  JavaScriptFrameIterator frame_it(id);
8714  JavaScriptFrame* frame = frame_it.frame();
8715
8716  // Find the requested scope.
8717  int n = 0;
8718  ScopeIterator it(frame);
8719  for (; !it.Done() && n < index; it.Next()) {
8720    n++;
8721  }
8722  if (it.Done()) {
8723    return Heap::undefined_value();
8724  }
8725
8726  // Calculate the size of the result.
8727  int details_size = kScopeDetailsSize;
8728  Handle<FixedArray> details = Factory::NewFixedArray(details_size);
8729
8730  // Fill in scope details.
8731  details->set(kScopeDetailsTypeIndex, Smi::FromInt(it.Type()));
8732  details->set(kScopeDetailsObjectIndex, *it.ScopeObject());
8733
8734  return *Factory::NewJSArrayWithElements(details);
8735}
8736
8737
8738static Object* Runtime_DebugPrintScopes(Arguments args) {
8739  HandleScope scope;
8740  ASSERT(args.length() == 0);
8741
8742#ifdef DEBUG
8743  // Print the scopes for the top frame.
8744  StackFrameLocator locator;
8745  JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
8746  for (ScopeIterator it(frame); !it.Done(); it.Next()) {
8747    it.DebugPrint();
8748  }
8749#endif
8750  return Heap::undefined_value();
8751}
8752
8753
8754static Object* Runtime_GetCFrames(Arguments args) {
8755  HandleScope scope;
8756  ASSERT(args.length() == 1);
8757  Object* result = Runtime_CheckExecutionState(args);
8758  if (result->IsFailure()) return result;
8759
8760#if V8_HOST_ARCH_64_BIT
8761  UNIMPLEMENTED();
8762  return Heap::undefined_value();
8763#else
8764
8765  static const int kMaxCFramesSize = 200;
8766  ScopedVector<OS::StackFrame> frames(kMaxCFramesSize);
8767  int frames_count = OS::StackWalk(frames);
8768  if (frames_count == OS::kStackWalkError) {
8769    return Heap::undefined_value();
8770  }
8771
8772  Handle<String> address_str = Factory::LookupAsciiSymbol("address");
8773  Handle<String> text_str = Factory::LookupAsciiSymbol("text");
8774  Handle<FixedArray> frames_array = Factory::NewFixedArray(frames_count);
8775  for (int i = 0; i < frames_count; i++) {
8776    Handle<JSObject> frame_value = Factory::NewJSObject(Top::object_function());
8777    frame_value->SetProperty(
8778        *address_str,
8779        *Factory::NewNumberFromInt(reinterpret_cast<int>(frames[i].address)),
8780        NONE);
8781
8782    // Get the stack walk text for this frame.
8783    Handle<String> frame_text;
8784    int frame_text_length = StrLength(frames[i].text);
8785    if (frame_text_length > 0) {
8786      Vector<const char> str(frames[i].text, frame_text_length);
8787      frame_text = Factory::NewStringFromAscii(str);
8788    }
8789
8790    if (!frame_text.is_null()) {
8791      frame_value->SetProperty(*text_str, *frame_text, NONE);
8792    }
8793
8794    frames_array->set(i, *frame_value);
8795  }
8796  return *Factory::NewJSArrayWithElements(frames_array);
8797#endif  // V8_HOST_ARCH_64_BIT
8798}
8799
8800
8801static Object* Runtime_GetThreadCount(Arguments args) {
8802  HandleScope scope;
8803  ASSERT(args.length() == 1);
8804
8805  // Check arguments.
8806  Object* result = Runtime_CheckExecutionState(args);
8807  if (result->IsFailure()) return result;
8808
8809  // Count all archived V8 threads.
8810  int n = 0;
8811  for (ThreadState* thread = ThreadState::FirstInUse();
8812       thread != NULL;
8813       thread = thread->Next()) {
8814    n++;
8815  }
8816
8817  // Total number of threads is current thread and archived threads.
8818  return Smi::FromInt(n + 1);
8819}
8820
8821
8822static const int kThreadDetailsCurrentThreadIndex = 0;
8823static const int kThreadDetailsThreadIdIndex = 1;
8824static const int kThreadDetailsSize = 2;
8825
8826// Return an array with thread details
8827// args[0]: number: break id
8828// args[1]: number: thread index
8829//
8830// The array returned contains the following information:
8831// 0: Is current thread?
8832// 1: Thread id
8833static Object* Runtime_GetThreadDetails(Arguments args) {
8834  HandleScope scope;
8835  ASSERT(args.length() == 2);
8836
8837  // Check arguments.
8838  Object* check = Runtime_CheckExecutionState(args);
8839  if (check->IsFailure()) return check;
8840  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
8841
8842  // Allocate array for result.
8843  Handle<FixedArray> details = Factory::NewFixedArray(kThreadDetailsSize);
8844
8845  // Thread index 0 is current thread.
8846  if (index == 0) {
8847    // Fill the details.
8848    details->set(kThreadDetailsCurrentThreadIndex, Heap::true_value());
8849    details->set(kThreadDetailsThreadIdIndex,
8850                 Smi::FromInt(ThreadManager::CurrentId()));
8851  } else {
8852    // Find the thread with the requested index.
8853    int n = 1;
8854    ThreadState* thread = ThreadState::FirstInUse();
8855    while (index != n && thread != NULL) {
8856      thread = thread->Next();
8857      n++;
8858    }
8859    if (thread == NULL) {
8860      return Heap::undefined_value();
8861    }
8862
8863    // Fill the details.
8864    details->set(kThreadDetailsCurrentThreadIndex, Heap::false_value());
8865    details->set(kThreadDetailsThreadIdIndex, Smi::FromInt(thread->id()));
8866  }
8867
8868  // Convert to JS array and return.
8869  return *Factory::NewJSArrayWithElements(details);
8870}
8871
8872
8873static Object* Runtime_GetBreakLocations(Arguments args) {
8874  HandleScope scope;
8875  ASSERT(args.length() == 1);
8876
8877  CONVERT_ARG_CHECKED(JSFunction, fun, 0);
8878  Handle<SharedFunctionInfo> shared(fun->shared());
8879  // Find the number of break points
8880  Handle<Object> break_locations = Debug::GetSourceBreakLocations(shared);
8881  if (break_locations->IsUndefined()) return Heap::undefined_value();
8882  // Return array as JS array
8883  return *Factory::NewJSArrayWithElements(
8884      Handle<FixedArray>::cast(break_locations));
8885}
8886
8887
8888// Set a break point in a function
8889// args[0]: function
8890// args[1]: number: break source position (within the function source)
8891// args[2]: number: break point object
8892static Object* Runtime_SetFunctionBreakPoint(Arguments args) {
8893  HandleScope scope;
8894  ASSERT(args.length() == 3);
8895  CONVERT_ARG_CHECKED(JSFunction, fun, 0);
8896  Handle<SharedFunctionInfo> shared(fun->shared());
8897  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
8898  RUNTIME_ASSERT(source_position >= 0);
8899  Handle<Object> break_point_object_arg = args.at<Object>(2);
8900
8901  // Set break point.
8902  Debug::SetBreakPoint(shared, source_position, break_point_object_arg);
8903
8904  return Heap::undefined_value();
8905}
8906
8907
8908Object* Runtime::FindSharedFunctionInfoInScript(Handle<Script> script,
8909                                                int position) {
8910  // Iterate the heap looking for SharedFunctionInfo generated from the
8911  // script. The inner most SharedFunctionInfo containing the source position
8912  // for the requested break point is found.
8913  // NOTE: This might reqire several heap iterations. If the SharedFunctionInfo
8914  // which is found is not compiled it is compiled and the heap is iterated
8915  // again as the compilation might create inner functions from the newly
8916  // compiled function and the actual requested break point might be in one of
8917  // these functions.
8918  bool done = false;
8919  // The current candidate for the source position:
8920  int target_start_position = RelocInfo::kNoPosition;
8921  Handle<SharedFunctionInfo> target;
8922  // The current candidate for the last function in script:
8923  Handle<SharedFunctionInfo> last;
8924  while (!done) {
8925    HeapIterator iterator;
8926    for (HeapObject* obj = iterator.next();
8927         obj != NULL; obj = iterator.next()) {
8928      if (obj->IsSharedFunctionInfo()) {
8929        Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(obj));
8930        if (shared->script() == *script) {
8931          // If the SharedFunctionInfo found has the requested script data and
8932          // contains the source position it is a candidate.
8933          int start_position = shared->function_token_position();
8934          if (start_position == RelocInfo::kNoPosition) {
8935            start_position = shared->start_position();
8936          }
8937          if (start_position <= position &&
8938              position <= shared->end_position()) {
8939            // If there is no candidate or this function is within the current
8940            // candidate this is the new candidate.
8941            if (target.is_null()) {
8942              target_start_position = start_position;
8943              target = shared;
8944            } else {
8945              if (target_start_position == start_position &&
8946                  shared->end_position() == target->end_position()) {
8947                  // If a top-level function contain only one function
8948                  // declartion the source for the top-level and the function is
8949                  // the same. In that case prefer the non top-level function.
8950                if (!shared->is_toplevel()) {
8951                  target_start_position = start_position;
8952                  target = shared;
8953                }
8954              } else if (target_start_position <= start_position &&
8955                         shared->end_position() <= target->end_position()) {
8956                // This containment check includes equality as a function inside
8957                // a top-level function can share either start or end position
8958                // with the top-level function.
8959                target_start_position = start_position;
8960                target = shared;
8961              }
8962            }
8963          }
8964
8965          // Keep track of the last function in the script.
8966          if (last.is_null() ||
8967              shared->end_position() > last->start_position()) {
8968            last = shared;
8969          }
8970        }
8971      }
8972    }
8973
8974    // Make sure some candidate is selected.
8975    if (target.is_null()) {
8976      if (!last.is_null()) {
8977        // Position after the last function - use last.
8978        target = last;
8979      } else {
8980        // Unable to find function - possibly script without any function.
8981        return Heap::undefined_value();
8982      }
8983    }
8984
8985    // If the candidate found is compiled we are done. NOTE: when lazy
8986    // compilation of inner functions is introduced some additional checking
8987    // needs to be done here to compile inner functions.
8988    done = target->is_compiled();
8989    if (!done) {
8990      // If the candidate is not compiled compile it to reveal any inner
8991      // functions which might contain the requested source position.
8992      CompileLazyShared(target, KEEP_EXCEPTION);
8993    }
8994  }
8995
8996  return *target;
8997}
8998
8999
9000// Change the state of a break point in a script. NOTE: Regarding performance
9001// see the NOTE for GetScriptFromScriptData.
9002// args[0]: script to set break point in
9003// args[1]: number: break source position (within the script source)
9004// args[2]: number: break point object
9005static Object* Runtime_SetScriptBreakPoint(Arguments args) {
9006  HandleScope scope;
9007  ASSERT(args.length() == 3);
9008  CONVERT_ARG_CHECKED(JSValue, wrapper, 0);
9009  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
9010  RUNTIME_ASSERT(source_position >= 0);
9011  Handle<Object> break_point_object_arg = args.at<Object>(2);
9012
9013  // Get the script from the script wrapper.
9014  RUNTIME_ASSERT(wrapper->value()->IsScript());
9015  Handle<Script> script(Script::cast(wrapper->value()));
9016
9017  Object* result = Runtime::FindSharedFunctionInfoInScript(
9018      script, source_position);
9019  if (!result->IsUndefined()) {
9020    Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
9021    // Find position within function. The script position might be before the
9022    // source position of the first function.
9023    int position;
9024    if (shared->start_position() > source_position) {
9025      position = 0;
9026    } else {
9027      position = source_position - shared->start_position();
9028    }
9029    Debug::SetBreakPoint(shared, position, break_point_object_arg);
9030  }
9031  return  Heap::undefined_value();
9032}
9033
9034
9035// Clear a break point
9036// args[0]: number: break point object
9037static Object* Runtime_ClearBreakPoint(Arguments args) {
9038  HandleScope scope;
9039  ASSERT(args.length() == 1);
9040  Handle<Object> break_point_object_arg = args.at<Object>(0);
9041
9042  // Clear break point.
9043  Debug::ClearBreakPoint(break_point_object_arg);
9044
9045  return Heap::undefined_value();
9046}
9047
9048
9049// Change the state of break on exceptions
9050// args[0]: boolean indicating uncaught exceptions
9051// args[1]: boolean indicating on/off
9052static Object* Runtime_ChangeBreakOnException(Arguments args) {
9053  HandleScope scope;
9054  ASSERT(args.length() == 2);
9055  ASSERT(args[0]->IsNumber());
9056  ASSERT(args[1]->IsBoolean());
9057
9058  // Update break point state
9059  ExceptionBreakType type =
9060      static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
9061  bool enable = args[1]->ToBoolean()->IsTrue();
9062  Debug::ChangeBreakOnException(type, enable);
9063  return Heap::undefined_value();
9064}
9065
9066
9067// Prepare for stepping
9068// args[0]: break id for checking execution state
9069// args[1]: step action from the enumeration StepAction
9070// args[2]: number of times to perform the step, for step out it is the number
9071//          of frames to step down.
9072static Object* Runtime_PrepareStep(Arguments args) {
9073  HandleScope scope;
9074  ASSERT(args.length() == 3);
9075  // Check arguments.
9076  Object* check = Runtime_CheckExecutionState(args);
9077  if (check->IsFailure()) return check;
9078  if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
9079    return Top::Throw(Heap::illegal_argument_symbol());
9080  }
9081
9082  // Get the step action and check validity.
9083  StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
9084  if (step_action != StepIn &&
9085      step_action != StepNext &&
9086      step_action != StepOut &&
9087      step_action != StepInMin &&
9088      step_action != StepMin) {
9089    return Top::Throw(Heap::illegal_argument_symbol());
9090  }
9091
9092  // Get the number of steps.
9093  int step_count = NumberToInt32(args[2]);
9094  if (step_count < 1) {
9095    return Top::Throw(Heap::illegal_argument_symbol());
9096  }
9097
9098  // Clear all current stepping setup.
9099  Debug::ClearStepping();
9100
9101  // Prepare step.
9102  Debug::PrepareStep(static_cast<StepAction>(step_action), step_count);
9103  return Heap::undefined_value();
9104}
9105
9106
9107// Clear all stepping set by PrepareStep.
9108static Object* Runtime_ClearStepping(Arguments args) {
9109  HandleScope scope;
9110  ASSERT(args.length() == 0);
9111  Debug::ClearStepping();
9112  return Heap::undefined_value();
9113}
9114
9115
9116// Creates a copy of the with context chain. The copy of the context chain is
9117// is linked to the function context supplied.
9118static Handle<Context> CopyWithContextChain(Handle<Context> context_chain,
9119                                            Handle<Context> function_context) {
9120  // At the bottom of the chain. Return the function context to link to.
9121  if (context_chain->is_function_context()) {
9122    return function_context;
9123  }
9124
9125  // Recursively copy the with contexts.
9126  Handle<Context> previous(context_chain->previous());
9127  Handle<JSObject> extension(JSObject::cast(context_chain->extension()));
9128  return Factory::NewWithContext(
9129      CopyWithContextChain(function_context, previous),
9130      extension,
9131      context_chain->IsCatchContext());
9132}
9133
9134
9135// Helper function to find or create the arguments object for
9136// Runtime_DebugEvaluate.
9137static Handle<Object> GetArgumentsObject(JavaScriptFrame* frame,
9138                                         Handle<JSFunction> function,
9139                                         Handle<Code> code,
9140                                         const ScopeInfo<>* sinfo,
9141                                         Handle<Context> function_context) {
9142  // Try to find the value of 'arguments' to pass as parameter. If it is not
9143  // found (that is the debugged function does not reference 'arguments' and
9144  // does not support eval) then create an 'arguments' object.
9145  int index;
9146  if (sinfo->number_of_stack_slots() > 0) {
9147    index = ScopeInfo<>::StackSlotIndex(*code, Heap::arguments_symbol());
9148    if (index != -1) {
9149      return Handle<Object>(frame->GetExpression(index));
9150    }
9151  }
9152
9153  if (sinfo->number_of_context_slots() > Context::MIN_CONTEXT_SLOTS) {
9154    index = ScopeInfo<>::ContextSlotIndex(*code, Heap::arguments_symbol(),
9155                                          NULL);
9156    if (index != -1) {
9157      return Handle<Object>(function_context->get(index));
9158    }
9159  }
9160
9161  const int length = frame->GetProvidedParametersCount();
9162  Handle<JSObject> arguments = Factory::NewArgumentsObject(function, length);
9163  Handle<FixedArray> array = Factory::NewFixedArray(length);
9164
9165  AssertNoAllocation no_gc;
9166  WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
9167  for (int i = 0; i < length; i++) {
9168    array->set(i, frame->GetParameter(i), mode);
9169  }
9170  arguments->set_elements(*array);
9171  return arguments;
9172}
9173
9174
9175// Evaluate a piece of JavaScript in the context of a stack frame for
9176// debugging. This is accomplished by creating a new context which in its
9177// extension part has all the parameters and locals of the function on the
9178// stack frame. A function which calls eval with the code to evaluate is then
9179// compiled in this context and called in this context. As this context
9180// replaces the context of the function on the stack frame a new (empty)
9181// function is created as well to be used as the closure for the context.
9182// This function and the context acts as replacements for the function on the
9183// stack frame presenting the same view of the values of parameters and
9184// local variables as if the piece of JavaScript was evaluated at the point
9185// where the function on the stack frame is currently stopped.
9186static Object* Runtime_DebugEvaluate(Arguments args) {
9187  HandleScope scope;
9188
9189  // Check the execution state and decode arguments frame and source to be
9190  // evaluated.
9191  ASSERT(args.length() == 4);
9192  Object* check_result = Runtime_CheckExecutionState(args);
9193  if (check_result->IsFailure()) return check_result;
9194  CONVERT_CHECKED(Smi, wrapped_id, args[1]);
9195  CONVERT_ARG_CHECKED(String, source, 2);
9196  CONVERT_BOOLEAN_CHECKED(disable_break, args[3]);
9197
9198  // Handle the processing of break.
9199  DisableBreak disable_break_save(disable_break);
9200
9201  // Get the frame where the debugging is performed.
9202  StackFrame::Id id = UnwrapFrameId(wrapped_id);
9203  JavaScriptFrameIterator it(id);
9204  JavaScriptFrame* frame = it.frame();
9205  Handle<JSFunction> function(JSFunction::cast(frame->function()));
9206  Handle<Code> code(function->code());
9207  ScopeInfo<> sinfo(*code);
9208
9209  // Traverse the saved contexts chain to find the active context for the
9210  // selected frame.
9211  SaveContext* save = Top::save_context();
9212  while (save != NULL && !save->below(frame)) {
9213    save = save->prev();
9214  }
9215  ASSERT(save != NULL);
9216  SaveContext savex;
9217  Top::set_context(*(save->context()));
9218
9219  // Create the (empty) function replacing the function on the stack frame for
9220  // the purpose of evaluating in the context created below. It is important
9221  // that this function does not describe any parameters and local variables
9222  // in the context. If it does then this will cause problems with the lookup
9223  // in Context::Lookup, where context slots for parameters and local variables
9224  // are looked at before the extension object.
9225  Handle<JSFunction> go_between =
9226      Factory::NewFunction(Factory::empty_string(), Factory::undefined_value());
9227  go_between->set_context(function->context());
9228#ifdef DEBUG
9229  ScopeInfo<> go_between_sinfo(go_between->shared()->code());
9230  ASSERT(go_between_sinfo.number_of_parameters() == 0);
9231  ASSERT(go_between_sinfo.number_of_context_slots() == 0);
9232#endif
9233
9234  // Materialize the content of the local scope into a JSObject.
9235  Handle<JSObject> local_scope = MaterializeLocalScope(frame);
9236
9237  // Allocate a new context for the debug evaluation and set the extension
9238  // object build.
9239  Handle<Context> context =
9240      Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, go_between);
9241  context->set_extension(*local_scope);
9242  // Copy any with contexts present and chain them in front of this context.
9243  Handle<Context> frame_context(Context::cast(frame->context()));
9244  Handle<Context> function_context(frame_context->fcontext());
9245  context = CopyWithContextChain(frame_context, context);
9246
9247  // Wrap the evaluation statement in a new function compiled in the newly
9248  // created context. The function has one parameter which has to be called
9249  // 'arguments'. This it to have access to what would have been 'arguments' in
9250  // the function being debugged.
9251  // function(arguments,__source__) {return eval(__source__);}
9252  static const char* source_str =
9253      "(function(arguments,__source__){return eval(__source__);})";
9254  static const int source_str_length = StrLength(source_str);
9255  Handle<String> function_source =
9256      Factory::NewStringFromAscii(Vector<const char>(source_str,
9257                                                     source_str_length));
9258  Handle<SharedFunctionInfo> shared =
9259      Compiler::CompileEval(function_source,
9260                            context,
9261                            context->IsGlobalContext(),
9262                            Compiler::DONT_VALIDATE_JSON);
9263  if (shared.is_null()) return Failure::Exception();
9264  Handle<JSFunction> compiled_function =
9265      Factory::NewFunctionFromSharedFunctionInfo(shared, context);
9266
9267  // Invoke the result of the compilation to get the evaluation function.
9268  bool has_pending_exception;
9269  Handle<Object> receiver(frame->receiver());
9270  Handle<Object> evaluation_function =
9271      Execution::Call(compiled_function, receiver, 0, NULL,
9272                      &has_pending_exception);
9273  if (has_pending_exception) return Failure::Exception();
9274
9275  Handle<Object> arguments = GetArgumentsObject(frame, function, code, &sinfo,
9276                                                function_context);
9277
9278  // Invoke the evaluation function and return the result.
9279  const int argc = 2;
9280  Object** argv[argc] = { arguments.location(),
9281                          Handle<Object>::cast(source).location() };
9282  Handle<Object> result =
9283      Execution::Call(Handle<JSFunction>::cast(evaluation_function), receiver,
9284                      argc, argv, &has_pending_exception);
9285  if (has_pending_exception) return Failure::Exception();
9286
9287  // Skip the global proxy as it has no properties and always delegates to the
9288  // real global object.
9289  if (result->IsJSGlobalProxy()) {
9290    result = Handle<JSObject>(JSObject::cast(result->GetPrototype()));
9291  }
9292
9293  return *result;
9294}
9295
9296
9297static Object* Runtime_DebugEvaluateGlobal(Arguments args) {
9298  HandleScope scope;
9299
9300  // Check the execution state and decode arguments frame and source to be
9301  // evaluated.
9302  ASSERT(args.length() == 3);
9303  Object* check_result = Runtime_CheckExecutionState(args);
9304  if (check_result->IsFailure()) return check_result;
9305  CONVERT_ARG_CHECKED(String, source, 1);
9306  CONVERT_BOOLEAN_CHECKED(disable_break, args[2]);
9307
9308  // Handle the processing of break.
9309  DisableBreak disable_break_save(disable_break);
9310
9311  // Enter the top context from before the debugger was invoked.
9312  SaveContext save;
9313  SaveContext* top = &save;
9314  while (top != NULL && *top->context() == *Debug::debug_context()) {
9315    top = top->prev();
9316  }
9317  if (top != NULL) {
9318    Top::set_context(*top->context());
9319  }
9320
9321  // Get the global context now set to the top context from before the
9322  // debugger was invoked.
9323  Handle<Context> context = Top::global_context();
9324
9325  // Compile the source to be evaluated.
9326  Handle<SharedFunctionInfo> shared =
9327      Compiler::CompileEval(source,
9328                            context,
9329                            true,
9330                            Compiler::DONT_VALIDATE_JSON);
9331  if (shared.is_null()) return Failure::Exception();
9332  Handle<JSFunction> compiled_function =
9333      Handle<JSFunction>(Factory::NewFunctionFromSharedFunctionInfo(shared,
9334                                                                    context));
9335
9336  // Invoke the result of the compilation to get the evaluation function.
9337  bool has_pending_exception;
9338  Handle<Object> receiver = Top::global();
9339  Handle<Object> result =
9340    Execution::Call(compiled_function, receiver, 0, NULL,
9341                    &has_pending_exception);
9342  if (has_pending_exception) return Failure::Exception();
9343  return *result;
9344}
9345
9346
9347static Object* Runtime_DebugGetLoadedScripts(Arguments args) {
9348  HandleScope scope;
9349  ASSERT(args.length() == 0);
9350
9351  // Fill the script objects.
9352  Handle<FixedArray> instances = Debug::GetLoadedScripts();
9353
9354  // Convert the script objects to proper JS objects.
9355  for (int i = 0; i < instances->length(); i++) {
9356    Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
9357    // Get the script wrapper in a local handle before calling GetScriptWrapper,
9358    // because using
9359    //   instances->set(i, *GetScriptWrapper(script))
9360    // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
9361    // already have deferenced the instances handle.
9362    Handle<JSValue> wrapper = GetScriptWrapper(script);
9363    instances->set(i, *wrapper);
9364  }
9365
9366  // Return result as a JS array.
9367  Handle<JSObject> result = Factory::NewJSObject(Top::array_function());
9368  Handle<JSArray>::cast(result)->SetContent(*instances);
9369  return *result;
9370}
9371
9372
9373// Helper function used by Runtime_DebugReferencedBy below.
9374static int DebugReferencedBy(JSObject* target,
9375                             Object* instance_filter, int max_references,
9376                             FixedArray* instances, int instances_size,
9377                             JSFunction* arguments_function) {
9378  NoHandleAllocation ha;
9379  AssertNoAllocation no_alloc;
9380
9381  // Iterate the heap.
9382  int count = 0;
9383  JSObject* last = NULL;
9384  HeapIterator iterator;
9385  HeapObject* heap_obj = NULL;
9386  while (((heap_obj = iterator.next()) != NULL) &&
9387         (max_references == 0 || count < max_references)) {
9388    // Only look at all JSObjects.
9389    if (heap_obj->IsJSObject()) {
9390      // Skip context extension objects and argument arrays as these are
9391      // checked in the context of functions using them.
9392      JSObject* obj = JSObject::cast(heap_obj);
9393      if (obj->IsJSContextExtensionObject() ||
9394          obj->map()->constructor() == arguments_function) {
9395        continue;
9396      }
9397
9398      // Check if the JS object has a reference to the object looked for.
9399      if (obj->ReferencesObject(target)) {
9400        // Check instance filter if supplied. This is normally used to avoid
9401        // references from mirror objects (see Runtime_IsInPrototypeChain).
9402        if (!instance_filter->IsUndefined()) {
9403          Object* V = obj;
9404          while (true) {
9405            Object* prototype = V->GetPrototype();
9406            if (prototype->IsNull()) {
9407              break;
9408            }
9409            if (instance_filter == prototype) {
9410              obj = NULL;  // Don't add this object.
9411              break;
9412            }
9413            V = prototype;
9414          }
9415        }
9416
9417        if (obj != NULL) {
9418          // Valid reference found add to instance array if supplied an update
9419          // count.
9420          if (instances != NULL && count < instances_size) {
9421            instances->set(count, obj);
9422          }
9423          last = obj;
9424          count++;
9425        }
9426      }
9427    }
9428  }
9429
9430  // Check for circular reference only. This can happen when the object is only
9431  // referenced from mirrors and has a circular reference in which case the
9432  // object is not really alive and would have been garbage collected if not
9433  // referenced from the mirror.
9434  if (count == 1 && last == target) {
9435    count = 0;
9436  }
9437
9438  // Return the number of referencing objects found.
9439  return count;
9440}
9441
9442
9443// Scan the heap for objects with direct references to an object
9444// args[0]: the object to find references to
9445// args[1]: constructor function for instances to exclude (Mirror)
9446// args[2]: the the maximum number of objects to return
9447static Object* Runtime_DebugReferencedBy(Arguments args) {
9448  ASSERT(args.length() == 3);
9449
9450  // First perform a full GC in order to avoid references from dead objects.
9451  Heap::CollectAllGarbage(false);
9452
9453  // Check parameters.
9454  CONVERT_CHECKED(JSObject, target, args[0]);
9455  Object* instance_filter = args[1];
9456  RUNTIME_ASSERT(instance_filter->IsUndefined() ||
9457                 instance_filter->IsJSObject());
9458  CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
9459  RUNTIME_ASSERT(max_references >= 0);
9460
9461  // Get the constructor function for context extension and arguments array.
9462  JSObject* arguments_boilerplate =
9463      Top::context()->global_context()->arguments_boilerplate();
9464  JSFunction* arguments_function =
9465      JSFunction::cast(arguments_boilerplate->map()->constructor());
9466
9467  // Get the number of referencing objects.
9468  int count;
9469  count = DebugReferencedBy(target, instance_filter, max_references,
9470                            NULL, 0, arguments_function);
9471
9472  // Allocate an array to hold the result.
9473  Object* object = Heap::AllocateFixedArray(count);
9474  if (object->IsFailure()) return object;
9475  FixedArray* instances = FixedArray::cast(object);
9476
9477  // Fill the referencing objects.
9478  count = DebugReferencedBy(target, instance_filter, max_references,
9479                            instances, count, arguments_function);
9480
9481  // Return result as JS array.
9482  Object* result =
9483      Heap::AllocateJSObject(
9484          Top::context()->global_context()->array_function());
9485  if (!result->IsFailure()) JSArray::cast(result)->SetContent(instances);
9486  return result;
9487}
9488
9489
9490// Helper function used by Runtime_DebugConstructedBy below.
9491static int DebugConstructedBy(JSFunction* constructor, int max_references,
9492                              FixedArray* instances, int instances_size) {
9493  AssertNoAllocation no_alloc;
9494
9495  // Iterate the heap.
9496  int count = 0;
9497  HeapIterator iterator;
9498  HeapObject* heap_obj = NULL;
9499  while (((heap_obj = iterator.next()) != NULL) &&
9500         (max_references == 0 || count < max_references)) {
9501    // Only look at all JSObjects.
9502    if (heap_obj->IsJSObject()) {
9503      JSObject* obj = JSObject::cast(heap_obj);
9504      if (obj->map()->constructor() == constructor) {
9505        // Valid reference found add to instance array if supplied an update
9506        // count.
9507        if (instances != NULL && count < instances_size) {
9508          instances->set(count, obj);
9509        }
9510        count++;
9511      }
9512    }
9513  }
9514
9515  // Return the number of referencing objects found.
9516  return count;
9517}
9518
9519
9520// Scan the heap for objects constructed by a specific function.
9521// args[0]: the constructor to find instances of
9522// args[1]: the the maximum number of objects to return
9523static Object* Runtime_DebugConstructedBy(Arguments args) {
9524  ASSERT(args.length() == 2);
9525
9526  // First perform a full GC in order to avoid dead objects.
9527  Heap::CollectAllGarbage(false);
9528
9529  // Check parameters.
9530  CONVERT_CHECKED(JSFunction, constructor, args[0]);
9531  CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
9532  RUNTIME_ASSERT(max_references >= 0);
9533
9534  // Get the number of referencing objects.
9535  int count;
9536  count = DebugConstructedBy(constructor, max_references, NULL, 0);
9537
9538  // Allocate an array to hold the result.
9539  Object* object = Heap::AllocateFixedArray(count);
9540  if (object->IsFailure()) return object;
9541  FixedArray* instances = FixedArray::cast(object);
9542
9543  // Fill the referencing objects.
9544  count = DebugConstructedBy(constructor, max_references, instances, count);
9545
9546  // Return result as JS array.
9547  Object* result =
9548      Heap::AllocateJSObject(
9549          Top::context()->global_context()->array_function());
9550  if (!result->IsFailure()) JSArray::cast(result)->SetContent(instances);
9551  return result;
9552}
9553
9554
9555// Find the effective prototype object as returned by __proto__.
9556// args[0]: the object to find the prototype for.
9557static Object* Runtime_DebugGetPrototype(Arguments args) {
9558  ASSERT(args.length() == 1);
9559
9560  CONVERT_CHECKED(JSObject, obj, args[0]);
9561
9562  // Use the __proto__ accessor.
9563  return Accessors::ObjectPrototype.getter(obj, NULL);
9564}
9565
9566
9567static Object* Runtime_SystemBreak(Arguments args) {
9568  ASSERT(args.length() == 0);
9569  CPU::DebugBreak();
9570  return Heap::undefined_value();
9571}
9572
9573
9574static Object* Runtime_DebugDisassembleFunction(Arguments args) {
9575#ifdef DEBUG
9576  HandleScope scope;
9577  ASSERT(args.length() == 1);
9578  // Get the function and make sure it is compiled.
9579  CONVERT_ARG_CHECKED(JSFunction, func, 0);
9580  Handle<SharedFunctionInfo> shared(func->shared());
9581  if (!EnsureCompiled(shared, KEEP_EXCEPTION)) {
9582    return Failure::Exception();
9583  }
9584  func->code()->PrintLn();
9585#endif  // DEBUG
9586  return Heap::undefined_value();
9587}
9588
9589
9590static Object* Runtime_DebugDisassembleConstructor(Arguments args) {
9591#ifdef DEBUG
9592  HandleScope scope;
9593  ASSERT(args.length() == 1);
9594  // Get the function and make sure it is compiled.
9595  CONVERT_ARG_CHECKED(JSFunction, func, 0);
9596  Handle<SharedFunctionInfo> shared(func->shared());
9597  if (!EnsureCompiled(shared, KEEP_EXCEPTION)) {
9598    return Failure::Exception();
9599  }
9600  shared->construct_stub()->PrintLn();
9601#endif  // DEBUG
9602  return Heap::undefined_value();
9603}
9604
9605
9606static Object* Runtime_FunctionGetInferredName(Arguments args) {
9607  NoHandleAllocation ha;
9608  ASSERT(args.length() == 1);
9609
9610  CONVERT_CHECKED(JSFunction, f, args[0]);
9611  return f->shared()->inferred_name();
9612}
9613
9614
9615static int FindSharedFunctionInfosForScript(Script* script,
9616                                     FixedArray* buffer) {
9617  AssertNoAllocation no_allocations;
9618
9619  int counter = 0;
9620  int buffer_size = buffer->length();
9621  HeapIterator iterator;
9622  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
9623    ASSERT(obj != NULL);
9624    if (!obj->IsSharedFunctionInfo()) {
9625      continue;
9626    }
9627    SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
9628    if (shared->script() != script) {
9629      continue;
9630    }
9631    if (counter < buffer_size) {
9632      buffer->set(counter, shared);
9633    }
9634    counter++;
9635  }
9636  return counter;
9637}
9638
9639// For a script finds all SharedFunctionInfo's in the heap that points
9640// to this script. Returns JSArray of SharedFunctionInfo wrapped
9641// in OpaqueReferences.
9642static Object* Runtime_LiveEditFindSharedFunctionInfosForScript(
9643    Arguments args) {
9644  ASSERT(args.length() == 1);
9645  HandleScope scope;
9646  CONVERT_CHECKED(JSValue, script_value, args[0]);
9647
9648  Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
9649
9650  const int kBufferSize = 32;
9651
9652  Handle<FixedArray> array;
9653  array = Factory::NewFixedArray(kBufferSize);
9654  int number = FindSharedFunctionInfosForScript(*script, *array);
9655  if (number > kBufferSize) {
9656    array = Factory::NewFixedArray(number);
9657    FindSharedFunctionInfosForScript(*script, *array);
9658  }
9659
9660  Handle<JSArray> result = Factory::NewJSArrayWithElements(array);
9661  result->set_length(Smi::FromInt(number));
9662
9663  LiveEdit::WrapSharedFunctionInfos(result);
9664
9665  return *result;
9666}
9667
9668// For a script calculates compilation information about all its functions.
9669// The script source is explicitly specified by the second argument.
9670// The source of the actual script is not used, however it is important that
9671// all generated code keeps references to this particular instance of script.
9672// Returns a JSArray of compilation infos. The array is ordered so that
9673// each function with all its descendant is always stored in a continues range
9674// with the function itself going first. The root function is a script function.
9675static Object* Runtime_LiveEditGatherCompileInfo(Arguments args) {
9676  ASSERT(args.length() == 2);
9677  HandleScope scope;
9678  CONVERT_CHECKED(JSValue, script, args[0]);
9679  CONVERT_ARG_CHECKED(String, source, 1);
9680  Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
9681
9682  JSArray* result =  LiveEdit::GatherCompileInfo(script_handle, source);
9683
9684  if (Top::has_pending_exception()) {
9685    return Failure::Exception();
9686  }
9687
9688  return result;
9689}
9690
9691// Changes the source of the script to a new_source.
9692// If old_script_name is provided (i.e. is a String), also creates a copy of
9693// the script with its original source and sends notification to debugger.
9694static Object* Runtime_LiveEditReplaceScript(Arguments args) {
9695  ASSERT(args.length() == 3);
9696  HandleScope scope;
9697  CONVERT_CHECKED(JSValue, original_script_value, args[0]);
9698  CONVERT_ARG_CHECKED(String, new_source, 1);
9699  Handle<Object> old_script_name(args[2]);
9700
9701  CONVERT_CHECKED(Script, original_script_pointer,
9702                  original_script_value->value());
9703  Handle<Script> original_script(original_script_pointer);
9704
9705  Object* old_script = LiveEdit::ChangeScriptSource(original_script,
9706                                                    new_source,
9707                                                    old_script_name);
9708
9709  if (old_script->IsScript()) {
9710    Handle<Script> script_handle(Script::cast(old_script));
9711    return *(GetScriptWrapper(script_handle));
9712  } else {
9713    return Heap::null_value();
9714  }
9715}
9716
9717// Replaces code of SharedFunctionInfo with a new one.
9718static Object* Runtime_LiveEditReplaceFunctionCode(Arguments args) {
9719  ASSERT(args.length() == 2);
9720  HandleScope scope;
9721  CONVERT_ARG_CHECKED(JSArray, new_compile_info, 0);
9722  CONVERT_ARG_CHECKED(JSArray, shared_info, 1);
9723
9724  return LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
9725}
9726
9727// Connects SharedFunctionInfo to another script.
9728static Object* Runtime_LiveEditFunctionSetScript(Arguments args) {
9729  ASSERT(args.length() == 2);
9730  HandleScope scope;
9731  Handle<Object> function_object(args[0]);
9732  Handle<Object> script_object(args[1]);
9733
9734  if (function_object->IsJSValue()) {
9735    Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
9736    if (script_object->IsJSValue()) {
9737      CONVERT_CHECKED(Script, script, JSValue::cast(*script_object)->value());
9738      script_object = Handle<Object>(script);
9739    }
9740
9741    LiveEdit::SetFunctionScript(function_wrapper, script_object);
9742  } else {
9743    // Just ignore this. We may not have a SharedFunctionInfo for some functions
9744    // and we check it in this function.
9745  }
9746
9747  return Heap::undefined_value();
9748}
9749
9750
9751// In a code of a parent function replaces original function as embedded object
9752// with a substitution one.
9753static Object* Runtime_LiveEditReplaceRefToNestedFunction(Arguments args) {
9754  ASSERT(args.length() == 3);
9755  HandleScope scope;
9756
9757  CONVERT_ARG_CHECKED(JSValue, parent_wrapper, 0);
9758  CONVERT_ARG_CHECKED(JSValue, orig_wrapper, 1);
9759  CONVERT_ARG_CHECKED(JSValue, subst_wrapper, 2);
9760
9761  LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper,
9762                                       subst_wrapper);
9763
9764  return Heap::undefined_value();
9765}
9766
9767
9768// Updates positions of a shared function info (first parameter) according
9769// to script source change. Text change is described in second parameter as
9770// array of groups of 3 numbers:
9771// (change_begin, change_end, change_end_new_position).
9772// Each group describes a change in text; groups are sorted by change_begin.
9773static Object* Runtime_LiveEditPatchFunctionPositions(Arguments args) {
9774  ASSERT(args.length() == 2);
9775  HandleScope scope;
9776  CONVERT_ARG_CHECKED(JSArray, shared_array, 0);
9777  CONVERT_ARG_CHECKED(JSArray, position_change_array, 1);
9778
9779  return LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
9780}
9781
9782
9783// For array of SharedFunctionInfo's (each wrapped in JSValue)
9784// checks that none of them have activations on stacks (of any thread).
9785// Returns array of the same length with corresponding results of
9786// LiveEdit::FunctionPatchabilityStatus type.
9787static Object* Runtime_LiveEditCheckAndDropActivations(Arguments args) {
9788  ASSERT(args.length() == 2);
9789  HandleScope scope;
9790  CONVERT_ARG_CHECKED(JSArray, shared_array, 0);
9791  CONVERT_BOOLEAN_CHECKED(do_drop, args[1]);
9792
9793  return *LiveEdit::CheckAndDropActivations(shared_array, do_drop);
9794}
9795
9796// Compares 2 strings line-by-line and returns diff in form of JSArray of
9797// triplets (pos1, pos1_end, pos2_end) describing list of diff chunks.
9798static Object* Runtime_LiveEditCompareStringsLinewise(Arguments args) {
9799  ASSERT(args.length() == 2);
9800  HandleScope scope;
9801  CONVERT_ARG_CHECKED(String, s1, 0);
9802  CONVERT_ARG_CHECKED(String, s2, 1);
9803
9804  return *LiveEdit::CompareStringsLinewise(s1, s2);
9805}
9806
9807
9808
9809// A testing entry. Returns statement position which is the closest to
9810// source_position.
9811static Object* Runtime_GetFunctionCodePositionFromSource(Arguments args) {
9812  ASSERT(args.length() == 2);
9813  HandleScope scope;
9814  CONVERT_ARG_CHECKED(JSFunction, function, 0);
9815  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
9816
9817  Handle<Code> code(function->code());
9818
9819  RelocIterator it(*code, 1 << RelocInfo::STATEMENT_POSITION);
9820  int closest_pc = 0;
9821  int distance = kMaxInt;
9822  while (!it.done()) {
9823    int statement_position = static_cast<int>(it.rinfo()->data());
9824    // Check if this break point is closer that what was previously found.
9825    if (source_position <= statement_position &&
9826        statement_position - source_position < distance) {
9827      closest_pc =
9828          static_cast<int>(it.rinfo()->pc() - code->instruction_start());
9829      distance = statement_position - source_position;
9830      // Check whether we can't get any closer.
9831      if (distance == 0) break;
9832    }
9833    it.next();
9834  }
9835
9836  return Smi::FromInt(closest_pc);
9837}
9838
9839
9840// Calls specified function with or without entering the debugger.
9841// This is used in unit tests to run code as if debugger is entered or simply
9842// to have a stack with C++ frame in the middle.
9843static Object* Runtime_ExecuteInDebugContext(Arguments args) {
9844  ASSERT(args.length() == 2);
9845  HandleScope scope;
9846  CONVERT_ARG_CHECKED(JSFunction, function, 0);
9847  CONVERT_BOOLEAN_CHECKED(without_debugger, args[1]);
9848
9849  Handle<Object> result;
9850  bool pending_exception;
9851  {
9852    if (without_debugger) {
9853      result = Execution::Call(function, Top::global(), 0, NULL,
9854                               &pending_exception);
9855    } else {
9856      EnterDebugger enter_debugger;
9857      result = Execution::Call(function, Top::global(), 0, NULL,
9858                               &pending_exception);
9859    }
9860  }
9861  if (!pending_exception) {
9862    return *result;
9863  } else {
9864    return Failure::Exception();
9865  }
9866}
9867
9868
9869#endif  // ENABLE_DEBUGGER_SUPPORT
9870
9871#ifdef ENABLE_LOGGING_AND_PROFILING
9872
9873static Object* Runtime_ProfilerResume(Arguments args) {
9874  NoHandleAllocation ha;
9875  ASSERT(args.length() == 2);
9876
9877  CONVERT_CHECKED(Smi, smi_modules, args[0]);
9878  CONVERT_CHECKED(Smi, smi_tag, args[1]);
9879  v8::V8::ResumeProfilerEx(smi_modules->value(), smi_tag->value());
9880  return Heap::undefined_value();
9881}
9882
9883
9884static Object* Runtime_ProfilerPause(Arguments args) {
9885  NoHandleAllocation ha;
9886  ASSERT(args.length() == 2);
9887
9888  CONVERT_CHECKED(Smi, smi_modules, args[0]);
9889  CONVERT_CHECKED(Smi, smi_tag, args[1]);
9890  v8::V8::PauseProfilerEx(smi_modules->value(), smi_tag->value());
9891  return Heap::undefined_value();
9892}
9893
9894#endif  // ENABLE_LOGGING_AND_PROFILING
9895
9896// Finds the script object from the script data. NOTE: This operation uses
9897// heap traversal to find the function generated for the source position
9898// for the requested break point. For lazily compiled functions several heap
9899// traversals might be required rendering this operation as a rather slow
9900// operation. However for setting break points which is normally done through
9901// some kind of user interaction the performance is not crucial.
9902static Handle<Object> Runtime_GetScriptFromScriptName(
9903    Handle<String> script_name) {
9904  // Scan the heap for Script objects to find the script with the requested
9905  // script data.
9906  Handle<Script> script;
9907  HeapIterator iterator;
9908  HeapObject* obj = NULL;
9909  while (script.is_null() && ((obj = iterator.next()) != NULL)) {
9910    // If a script is found check if it has the script data requested.
9911    if (obj->IsScript()) {
9912      if (Script::cast(obj)->name()->IsString()) {
9913        if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) {
9914          script = Handle<Script>(Script::cast(obj));
9915        }
9916      }
9917    }
9918  }
9919
9920  // If no script with the requested script data is found return undefined.
9921  if (script.is_null()) return Factory::undefined_value();
9922
9923  // Return the script found.
9924  return GetScriptWrapper(script);
9925}
9926
9927
9928// Get the script object from script data. NOTE: Regarding performance
9929// see the NOTE for GetScriptFromScriptData.
9930// args[0]: script data for the script to find the source for
9931static Object* Runtime_GetScript(Arguments args) {
9932  HandleScope scope;
9933
9934  ASSERT(args.length() == 1);
9935
9936  CONVERT_CHECKED(String, script_name, args[0]);
9937
9938  // Find the requested script.
9939  Handle<Object> result =
9940      Runtime_GetScriptFromScriptName(Handle<String>(script_name));
9941  return *result;
9942}
9943
9944
9945// Determines whether the given stack frame should be displayed in
9946// a stack trace.  The caller is the error constructor that asked
9947// for the stack trace to be collected.  The first time a construct
9948// call to this function is encountered it is skipped.  The seen_caller
9949// in/out parameter is used to remember if the caller has been seen
9950// yet.
9951static bool ShowFrameInStackTrace(StackFrame* raw_frame, Object* caller,
9952    bool* seen_caller) {
9953  // Only display JS frames.
9954  if (!raw_frame->is_java_script())
9955    return false;
9956  JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
9957  Object* raw_fun = frame->function();
9958  // Not sure when this can happen but skip it just in case.
9959  if (!raw_fun->IsJSFunction())
9960    return false;
9961  if ((raw_fun == caller) && !(*seen_caller)) {
9962    *seen_caller = true;
9963    return false;
9964  }
9965  // Skip all frames until we've seen the caller.  Also, skip the most
9966  // obvious builtin calls.  Some builtin calls (such as Number.ADD
9967  // which is invoked using 'call') are very difficult to recognize
9968  // so we're leaving them in for now.
9969  return *seen_caller && !frame->receiver()->IsJSBuiltinsObject();
9970}
9971
9972
9973// Collect the raw data for a stack trace.  Returns an array of three
9974// element segments each containing a receiver, function and native
9975// code offset.
9976static Object* Runtime_CollectStackTrace(Arguments args) {
9977  ASSERT_EQ(args.length(), 2);
9978  Handle<Object> caller = args.at<Object>(0);
9979  CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[1]);
9980
9981  HandleScope scope;
9982
9983  limit = Max(limit, 0);  // Ensure that limit is not negative.
9984  int initial_size = Min(limit, 10);
9985  Handle<JSArray> result = Factory::NewJSArray(initial_size * 3);
9986
9987  StackFrameIterator iter;
9988  // If the caller parameter is a function we skip frames until we're
9989  // under it before starting to collect.
9990  bool seen_caller = !caller->IsJSFunction();
9991  int cursor = 0;
9992  int frames_seen = 0;
9993  while (!iter.done() && frames_seen < limit) {
9994    StackFrame* raw_frame = iter.frame();
9995    if (ShowFrameInStackTrace(raw_frame, *caller, &seen_caller)) {
9996      frames_seen++;
9997      JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
9998      Object* recv = frame->receiver();
9999      Object* fun = frame->function();
10000      Address pc = frame->pc();
10001      Address start = frame->code()->address();
10002      Smi* offset = Smi::FromInt(static_cast<int>(pc - start));
10003      FixedArray* elements = FixedArray::cast(result->elements());
10004      if (cursor + 2 < elements->length()) {
10005        elements->set(cursor++, recv);
10006        elements->set(cursor++, fun);
10007        elements->set(cursor++, offset);
10008      } else {
10009        HandleScope scope;
10010        Handle<Object> recv_handle(recv);
10011        Handle<Object> fun_handle(fun);
10012        SetElement(result, cursor++, recv_handle);
10013        SetElement(result, cursor++, fun_handle);
10014        SetElement(result, cursor++, Handle<Smi>(offset));
10015      }
10016    }
10017    iter.Advance();
10018  }
10019
10020  result->set_length(Smi::FromInt(cursor));
10021  return *result;
10022}
10023
10024
10025// Returns V8 version as a string.
10026static Object* Runtime_GetV8Version(Arguments args) {
10027  ASSERT_EQ(args.length(), 0);
10028
10029  NoHandleAllocation ha;
10030
10031  const char* version_string = v8::V8::GetVersion();
10032
10033  return Heap::AllocateStringFromAscii(CStrVector(version_string), NOT_TENURED);
10034}
10035
10036
10037static Object* Runtime_Abort(Arguments args) {
10038  ASSERT(args.length() == 2);
10039  OS::PrintError("abort: %s\n", reinterpret_cast<char*>(args[0]) +
10040                                    Smi::cast(args[1])->value());
10041  Top::PrintStack();
10042  OS::Abort();
10043  UNREACHABLE();
10044  return NULL;
10045}
10046
10047
10048static Object* Runtime_DeleteHandleScopeExtensions(Arguments args) {
10049  ASSERT(args.length() == 0);
10050  HandleScope::DeleteExtensions();
10051  return Heap::undefined_value();
10052}
10053
10054
10055static Object* CacheMiss(FixedArray* cache_obj, int index, Object* key_obj) {
10056  ASSERT(index % 2 == 0);  // index of the key
10057  ASSERT(index >= JSFunctionResultCache::kEntriesIndex);
10058  ASSERT(index < cache_obj->length());
10059
10060  HandleScope scope;
10061
10062  Handle<FixedArray> cache(cache_obj);
10063  Handle<Object> key(key_obj);
10064  Handle<JSFunction> factory(JSFunction::cast(
10065        cache->get(JSFunctionResultCache::kFactoryIndex)));
10066  // TODO(antonm): consider passing a receiver when constructing a cache.
10067  Handle<Object> receiver(Top::global_context()->global());
10068
10069  Handle<Object> value;
10070  {
10071    // This handle is nor shared, nor used later, so it's safe.
10072    Object** argv[] = { key.location() };
10073    bool pending_exception = false;
10074    value = Execution::Call(factory,
10075                            receiver,
10076                            1,
10077                            argv,
10078                            &pending_exception);
10079    if (pending_exception) return Failure::Exception();
10080  }
10081
10082  cache->set(index, *key);
10083  cache->set(index + 1, *value);
10084  cache->set(JSFunctionResultCache::kFingerIndex, Smi::FromInt(index));
10085
10086  return *value;
10087}
10088
10089
10090static Object* Runtime_GetFromCache(Arguments args) {
10091  // This is only called from codegen, so checks might be more lax.
10092  CONVERT_CHECKED(FixedArray, cache, args[0]);
10093  Object* key = args[1];
10094
10095  const int finger_index =
10096      Smi::cast(cache->get(JSFunctionResultCache::kFingerIndex))->value();
10097
10098  Object* o = cache->get(finger_index);
10099  if (o == key) {
10100    // The fastest case: hit the same place again.
10101    return cache->get(finger_index + 1);
10102  }
10103
10104  for (int i = finger_index - 2;
10105       i >= JSFunctionResultCache::kEntriesIndex;
10106       i -= 2) {
10107    o = cache->get(i);
10108    if (o == key) {
10109      cache->set(JSFunctionResultCache::kFingerIndex, Smi::FromInt(i));
10110      return cache->get(i + 1);
10111    }
10112  }
10113
10114  const int size =
10115      Smi::cast(cache->get(JSFunctionResultCache::kCacheSizeIndex))->value();
10116  ASSERT(size <= cache->length());
10117
10118  for (int i = size - 2; i > finger_index; i -= 2) {
10119    o = cache->get(i);
10120    if (o == key) {
10121      cache->set(JSFunctionResultCache::kFingerIndex, Smi::FromInt(i));
10122      return cache->get(i + 1);
10123    }
10124  }
10125
10126  // Cache miss.  If we have spare room, put new data into it, otherwise
10127  // evict post finger entry which must be least recently used.
10128  if (size < cache->length()) {
10129    cache->set(JSFunctionResultCache::kCacheSizeIndex, Smi::FromInt(size + 2));
10130    return CacheMiss(cache, size, key);
10131  } else {
10132    int target_index = finger_index + JSFunctionResultCache::kEntrySize;
10133    if (target_index == cache->length()) {
10134      target_index = JSFunctionResultCache::kEntriesIndex;
10135    }
10136    return CacheMiss(cache, target_index, key);
10137  }
10138}
10139
10140#ifdef DEBUG
10141// ListNatives is ONLY used by the fuzz-natives.js in debug mode
10142// Exclude the code in release mode.
10143static Object* Runtime_ListNatives(Arguments args) {
10144  ASSERT(args.length() == 0);
10145  HandleScope scope;
10146  Handle<JSArray> result = Factory::NewJSArray(0);
10147  int index = 0;
10148  bool inline_runtime_functions = false;
10149#define ADD_ENTRY(Name, argc, ressize)                                       \
10150  {                                                                          \
10151    HandleScope inner;                                                       \
10152    Handle<String> name;                                                     \
10153    /* Inline runtime functions have an underscore in front of the name. */  \
10154    if (inline_runtime_functions) {                                          \
10155      name = Factory::NewStringFromAscii(                                    \
10156          Vector<const char>("_" #Name, StrLength("_" #Name)));              \
10157    } else {                                                                 \
10158      name = Factory::NewStringFromAscii(                                    \
10159          Vector<const char>(#Name, StrLength(#Name)));                      \
10160    }                                                                        \
10161    Handle<JSArray> pair = Factory::NewJSArray(0);                           \
10162    SetElement(pair, 0, name);                                               \
10163    SetElement(pair, 1, Handle<Smi>(Smi::FromInt(argc)));                    \
10164    SetElement(result, index++, pair);                                       \
10165  }
10166  inline_runtime_functions = false;
10167  RUNTIME_FUNCTION_LIST(ADD_ENTRY)
10168  inline_runtime_functions = true;
10169  INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY)
10170#undef ADD_ENTRY
10171  return *result;
10172}
10173#endif
10174
10175
10176static Object* Runtime_Log(Arguments args) {
10177  ASSERT(args.length() == 2);
10178  CONVERT_CHECKED(String, format, args[0]);
10179  CONVERT_CHECKED(JSArray, elms, args[1]);
10180  Vector<const char> chars = format->ToAsciiVector();
10181  Logger::LogRuntime(chars, elms);
10182  return Heap::undefined_value();
10183}
10184
10185
10186static Object* Runtime_IS_VAR(Arguments args) {
10187  UNREACHABLE();  // implemented as macro in the parser
10188  return NULL;
10189}
10190
10191
10192// ----------------------------------------------------------------------------
10193// Implementation of Runtime
10194
10195#define F(name, nargs, ressize)                                           \
10196  { #name, FUNCTION_ADDR(Runtime_##name), nargs, \
10197    static_cast<int>(Runtime::k##name), ressize },
10198
10199static Runtime::Function Runtime_functions[] = {
10200  RUNTIME_FUNCTION_LIST(F)
10201  { NULL, NULL, 0, -1, 0 }
10202};
10203
10204#undef F
10205
10206
10207Runtime::Function* Runtime::FunctionForId(FunctionId fid) {
10208  ASSERT(0 <= fid && fid < kNofFunctions);
10209  return &Runtime_functions[fid];
10210}
10211
10212
10213Runtime::Function* Runtime::FunctionForName(const char* name) {
10214  for (Function* f = Runtime_functions; f->name != NULL; f++) {
10215    if (strcmp(f->name, name) == 0) {
10216      return f;
10217    }
10218  }
10219  return NULL;
10220}
10221
10222
10223void Runtime::PerformGC(Object* result) {
10224  Failure* failure = Failure::cast(result);
10225  if (failure->IsRetryAfterGC()) {
10226    // Try to do a garbage collection; ignore it if it fails. The C
10227    // entry stub will throw an out-of-memory exception in that case.
10228    Heap::CollectGarbage(failure->requested(), failure->allocation_space());
10229  } else {
10230    // Handle last resort GC and make sure to allow future allocations
10231    // to grow the heap without causing GCs (if possible).
10232    Counters::gc_last_resort_from_js.Increment();
10233    Heap::CollectAllGarbage(false);
10234  }
10235}
10236
10237
10238} }  // namespace v8::internal
10239