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