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