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