• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include <stdlib.h>
29 
30 #include "v8.h"
31 
32 #include "accessors.h"
33 #include "api.h"
34 #include "arguments.h"
35 #include "codegen.h"
36 #include "compilation-cache.h"
37 #include "compiler.h"
38 #include "cpu.h"
39 #include "dateparser-inl.h"
40 #include "debug.h"
41 #include "deoptimizer.h"
42 #include "execution.h"
43 #include "global-handles.h"
44 #include "jsregexp.h"
45 #include "liveedit.h"
46 #include "liveobjectlist-inl.h"
47 #include "parser.h"
48 #include "platform.h"
49 #include "runtime.h"
50 #include "runtime-profiler.h"
51 #include "scopeinfo.h"
52 #include "smart-pointer.h"
53 #include "stub-cache.h"
54 #include "v8threads.h"
55 #include "string-search.h"
56 
57 namespace v8 {
58 namespace internal {
59 
60 
61 #define RUNTIME_ASSERT(value) \
62   if (!(value)) return isolate->ThrowIllegalOperation();
63 
64 // Cast the given object to a value of the specified type and store
65 // it in a variable with the given name.  If the object is not of the
66 // expected type call IllegalOperation and return.
67 #define CONVERT_CHECKED(Type, name, obj)                             \
68   RUNTIME_ASSERT(obj->Is##Type());                                   \
69   Type* name = Type::cast(obj);
70 
71 #define CONVERT_ARG_CHECKED(Type, name, index)                       \
72   RUNTIME_ASSERT(args[index]->Is##Type());                           \
73   Handle<Type> name = args.at<Type>(index);
74 
75 // Cast the given object to a boolean and store it in a variable with
76 // the given name.  If the object is not a boolean call IllegalOperation
77 // and return.
78 #define CONVERT_BOOLEAN_CHECKED(name, obj)                            \
79   RUNTIME_ASSERT(obj->IsBoolean());                                   \
80   bool name = (obj)->IsTrue();
81 
82 // Cast the given object to a Smi and store its value in an int variable
83 // with the given name.  If the object is not a Smi call IllegalOperation
84 // and return.
85 #define CONVERT_SMI_CHECKED(name, obj)                            \
86   RUNTIME_ASSERT(obj->IsSmi());                                   \
87   int name = Smi::cast(obj)->value();
88 
89 // Cast the given object to a double and store it in a variable with
90 // the given name.  If the object is not a number (as opposed to
91 // the number not-a-number) call IllegalOperation and return.
92 #define CONVERT_DOUBLE_CHECKED(name, obj)                            \
93   RUNTIME_ASSERT(obj->IsNumber());                                   \
94   double name = (obj)->Number();
95 
96 // Call the specified converter on the object *comand store the result in
97 // a variable of the specified type with the given name.  If the
98 // object is not a Number call IllegalOperation and return.
99 #define CONVERT_NUMBER_CHECKED(type, name, Type, obj)                \
100   RUNTIME_ASSERT(obj->IsNumber());                                   \
101   type name = NumberTo##Type(obj);
102 
103 
DeepCopyBoilerplate(Isolate * isolate,JSObject * boilerplate)104 MUST_USE_RESULT static MaybeObject* DeepCopyBoilerplate(Isolate* isolate,
105                                                    JSObject* boilerplate) {
106   StackLimitCheck check(isolate);
107   if (check.HasOverflowed()) return isolate->StackOverflow();
108 
109   Heap* heap = isolate->heap();
110   Object* result;
111   { MaybeObject* maybe_result = heap->CopyJSObject(boilerplate);
112     if (!maybe_result->ToObject(&result)) return maybe_result;
113   }
114   JSObject* copy = JSObject::cast(result);
115 
116   // Deep copy local properties.
117   if (copy->HasFastProperties()) {
118     FixedArray* properties = copy->properties();
119     for (int i = 0; i < properties->length(); i++) {
120       Object* value = properties->get(i);
121       if (value->IsJSObject()) {
122         JSObject* js_object = JSObject::cast(value);
123         { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
124           if (!maybe_result->ToObject(&result)) return maybe_result;
125         }
126         properties->set(i, result);
127       }
128     }
129     int nof = copy->map()->inobject_properties();
130     for (int i = 0; i < nof; i++) {
131       Object* value = copy->InObjectPropertyAt(i);
132       if (value->IsJSObject()) {
133         JSObject* js_object = JSObject::cast(value);
134         { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
135           if (!maybe_result->ToObject(&result)) return maybe_result;
136         }
137         copy->InObjectPropertyAtPut(i, result);
138       }
139     }
140   } else {
141     { MaybeObject* maybe_result =
142           heap->AllocateFixedArray(copy->NumberOfLocalProperties(NONE));
143       if (!maybe_result->ToObject(&result)) return maybe_result;
144     }
145     FixedArray* names = FixedArray::cast(result);
146     copy->GetLocalPropertyNames(names, 0);
147     for (int i = 0; i < names->length(); i++) {
148       ASSERT(names->get(i)->IsString());
149       String* key_string = String::cast(names->get(i));
150       PropertyAttributes attributes =
151           copy->GetLocalPropertyAttribute(key_string);
152       // Only deep copy fields from the object literal expression.
153       // In particular, don't try to copy the length attribute of
154       // an array.
155       if (attributes != NONE) continue;
156       Object* value =
157           copy->GetProperty(key_string, &attributes)->ToObjectUnchecked();
158       if (value->IsJSObject()) {
159         JSObject* js_object = JSObject::cast(value);
160         { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
161           if (!maybe_result->ToObject(&result)) return maybe_result;
162         }
163         { MaybeObject* maybe_result =
164               // Creating object copy for literals. No strict mode needed.
165               copy->SetProperty(key_string, result, NONE, kNonStrictMode);
166           if (!maybe_result->ToObject(&result)) return maybe_result;
167         }
168       }
169     }
170   }
171 
172   // Deep copy local elements.
173   // Pixel elements cannot be created using an object literal.
174   ASSERT(!copy->HasExternalArrayElements());
175   switch (copy->GetElementsKind()) {
176     case JSObject::FAST_ELEMENTS: {
177       FixedArray* elements = FixedArray::cast(copy->elements());
178       if (elements->map() == heap->fixed_cow_array_map()) {
179         isolate->counters()->cow_arrays_created_runtime()->Increment();
180 #ifdef DEBUG
181         for (int i = 0; i < elements->length(); i++) {
182           ASSERT(!elements->get(i)->IsJSObject());
183         }
184 #endif
185       } else {
186         for (int i = 0; i < elements->length(); i++) {
187           Object* value = elements->get(i);
188           if (value->IsJSObject()) {
189             JSObject* js_object = JSObject::cast(value);
190             { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate,
191                                                               js_object);
192               if (!maybe_result->ToObject(&result)) return maybe_result;
193             }
194             elements->set(i, result);
195           }
196         }
197       }
198       break;
199     }
200     case JSObject::DICTIONARY_ELEMENTS: {
201       NumberDictionary* element_dictionary = copy->element_dictionary();
202       int capacity = element_dictionary->Capacity();
203       for (int i = 0; i < capacity; i++) {
204         Object* k = element_dictionary->KeyAt(i);
205         if (element_dictionary->IsKey(k)) {
206           Object* value = element_dictionary->ValueAt(i);
207           if (value->IsJSObject()) {
208             JSObject* js_object = JSObject::cast(value);
209             { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate,
210                                                               js_object);
211               if (!maybe_result->ToObject(&result)) return maybe_result;
212             }
213             element_dictionary->ValueAtPut(i, result);
214           }
215         }
216       }
217       break;
218     }
219     default:
220       UNREACHABLE();
221       break;
222   }
223   return copy;
224 }
225 
226 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CloneLiteralBoilerplate)227 RUNTIME_FUNCTION(MaybeObject*, Runtime_CloneLiteralBoilerplate) {
228   CONVERT_CHECKED(JSObject, boilerplate, args[0]);
229   return DeepCopyBoilerplate(isolate, boilerplate);
230 }
231 
232 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CloneShallowLiteralBoilerplate)233 RUNTIME_FUNCTION(MaybeObject*, Runtime_CloneShallowLiteralBoilerplate) {
234   CONVERT_CHECKED(JSObject, boilerplate, args[0]);
235   return isolate->heap()->CopyJSObject(boilerplate);
236 }
237 
238 
ComputeObjectLiteralMap(Handle<Context> context,Handle<FixedArray> constant_properties,bool * is_result_from_cache)239 static Handle<Map> ComputeObjectLiteralMap(
240     Handle<Context> context,
241     Handle<FixedArray> constant_properties,
242     bool* is_result_from_cache) {
243   Isolate* isolate = context->GetIsolate();
244   int properties_length = constant_properties->length();
245   int number_of_properties = properties_length / 2;
246   if (FLAG_canonicalize_object_literal_maps) {
247     // Check that there are only symbols and array indices among keys.
248     int number_of_symbol_keys = 0;
249     for (int p = 0; p != properties_length; p += 2) {
250       Object* key = constant_properties->get(p);
251       uint32_t element_index = 0;
252       if (key->IsSymbol()) {
253         number_of_symbol_keys++;
254       } else if (key->ToArrayIndex(&element_index)) {
255         // An index key does not require space in the property backing store.
256         number_of_properties--;
257       } else {
258         // Bail out as a non-symbol non-index key makes caching impossible.
259         // ASSERT to make sure that the if condition after the loop is false.
260         ASSERT(number_of_symbol_keys != number_of_properties);
261         break;
262       }
263     }
264     // If we only have symbols and array indices among keys then we can
265     // use the map cache in the global context.
266     const int kMaxKeys = 10;
267     if ((number_of_symbol_keys == number_of_properties) &&
268         (number_of_symbol_keys < kMaxKeys)) {
269       // Create the fixed array with the key.
270       Handle<FixedArray> keys =
271           isolate->factory()->NewFixedArray(number_of_symbol_keys);
272       if (number_of_symbol_keys > 0) {
273         int index = 0;
274         for (int p = 0; p < properties_length; p += 2) {
275           Object* key = constant_properties->get(p);
276           if (key->IsSymbol()) {
277             keys->set(index++, key);
278           }
279         }
280         ASSERT(index == number_of_symbol_keys);
281       }
282       *is_result_from_cache = true;
283       return isolate->factory()->ObjectLiteralMapFromCache(context, keys);
284     }
285   }
286   *is_result_from_cache = false;
287   return isolate->factory()->CopyMap(
288       Handle<Map>(context->object_function()->initial_map()),
289       number_of_properties);
290 }
291 
292 
293 static Handle<Object> CreateLiteralBoilerplate(
294     Isolate* isolate,
295     Handle<FixedArray> literals,
296     Handle<FixedArray> constant_properties);
297 
298 
CreateObjectLiteralBoilerplate(Isolate * isolate,Handle<FixedArray> literals,Handle<FixedArray> constant_properties,bool should_have_fast_elements,bool has_function_literal)299 static Handle<Object> CreateObjectLiteralBoilerplate(
300     Isolate* isolate,
301     Handle<FixedArray> literals,
302     Handle<FixedArray> constant_properties,
303     bool should_have_fast_elements,
304     bool has_function_literal) {
305   // Get the global context from the literals array.  This is the
306   // context in which the function was created and we use the object
307   // function from this context to create the object literal.  We do
308   // not use the object function from the current global context
309   // because this might be the object function from another context
310   // which we should not have access to.
311   Handle<Context> context =
312       Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals));
313 
314   // In case we have function literals, we want the object to be in
315   // slow properties mode for now. We don't go in the map cache because
316   // maps with constant functions can't be shared if the functions are
317   // not the same (which is the common case).
318   bool is_result_from_cache = false;
319   Handle<Map> map = has_function_literal
320       ? Handle<Map>(context->object_function()->initial_map())
321       : ComputeObjectLiteralMap(context,
322                                 constant_properties,
323                                 &is_result_from_cache);
324 
325   Handle<JSObject> boilerplate = isolate->factory()->NewJSObjectFromMap(map);
326 
327   // Normalize the elements of the boilerplate to save space if needed.
328   if (!should_have_fast_elements) NormalizeElements(boilerplate);
329 
330   // Add the constant properties to the boilerplate.
331   int length = constant_properties->length();
332   bool should_transform =
333       !is_result_from_cache && boilerplate->HasFastProperties();
334   if (should_transform || has_function_literal) {
335     // Normalize the properties of object to avoid n^2 behavior
336     // when extending the object multiple properties. Indicate the number of
337     // properties to be added.
338     NormalizeProperties(boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2);
339   }
340 
341   for (int index = 0; index < length; index +=2) {
342     Handle<Object> key(constant_properties->get(index+0), isolate);
343     Handle<Object> value(constant_properties->get(index+1), isolate);
344     if (value->IsFixedArray()) {
345       // The value contains the constant_properties of a
346       // simple object or array literal.
347       Handle<FixedArray> array = Handle<FixedArray>::cast(value);
348       value = CreateLiteralBoilerplate(isolate, literals, array);
349       if (value.is_null()) return value;
350     }
351     Handle<Object> result;
352     uint32_t element_index = 0;
353     if (key->IsSymbol()) {
354       if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
355         // Array index as string (uint32).
356         result = SetOwnElement(boilerplate,
357                                element_index,
358                                value,
359                                kNonStrictMode);
360       } else {
361         Handle<String> name(String::cast(*key));
362         ASSERT(!name->AsArrayIndex(&element_index));
363         result = SetLocalPropertyIgnoreAttributes(boilerplate, name,
364                                                   value, NONE);
365       }
366     } else if (key->ToArrayIndex(&element_index)) {
367       // Array index (uint32).
368       result = SetOwnElement(boilerplate,
369                              element_index,
370                              value,
371                              kNonStrictMode);
372     } else {
373       // Non-uint32 number.
374       ASSERT(key->IsNumber());
375       double num = key->Number();
376       char arr[100];
377       Vector<char> buffer(arr, ARRAY_SIZE(arr));
378       const char* str = DoubleToCString(num, buffer);
379       Handle<String> name =
380           isolate->factory()->NewStringFromAscii(CStrVector(str));
381       result = SetLocalPropertyIgnoreAttributes(boilerplate, name,
382                                                 value, NONE);
383     }
384     // If setting the property on the boilerplate throws an
385     // exception, the exception is converted to an empty handle in
386     // the handle based operations.  In that case, we need to
387     // convert back to an exception.
388     if (result.is_null()) return result;
389   }
390 
391   // Transform to fast properties if necessary. For object literals with
392   // containing function literals we defer this operation until after all
393   // computed properties have been assigned so that we can generate
394   // constant function properties.
395   if (should_transform && !has_function_literal) {
396     TransformToFastProperties(boilerplate,
397                               boilerplate->map()->unused_property_fields());
398   }
399 
400   return boilerplate;
401 }
402 
403 
CreateArrayLiteralBoilerplate(Isolate * isolate,Handle<FixedArray> literals,Handle<FixedArray> elements)404 static Handle<Object> CreateArrayLiteralBoilerplate(
405     Isolate* isolate,
406     Handle<FixedArray> literals,
407     Handle<FixedArray> elements) {
408   // Create the JSArray.
409   Handle<JSFunction> constructor(
410       JSFunction::GlobalContextFromLiterals(*literals)->array_function());
411   Handle<Object> object = isolate->factory()->NewJSObject(constructor);
412 
413   const bool is_cow =
414       (elements->map() == isolate->heap()->fixed_cow_array_map());
415   Handle<FixedArray> copied_elements =
416       is_cow ? elements : isolate->factory()->CopyFixedArray(elements);
417 
418   Handle<FixedArray> content = Handle<FixedArray>::cast(copied_elements);
419   if (is_cow) {
420 #ifdef DEBUG
421     // Copy-on-write arrays must be shallow (and simple).
422     for (int i = 0; i < content->length(); i++) {
423       ASSERT(!content->get(i)->IsFixedArray());
424     }
425 #endif
426   } else {
427     for (int i = 0; i < content->length(); i++) {
428       if (content->get(i)->IsFixedArray()) {
429         // The value contains the constant_properties of a
430         // simple object or array literal.
431         Handle<FixedArray> fa(FixedArray::cast(content->get(i)));
432         Handle<Object> result =
433             CreateLiteralBoilerplate(isolate, literals, fa);
434         if (result.is_null()) return result;
435         content->set(i, *result);
436       }
437     }
438   }
439 
440   // Set the elements.
441   Handle<JSArray>::cast(object)->SetContent(*content);
442   return object;
443 }
444 
445 
CreateLiteralBoilerplate(Isolate * isolate,Handle<FixedArray> literals,Handle<FixedArray> array)446 static Handle<Object> CreateLiteralBoilerplate(
447     Isolate* isolate,
448     Handle<FixedArray> literals,
449     Handle<FixedArray> array) {
450   Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
451   const bool kHasNoFunctionLiteral = false;
452   switch (CompileTimeValue::GetType(array)) {
453     case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS:
454       return CreateObjectLiteralBoilerplate(isolate,
455                                             literals,
456                                             elements,
457                                             true,
458                                             kHasNoFunctionLiteral);
459     case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS:
460       return CreateObjectLiteralBoilerplate(isolate,
461                                             literals,
462                                             elements,
463                                             false,
464                                             kHasNoFunctionLiteral);
465     case CompileTimeValue::ARRAY_LITERAL:
466       return CreateArrayLiteralBoilerplate(isolate, literals, elements);
467     default:
468       UNREACHABLE();
469       return Handle<Object>::null();
470   }
471 }
472 
473 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateArrayLiteralBoilerplate)474 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralBoilerplate) {
475   // Takes a FixedArray of elements containing the literal elements of
476   // the array literal and produces JSArray with those elements.
477   // Additionally takes the literals array of the surrounding function
478   // which contains the context from which to get the Array function
479   // to use for creating the array literal.
480   HandleScope scope(isolate);
481   ASSERT(args.length() == 3);
482   CONVERT_ARG_CHECKED(FixedArray, literals, 0);
483   CONVERT_SMI_CHECKED(literals_index, args[1]);
484   CONVERT_ARG_CHECKED(FixedArray, elements, 2);
485 
486   Handle<Object> object =
487       CreateArrayLiteralBoilerplate(isolate, literals, elements);
488   if (object.is_null()) return Failure::Exception();
489 
490   // Update the functions literal and return the boilerplate.
491   literals->set(literals_index, *object);
492   return *object;
493 }
494 
495 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateObjectLiteral)496 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteral) {
497   HandleScope scope(isolate);
498   ASSERT(args.length() == 4);
499   CONVERT_ARG_CHECKED(FixedArray, literals, 0);
500   CONVERT_SMI_CHECKED(literals_index, args[1]);
501   CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2);
502   CONVERT_SMI_CHECKED(flags, args[3]);
503   bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
504   bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
505 
506   // Check if boilerplate exists. If not, create it first.
507   Handle<Object> boilerplate(literals->get(literals_index), isolate);
508   if (*boilerplate == isolate->heap()->undefined_value()) {
509     boilerplate = CreateObjectLiteralBoilerplate(isolate,
510                                                  literals,
511                                                  constant_properties,
512                                                  should_have_fast_elements,
513                                                  has_function_literal);
514     if (boilerplate.is_null()) return Failure::Exception();
515     // Update the functions literal and return the boilerplate.
516     literals->set(literals_index, *boilerplate);
517   }
518   return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate));
519 }
520 
521 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateObjectLiteralShallow)522 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteralShallow) {
523   HandleScope scope(isolate);
524   ASSERT(args.length() == 4);
525   CONVERT_ARG_CHECKED(FixedArray, literals, 0);
526   CONVERT_SMI_CHECKED(literals_index, args[1]);
527   CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2);
528   CONVERT_SMI_CHECKED(flags, args[3]);
529   bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
530   bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
531 
532   // Check if boilerplate exists. If not, create it first.
533   Handle<Object> boilerplate(literals->get(literals_index), isolate);
534   if (*boilerplate == isolate->heap()->undefined_value()) {
535     boilerplate = CreateObjectLiteralBoilerplate(isolate,
536                                                  literals,
537                                                  constant_properties,
538                                                  should_have_fast_elements,
539                                                  has_function_literal);
540     if (boilerplate.is_null()) return Failure::Exception();
541     // Update the functions literal and return the boilerplate.
542     literals->set(literals_index, *boilerplate);
543   }
544   return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate));
545 }
546 
547 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateArrayLiteral)548 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteral) {
549   HandleScope scope(isolate);
550   ASSERT(args.length() == 3);
551   CONVERT_ARG_CHECKED(FixedArray, literals, 0);
552   CONVERT_SMI_CHECKED(literals_index, args[1]);
553   CONVERT_ARG_CHECKED(FixedArray, elements, 2);
554 
555   // Check if boilerplate exists. If not, create it first.
556   Handle<Object> boilerplate(literals->get(literals_index), isolate);
557   if (*boilerplate == isolate->heap()->undefined_value()) {
558     boilerplate = CreateArrayLiteralBoilerplate(isolate, literals, elements);
559     if (boilerplate.is_null()) return Failure::Exception();
560     // Update the functions literal and return the boilerplate.
561     literals->set(literals_index, *boilerplate);
562   }
563   return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate));
564 }
565 
566 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateArrayLiteralShallow)567 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralShallow) {
568   HandleScope scope(isolate);
569   ASSERT(args.length() == 3);
570   CONVERT_ARG_CHECKED(FixedArray, literals, 0);
571   CONVERT_SMI_CHECKED(literals_index, args[1]);
572   CONVERT_ARG_CHECKED(FixedArray, elements, 2);
573 
574   // Check if boilerplate exists. If not, create it first.
575   Handle<Object> boilerplate(literals->get(literals_index), isolate);
576   if (*boilerplate == isolate->heap()->undefined_value()) {
577     boilerplate = CreateArrayLiteralBoilerplate(isolate, literals, elements);
578     if (boilerplate.is_null()) return Failure::Exception();
579     // Update the functions literal and return the boilerplate.
580     literals->set(literals_index, *boilerplate);
581   }
582   if (JSObject::cast(*boilerplate)->elements()->map() ==
583       isolate->heap()->fixed_cow_array_map()) {
584     isolate->counters()->cow_arrays_created_runtime()->Increment();
585   }
586   return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate));
587 }
588 
589 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateCatchExtensionObject)590 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateCatchExtensionObject) {
591   ASSERT(args.length() == 2);
592   CONVERT_CHECKED(String, key, args[0]);
593   Object* value = args[1];
594   // Create a catch context extension object.
595   JSFunction* constructor =
596       isolate->context()->global_context()->
597           context_extension_function();
598   Object* object;
599   { MaybeObject* maybe_object = isolate->heap()->AllocateJSObject(constructor);
600     if (!maybe_object->ToObject(&object)) return maybe_object;
601   }
602   // Assign the exception value to the catch variable and make sure
603   // that the catch variable is DontDelete.
604   { MaybeObject* maybe_value =
605         // Passing non-strict per ECMA-262 5th Ed. 12.14. Catch, bullet #4.
606         JSObject::cast(object)->SetProperty(
607             key, value, DONT_DELETE, kNonStrictMode);
608     if (!maybe_value->ToObject(&value)) return maybe_value;
609   }
610   return object;
611 }
612 
613 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ClassOf)614 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) {
615   NoHandleAllocation ha;
616   ASSERT(args.length() == 1);
617   Object* obj = args[0];
618   if (!obj->IsJSObject()) return isolate->heap()->null_value();
619   return JSObject::cast(obj)->class_name();
620 }
621 
622 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsInPrototypeChain)623 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) {
624   NoHandleAllocation ha;
625   ASSERT(args.length() == 2);
626   // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
627   Object* O = args[0];
628   Object* V = args[1];
629   while (true) {
630     Object* prototype = V->GetPrototype();
631     if (prototype->IsNull()) return isolate->heap()->false_value();
632     if (O == prototype) return isolate->heap()->true_value();
633     V = prototype;
634   }
635 }
636 
637 
638 // Inserts an object as the hidden prototype of another object.
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetHiddenPrototype)639 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetHiddenPrototype) {
640   NoHandleAllocation ha;
641   ASSERT(args.length() == 2);
642   CONVERT_CHECKED(JSObject, jsobject, args[0]);
643   CONVERT_CHECKED(JSObject, proto, args[1]);
644 
645   // Sanity checks.  The old prototype (that we are replacing) could
646   // theoretically be null, but if it is not null then check that we
647   // didn't already install a hidden prototype here.
648   RUNTIME_ASSERT(!jsobject->GetPrototype()->IsHeapObject() ||
649     !HeapObject::cast(jsobject->GetPrototype())->map()->is_hidden_prototype());
650   RUNTIME_ASSERT(!proto->map()->is_hidden_prototype());
651 
652   // Allocate up front before we start altering state in case we get a GC.
653   Object* map_or_failure;
654   { MaybeObject* maybe_map_or_failure = proto->map()->CopyDropTransitions();
655     if (!maybe_map_or_failure->ToObject(&map_or_failure)) {
656       return maybe_map_or_failure;
657     }
658   }
659   Map* new_proto_map = Map::cast(map_or_failure);
660 
661   { MaybeObject* maybe_map_or_failure = jsobject->map()->CopyDropTransitions();
662     if (!maybe_map_or_failure->ToObject(&map_or_failure)) {
663       return maybe_map_or_failure;
664     }
665   }
666   Map* new_map = Map::cast(map_or_failure);
667 
668   // Set proto's prototype to be the old prototype of the object.
669   new_proto_map->set_prototype(jsobject->GetPrototype());
670   proto->set_map(new_proto_map);
671   new_proto_map->set_is_hidden_prototype();
672 
673   // Set the object's prototype to proto.
674   new_map->set_prototype(proto);
675   jsobject->set_map(new_map);
676 
677   return isolate->heap()->undefined_value();
678 }
679 
680 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsConstructCall)681 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsConstructCall) {
682   NoHandleAllocation ha;
683   ASSERT(args.length() == 0);
684   JavaScriptFrameIterator it(isolate);
685   return isolate->heap()->ToBoolean(it.frame()->IsConstructor());
686 }
687 
688 
689 // Recursively traverses hidden prototypes if property is not found
GetOwnPropertyImplementation(JSObject * obj,String * name,LookupResult * result)690 static void GetOwnPropertyImplementation(JSObject* obj,
691                                          String* name,
692                                          LookupResult* result) {
693   obj->LocalLookupRealNamedProperty(name, result);
694 
695   if (!result->IsProperty()) {
696     Object* proto = obj->GetPrototype();
697     if (proto->IsJSObject() &&
698       JSObject::cast(proto)->map()->is_hidden_prototype())
699       GetOwnPropertyImplementation(JSObject::cast(proto),
700                                    name, result);
701   }
702 }
703 
704 
CheckAccessException(LookupResult * result,v8::AccessType access_type)705 static bool CheckAccessException(LookupResult* result,
706                                  v8::AccessType access_type) {
707   if (result->type() == CALLBACKS) {
708     Object* callback = result->GetCallbackObject();
709     if (callback->IsAccessorInfo()) {
710       AccessorInfo* info = AccessorInfo::cast(callback);
711       bool can_access =
712           (access_type == v8::ACCESS_HAS &&
713               (info->all_can_read() || info->all_can_write())) ||
714           (access_type == v8::ACCESS_GET && info->all_can_read()) ||
715           (access_type == v8::ACCESS_SET && info->all_can_write());
716       return can_access;
717     }
718   }
719 
720   return false;
721 }
722 
723 
CheckAccess(JSObject * obj,String * name,LookupResult * result,v8::AccessType access_type)724 static bool CheckAccess(JSObject* obj,
725                         String* name,
726                         LookupResult* result,
727                         v8::AccessType access_type) {
728   ASSERT(result->IsProperty());
729 
730   JSObject* holder = result->holder();
731   JSObject* current = obj;
732   Isolate* isolate = obj->GetIsolate();
733   while (true) {
734     if (current->IsAccessCheckNeeded() &&
735         !isolate->MayNamedAccess(current, name, access_type)) {
736       // Access check callback denied the access, but some properties
737       // can have a special permissions which override callbacks descision
738       // (currently see v8::AccessControl).
739       break;
740     }
741 
742     if (current == holder) {
743       return true;
744     }
745 
746     current = JSObject::cast(current->GetPrototype());
747   }
748 
749   // API callbacks can have per callback access exceptions.
750   switch (result->type()) {
751     case CALLBACKS: {
752       if (CheckAccessException(result, access_type)) {
753         return true;
754       }
755       break;
756     }
757     case INTERCEPTOR: {
758       // If the object has an interceptor, try real named properties.
759       // Overwrite the result to fetch the correct property later.
760       holder->LookupRealNamedProperty(name, result);
761       if (result->IsProperty()) {
762         if (CheckAccessException(result, access_type)) {
763           return true;
764         }
765       }
766       break;
767     }
768     default:
769       break;
770   }
771 
772   isolate->ReportFailedAccessCheck(current, access_type);
773   return false;
774 }
775 
776 
777 // TODO(1095): we should traverse hidden prototype hierachy as well.
CheckElementAccess(JSObject * obj,uint32_t index,v8::AccessType access_type)778 static bool CheckElementAccess(JSObject* obj,
779                                uint32_t index,
780                                v8::AccessType access_type) {
781   if (obj->IsAccessCheckNeeded() &&
782       !obj->GetIsolate()->MayIndexedAccess(obj, index, access_type)) {
783     return false;
784   }
785 
786   return true;
787 }
788 
789 
790 // Enumerator used as indices into the array returned from GetOwnProperty
791 enum PropertyDescriptorIndices {
792   IS_ACCESSOR_INDEX,
793   VALUE_INDEX,
794   GETTER_INDEX,
795   SETTER_INDEX,
796   WRITABLE_INDEX,
797   ENUMERABLE_INDEX,
798   CONFIGURABLE_INDEX,
799   DESCRIPTOR_SIZE
800 };
801 
802 // Returns an array with the property description:
803 //  if args[1] is not a property on args[0]
804 //          returns undefined
805 //  if args[1] is a data property on args[0]
806 //         [false, value, Writeable, Enumerable, Configurable]
807 //  if args[1] is an accessor on args[0]
808 //         [true, GetFunction, SetFunction, Enumerable, Configurable]
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetOwnProperty)809 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) {
810   ASSERT(args.length() == 2);
811   Heap* heap = isolate->heap();
812   HandleScope scope(isolate);
813   Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
814   Handle<JSArray> desc = isolate->factory()->NewJSArrayWithElements(elms);
815   LookupResult result;
816   CONVERT_ARG_CHECKED(JSObject, obj, 0);
817   CONVERT_ARG_CHECKED(String, name, 1);
818 
819   // This could be an element.
820   uint32_t index;
821   if (name->AsArrayIndex(&index)) {
822     switch (obj->HasLocalElement(index)) {
823       case JSObject::UNDEFINED_ELEMENT:
824         return heap->undefined_value();
825 
826       case JSObject::STRING_CHARACTER_ELEMENT: {
827         // Special handling of string objects according to ECMAScript 5
828         // 15.5.5.2. Note that this might be a string object with elements
829         // other than the actual string value. This is covered by the
830         // subsequent cases.
831         Handle<JSValue> js_value = Handle<JSValue>::cast(obj);
832         Handle<String> str(String::cast(js_value->value()));
833         Handle<String> substr = SubString(str, index, index + 1, NOT_TENURED);
834 
835         elms->set(IS_ACCESSOR_INDEX, heap->false_value());
836         elms->set(VALUE_INDEX, *substr);
837         elms->set(WRITABLE_INDEX, heap->false_value());
838         elms->set(ENUMERABLE_INDEX,  heap->false_value());
839         elms->set(CONFIGURABLE_INDEX, heap->false_value());
840         return *desc;
841       }
842 
843       case JSObject::INTERCEPTED_ELEMENT:
844       case JSObject::FAST_ELEMENT: {
845         elms->set(IS_ACCESSOR_INDEX, heap->false_value());
846         Handle<Object> value = GetElement(obj, index);
847         RETURN_IF_EMPTY_HANDLE(isolate, value);
848         elms->set(VALUE_INDEX, *value);
849         elms->set(WRITABLE_INDEX, heap->true_value());
850         elms->set(ENUMERABLE_INDEX,  heap->true_value());
851         elms->set(CONFIGURABLE_INDEX, heap->true_value());
852         return *desc;
853       }
854 
855       case JSObject::DICTIONARY_ELEMENT: {
856         Handle<JSObject> holder = obj;
857         if (obj->IsJSGlobalProxy()) {
858           Object* proto = obj->GetPrototype();
859           if (proto->IsNull()) return heap->undefined_value();
860           ASSERT(proto->IsJSGlobalObject());
861           holder = Handle<JSObject>(JSObject::cast(proto));
862         }
863         NumberDictionary* dictionary = holder->element_dictionary();
864         int entry = dictionary->FindEntry(index);
865         ASSERT(entry != NumberDictionary::kNotFound);
866         PropertyDetails details = dictionary->DetailsAt(entry);
867         switch (details.type()) {
868           case CALLBACKS: {
869             // This is an accessor property with getter and/or setter.
870             FixedArray* callbacks =
871                 FixedArray::cast(dictionary->ValueAt(entry));
872             elms->set(IS_ACCESSOR_INDEX, heap->true_value());
873             if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) {
874               elms->set(GETTER_INDEX, callbacks->get(0));
875             }
876             if (CheckElementAccess(*obj, index, v8::ACCESS_SET)) {
877               elms->set(SETTER_INDEX, callbacks->get(1));
878             }
879             break;
880           }
881           case NORMAL: {
882             // This is a data property.
883             elms->set(IS_ACCESSOR_INDEX, heap->false_value());
884             Handle<Object> value = GetElement(obj, index);
885             ASSERT(!value.is_null());
886             elms->set(VALUE_INDEX, *value);
887             elms->set(WRITABLE_INDEX, heap->ToBoolean(!details.IsReadOnly()));
888             break;
889           }
890           default:
891             UNREACHABLE();
892             break;
893         }
894         elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!details.IsDontEnum()));
895         elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!details.IsDontDelete()));
896         return *desc;
897       }
898     }
899   }
900 
901   // Use recursive implementation to also traverse hidden prototypes
902   GetOwnPropertyImplementation(*obj, *name, &result);
903 
904   if (!result.IsProperty()) {
905     return heap->undefined_value();
906   }
907 
908   if (!CheckAccess(*obj, *name, &result, v8::ACCESS_HAS)) {
909     return heap->false_value();
910   }
911 
912   elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!result.IsDontEnum()));
913   elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!result.IsDontDelete()));
914 
915   bool is_js_accessor = (result.type() == CALLBACKS) &&
916                         (result.GetCallbackObject()->IsFixedArray());
917 
918   if (is_js_accessor) {
919     // __defineGetter__/__defineSetter__ callback.
920     elms->set(IS_ACCESSOR_INDEX, heap->true_value());
921 
922     FixedArray* structure = FixedArray::cast(result.GetCallbackObject());
923     if (CheckAccess(*obj, *name, &result, v8::ACCESS_GET)) {
924       elms->set(GETTER_INDEX, structure->get(0));
925     }
926     if (CheckAccess(*obj, *name, &result, v8::ACCESS_SET)) {
927       elms->set(SETTER_INDEX, structure->get(1));
928     }
929   } else {
930     elms->set(IS_ACCESSOR_INDEX, heap->false_value());
931     elms->set(WRITABLE_INDEX, heap->ToBoolean(!result.IsReadOnly()));
932 
933     PropertyAttributes attrs;
934     Object* value;
935     // GetProperty will check access and report any violations.
936     { MaybeObject* maybe_value = obj->GetProperty(*obj, &result, *name, &attrs);
937       if (!maybe_value->ToObject(&value)) return maybe_value;
938     }
939     elms->set(VALUE_INDEX, value);
940   }
941 
942   return *desc;
943 }
944 
945 
RUNTIME_FUNCTION(MaybeObject *,Runtime_PreventExtensions)946 RUNTIME_FUNCTION(MaybeObject*, Runtime_PreventExtensions) {
947   ASSERT(args.length() == 1);
948   CONVERT_CHECKED(JSObject, obj, args[0]);
949   return obj->PreventExtensions();
950 }
951 
952 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsExtensible)953 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsExtensible) {
954   ASSERT(args.length() == 1);
955   CONVERT_CHECKED(JSObject, obj, args[0]);
956   if (obj->IsJSGlobalProxy()) {
957     Object* proto = obj->GetPrototype();
958     if (proto->IsNull()) return isolate->heap()->false_value();
959     ASSERT(proto->IsJSGlobalObject());
960     obj = JSObject::cast(proto);
961   }
962   return obj->map()->is_extensible() ? isolate->heap()->true_value()
963                                      : isolate->heap()->false_value();
964 }
965 
966 
RUNTIME_FUNCTION(MaybeObject *,Runtime_RegExpCompile)967 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpCompile) {
968   HandleScope scope(isolate);
969   ASSERT(args.length() == 3);
970   CONVERT_ARG_CHECKED(JSRegExp, re, 0);
971   CONVERT_ARG_CHECKED(String, pattern, 1);
972   CONVERT_ARG_CHECKED(String, flags, 2);
973   Handle<Object> result = RegExpImpl::Compile(re, pattern, flags);
974   if (result.is_null()) return Failure::Exception();
975   return *result;
976 }
977 
978 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CreateApiFunction)979 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateApiFunction) {
980   HandleScope scope(isolate);
981   ASSERT(args.length() == 1);
982   CONVERT_ARG_CHECKED(FunctionTemplateInfo, data, 0);
983   return *isolate->factory()->CreateApiFunction(data);
984 }
985 
986 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsTemplate)987 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsTemplate) {
988   ASSERT(args.length() == 1);
989   Object* arg = args[0];
990   bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
991   return isolate->heap()->ToBoolean(result);
992 }
993 
994 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetTemplateField)995 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetTemplateField) {
996   ASSERT(args.length() == 2);
997   CONVERT_CHECKED(HeapObject, templ, args[0]);
998   CONVERT_CHECKED(Smi, field, args[1]);
999   int index = field->value();
1000   int offset = index * kPointerSize + HeapObject::kHeaderSize;
1001   InstanceType type = templ->map()->instance_type();
1002   RUNTIME_ASSERT(type ==  FUNCTION_TEMPLATE_INFO_TYPE ||
1003                  type ==  OBJECT_TEMPLATE_INFO_TYPE);
1004   RUNTIME_ASSERT(offset > 0);
1005   if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
1006     RUNTIME_ASSERT(offset < FunctionTemplateInfo::kSize);
1007   } else {
1008     RUNTIME_ASSERT(offset < ObjectTemplateInfo::kSize);
1009   }
1010   return *HeapObject::RawField(templ, offset);
1011 }
1012 
1013 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DisableAccessChecks)1014 RUNTIME_FUNCTION(MaybeObject*, Runtime_DisableAccessChecks) {
1015   ASSERT(args.length() == 1);
1016   CONVERT_CHECKED(HeapObject, object, args[0]);
1017   Map* old_map = object->map();
1018   bool needs_access_checks = old_map->is_access_check_needed();
1019   if (needs_access_checks) {
1020     // Copy map so it won't interfere constructor's initial map.
1021     Object* new_map;
1022     { MaybeObject* maybe_new_map = old_map->CopyDropTransitions();
1023       if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
1024     }
1025 
1026     Map::cast(new_map)->set_is_access_check_needed(false);
1027     object->set_map(Map::cast(new_map));
1028   }
1029   return needs_access_checks ? isolate->heap()->true_value()
1030                              : isolate->heap()->false_value();
1031 }
1032 
1033 
RUNTIME_FUNCTION(MaybeObject *,Runtime_EnableAccessChecks)1034 RUNTIME_FUNCTION(MaybeObject*, Runtime_EnableAccessChecks) {
1035   ASSERT(args.length() == 1);
1036   CONVERT_CHECKED(HeapObject, object, args[0]);
1037   Map* old_map = object->map();
1038   if (!old_map->is_access_check_needed()) {
1039     // Copy map so it won't interfere constructor's initial map.
1040     Object* new_map;
1041     { MaybeObject* maybe_new_map = old_map->CopyDropTransitions();
1042       if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
1043     }
1044 
1045     Map::cast(new_map)->set_is_access_check_needed(true);
1046     object->set_map(Map::cast(new_map));
1047   }
1048   return isolate->heap()->undefined_value();
1049 }
1050 
1051 
ThrowRedeclarationError(Isolate * isolate,const char * type,Handle<String> name)1052 static Failure* ThrowRedeclarationError(Isolate* isolate,
1053                                         const char* type,
1054                                         Handle<String> name) {
1055   HandleScope scope(isolate);
1056   Handle<Object> type_handle =
1057       isolate->factory()->NewStringFromAscii(CStrVector(type));
1058   Handle<Object> args[2] = { type_handle, name };
1059   Handle<Object> error =
1060       isolate->factory()->NewTypeError("redeclaration", HandleVector(args, 2));
1061   return isolate->Throw(*error);
1062 }
1063 
1064 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DeclareGlobals)1065 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
1066   ASSERT(args.length() == 4);
1067   HandleScope scope(isolate);
1068   Handle<GlobalObject> global = Handle<GlobalObject>(
1069       isolate->context()->global());
1070 
1071   Handle<Context> context = args.at<Context>(0);
1072   CONVERT_ARG_CHECKED(FixedArray, pairs, 1);
1073   bool is_eval = Smi::cast(args[2])->value() == 1;
1074   StrictModeFlag strict_mode =
1075       static_cast<StrictModeFlag>(Smi::cast(args[3])->value());
1076   ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode);
1077 
1078   // Compute the property attributes. According to ECMA-262, section
1079   // 13, page 71, the property must be read-only and
1080   // non-deletable. However, neither SpiderMonkey nor KJS creates the
1081   // property as read-only, so we don't either.
1082   PropertyAttributes base = is_eval ? NONE : DONT_DELETE;
1083 
1084   // Traverse the name/value pairs and set the properties.
1085   int length = pairs->length();
1086   for (int i = 0; i < length; i += 2) {
1087     HandleScope scope(isolate);
1088     Handle<String> name(String::cast(pairs->get(i)));
1089     Handle<Object> value(pairs->get(i + 1), isolate);
1090 
1091     // We have to declare a global const property. To capture we only
1092     // assign to it when evaluating the assignment for "const x =
1093     // <expr>" the initial value is the hole.
1094     bool is_const_property = value->IsTheHole();
1095 
1096     if (value->IsUndefined() || is_const_property) {
1097       // Lookup the property in the global object, and don't set the
1098       // value of the variable if the property is already there.
1099       LookupResult lookup;
1100       global->Lookup(*name, &lookup);
1101       if (lookup.IsProperty()) {
1102         // Determine if the property is local by comparing the holder
1103         // against the global object. The information will be used to
1104         // avoid throwing re-declaration errors when declaring
1105         // variables or constants that exist in the prototype chain.
1106         bool is_local = (*global == lookup.holder());
1107         // Get the property attributes and determine if the property is
1108         // read-only.
1109         PropertyAttributes attributes = global->GetPropertyAttribute(*name);
1110         bool is_read_only = (attributes & READ_ONLY) != 0;
1111         if (lookup.type() == INTERCEPTOR) {
1112           // If the interceptor says the property is there, we
1113           // just return undefined without overwriting the property.
1114           // Otherwise, we continue to setting the property.
1115           if (attributes != ABSENT) {
1116             // Check if the existing property conflicts with regards to const.
1117             if (is_local && (is_read_only || is_const_property)) {
1118               const char* type = (is_read_only) ? "const" : "var";
1119               return ThrowRedeclarationError(isolate, type, name);
1120             };
1121             // The property already exists without conflicting: Go to
1122             // the next declaration.
1123             continue;
1124           }
1125           // Fall-through and introduce the absent property by using
1126           // SetProperty.
1127         } else {
1128           // For const properties, we treat a callback with this name
1129           // even in the prototype as a conflicting declaration.
1130           if (is_const_property && (lookup.type() == CALLBACKS)) {
1131             return ThrowRedeclarationError(isolate, "const", name);
1132           }
1133           // Otherwise, we check for locally conflicting declarations.
1134           if (is_local && (is_read_only || is_const_property)) {
1135             const char* type = (is_read_only) ? "const" : "var";
1136             return ThrowRedeclarationError(isolate, type, name);
1137           }
1138           // The property already exists without conflicting: Go to
1139           // the next declaration.
1140           continue;
1141         }
1142       }
1143     } else {
1144       // Copy the function and update its context. Use it as value.
1145       Handle<SharedFunctionInfo> shared =
1146           Handle<SharedFunctionInfo>::cast(value);
1147       Handle<JSFunction> function =
1148           isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
1149                                                                 context,
1150                                                                 TENURED);
1151       value = function;
1152     }
1153 
1154     LookupResult lookup;
1155     global->LocalLookup(*name, &lookup);
1156 
1157     PropertyAttributes attributes = is_const_property
1158         ? static_cast<PropertyAttributes>(base | READ_ONLY)
1159         : base;
1160 
1161     // There's a local property that we need to overwrite because
1162     // we're either declaring a function or there's an interceptor
1163     // that claims the property is absent.
1164     //
1165     // Check for conflicting re-declarations. We cannot have
1166     // conflicting types in case of intercepted properties because
1167     // they are absent.
1168     if (lookup.IsProperty() &&
1169         (lookup.type() != INTERCEPTOR) &&
1170         (lookup.IsReadOnly() || is_const_property)) {
1171       const char* type = (lookup.IsReadOnly()) ? "const" : "var";
1172       return ThrowRedeclarationError(isolate, type, name);
1173     }
1174 
1175     // Safari does not allow the invocation of callback setters for
1176     // function declarations. To mimic this behavior, we do not allow
1177     // the invocation of setters for function values. This makes a
1178     // difference for global functions with the same names as event
1179     // handlers such as "function onload() {}". Firefox does call the
1180     // onload setter in those case and Safari does not. We follow
1181     // Safari for compatibility.
1182     if (value->IsJSFunction()) {
1183       // Do not change DONT_DELETE to false from true.
1184       if (lookup.IsProperty() && (lookup.type() != INTERCEPTOR)) {
1185         attributes = static_cast<PropertyAttributes>(
1186             attributes | (lookup.GetAttributes() & DONT_DELETE));
1187       }
1188       RETURN_IF_EMPTY_HANDLE(isolate,
1189                              SetLocalPropertyIgnoreAttributes(global,
1190                                                               name,
1191                                                               value,
1192                                                               attributes));
1193     } else {
1194       RETURN_IF_EMPTY_HANDLE(isolate,
1195                              SetProperty(global,
1196                                          name,
1197                                          value,
1198                                          attributes,
1199                                          strict_mode));
1200     }
1201   }
1202 
1203   ASSERT(!isolate->has_pending_exception());
1204   return isolate->heap()->undefined_value();
1205 }
1206 
1207 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DeclareContextSlot)1208 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
1209   HandleScope scope(isolate);
1210   ASSERT(args.length() == 4);
1211 
1212   CONVERT_ARG_CHECKED(Context, context, 0);
1213   Handle<String> name(String::cast(args[1]));
1214   PropertyAttributes mode =
1215       static_cast<PropertyAttributes>(Smi::cast(args[2])->value());
1216   RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE);
1217   Handle<Object> initial_value(args[3], isolate);
1218 
1219   // Declarations are always done in the function context.
1220   context = Handle<Context>(context->fcontext());
1221 
1222   int index;
1223   PropertyAttributes attributes;
1224   ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
1225   Handle<Object> holder =
1226       context->Lookup(name, flags, &index, &attributes);
1227 
1228   if (attributes != ABSENT) {
1229     // The name was declared before; check for conflicting
1230     // re-declarations: This is similar to the code in parser.cc in
1231     // the AstBuildingParser::Declare function.
1232     if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
1233       // Functions are not read-only.
1234       ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
1235       const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
1236       return ThrowRedeclarationError(isolate, type, name);
1237     }
1238 
1239     // Initialize it if necessary.
1240     if (*initial_value != NULL) {
1241       if (index >= 0) {
1242         // The variable or constant context slot should always be in
1243         // the function context or the arguments object.
1244         if (holder->IsContext()) {
1245           ASSERT(holder.is_identical_to(context));
1246           if (((attributes & READ_ONLY) == 0) ||
1247               context->get(index)->IsTheHole()) {
1248             context->set(index, *initial_value);
1249           }
1250         } else {
1251           // The holder is an arguments object.
1252           Handle<JSObject> arguments(Handle<JSObject>::cast(holder));
1253           Handle<Object> result = SetElement(arguments, index, initial_value,
1254                                              kNonStrictMode);
1255           if (result.is_null()) return Failure::Exception();
1256         }
1257       } else {
1258         // Slow case: The property is not in the FixedArray part of the context.
1259         Handle<JSObject> context_ext = Handle<JSObject>::cast(holder);
1260         RETURN_IF_EMPTY_HANDLE(
1261             isolate,
1262             SetProperty(context_ext, name, initial_value,
1263                         mode, kNonStrictMode));
1264       }
1265     }
1266 
1267   } else {
1268     // The property is not in the function context. It needs to be
1269     // "declared" in the function context's extension context, or in the
1270     // global context.
1271     Handle<JSObject> context_ext;
1272     if (context->has_extension()) {
1273       // The function context's extension context exists - use it.
1274       context_ext = Handle<JSObject>(context->extension());
1275     } else {
1276       // The function context's extension context does not exists - allocate
1277       // it.
1278       context_ext = isolate->factory()->NewJSObject(
1279           isolate->context_extension_function());
1280       // And store it in the extension slot.
1281       context->set_extension(*context_ext);
1282     }
1283     ASSERT(*context_ext != NULL);
1284 
1285     // Declare the property by setting it to the initial value if provided,
1286     // or undefined, and use the correct mode (e.g. READ_ONLY attribute for
1287     // constant declarations).
1288     ASSERT(!context_ext->HasLocalProperty(*name));
1289     Handle<Object> value(isolate->heap()->undefined_value(), isolate);
1290     if (*initial_value != NULL) value = initial_value;
1291     // Declaring a const context slot is a conflicting declaration if
1292     // there is a callback with that name in a prototype. It is
1293     // allowed to introduce const variables in
1294     // JSContextExtensionObjects. They are treated specially in
1295     // SetProperty and no setters are invoked for those since they are
1296     // not real JSObjects.
1297     if (initial_value->IsTheHole() &&
1298         !context_ext->IsJSContextExtensionObject()) {
1299       LookupResult lookup;
1300       context_ext->Lookup(*name, &lookup);
1301       if (lookup.IsProperty() && (lookup.type() == CALLBACKS)) {
1302         return ThrowRedeclarationError(isolate, "const", name);
1303       }
1304     }
1305     RETURN_IF_EMPTY_HANDLE(isolate,
1306                            SetProperty(context_ext, name, value, mode,
1307                                        kNonStrictMode));
1308   }
1309 
1310   return isolate->heap()->undefined_value();
1311 }
1312 
1313 
RUNTIME_FUNCTION(MaybeObject *,Runtime_InitializeVarGlobal)1314 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
1315   NoHandleAllocation nha;
1316   // args[0] == name
1317   // args[1] == strict_mode
1318   // args[2] == value (optional)
1319 
1320   // Determine if we need to assign to the variable if it already
1321   // exists (based on the number of arguments).
1322   RUNTIME_ASSERT(args.length() == 2 || args.length() == 3);
1323   bool assign = args.length() == 3;
1324 
1325   CONVERT_ARG_CHECKED(String, name, 0);
1326   GlobalObject* global = isolate->context()->global();
1327   RUNTIME_ASSERT(args[1]->IsSmi());
1328   StrictModeFlag strict_mode =
1329       static_cast<StrictModeFlag>(Smi::cast(args[1])->value());
1330   ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode);
1331 
1332   // According to ECMA-262, section 12.2, page 62, the property must
1333   // not be deletable.
1334   PropertyAttributes attributes = DONT_DELETE;
1335 
1336   // Lookup the property locally in the global object. If it isn't
1337   // there, there is a property with this name in the prototype chain.
1338   // We follow Safari and Firefox behavior and only set the property
1339   // locally if there is an explicit initialization value that we have
1340   // to assign to the property.
1341   // Note that objects can have hidden prototypes, so we need to traverse
1342   // the whole chain of hidden prototypes to do a 'local' lookup.
1343   JSObject* real_holder = global;
1344   LookupResult lookup;
1345   while (true) {
1346     real_holder->LocalLookup(*name, &lookup);
1347     if (lookup.IsProperty()) {
1348       // Determine if this is a redeclaration of something read-only.
1349       if (lookup.IsReadOnly()) {
1350         // If we found readonly property on one of hidden prototypes,
1351         // just shadow it.
1352         if (real_holder != isolate->context()->global()) break;
1353         return ThrowRedeclarationError(isolate, "const", name);
1354       }
1355 
1356       // Determine if this is a redeclaration of an intercepted read-only
1357       // property and figure out if the property exists at all.
1358       bool found = true;
1359       PropertyType type = lookup.type();
1360       if (type == INTERCEPTOR) {
1361         HandleScope handle_scope(isolate);
1362         Handle<JSObject> holder(real_holder);
1363         PropertyAttributes intercepted = holder->GetPropertyAttribute(*name);
1364         real_holder = *holder;
1365         if (intercepted == ABSENT) {
1366           // The interceptor claims the property isn't there. We need to
1367           // make sure to introduce it.
1368           found = false;
1369         } else if ((intercepted & READ_ONLY) != 0) {
1370           // The property is present, but read-only. Since we're trying to
1371           // overwrite it with a variable declaration we must throw a
1372           // re-declaration error.  However if we found readonly property
1373           // on one of hidden prototypes, just shadow it.
1374           if (real_holder != isolate->context()->global()) break;
1375           return ThrowRedeclarationError(isolate, "const", name);
1376         }
1377       }
1378 
1379       if (found && !assign) {
1380         // The global property is there and we're not assigning any value
1381         // to it. Just return.
1382         return isolate->heap()->undefined_value();
1383       }
1384 
1385       // Assign the value (or undefined) to the property.
1386       Object* value = (assign) ? args[2] : isolate->heap()->undefined_value();
1387       return real_holder->SetProperty(
1388           &lookup, *name, value, attributes, strict_mode);
1389     }
1390 
1391     Object* proto = real_holder->GetPrototype();
1392     if (!proto->IsJSObject())
1393       break;
1394 
1395     if (!JSObject::cast(proto)->map()->is_hidden_prototype())
1396       break;
1397 
1398     real_holder = JSObject::cast(proto);
1399   }
1400 
1401   global = isolate->context()->global();
1402   if (assign) {
1403     return global->SetProperty(*name, args[2], attributes, strict_mode);
1404   }
1405   return isolate->heap()->undefined_value();
1406 }
1407 
1408 
RUNTIME_FUNCTION(MaybeObject *,Runtime_InitializeConstGlobal)1409 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
1410   // All constants are declared with an initial value. The name
1411   // of the constant is the first argument and the initial value
1412   // is the second.
1413   RUNTIME_ASSERT(args.length() == 2);
1414   CONVERT_ARG_CHECKED(String, name, 0);
1415   Handle<Object> value = args.at<Object>(1);
1416 
1417   // Get the current global object from top.
1418   GlobalObject* global = isolate->context()->global();
1419 
1420   // According to ECMA-262, section 12.2, page 62, the property must
1421   // not be deletable. Since it's a const, it must be READ_ONLY too.
1422   PropertyAttributes attributes =
1423       static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
1424 
1425   // Lookup the property locally in the global object. If it isn't
1426   // there, we add the property and take special precautions to always
1427   // add it as a local property even in case of callbacks in the
1428   // prototype chain (this rules out using SetProperty).
1429   // We use SetLocalPropertyIgnoreAttributes instead
1430   LookupResult lookup;
1431   global->LocalLookup(*name, &lookup);
1432   if (!lookup.IsProperty()) {
1433     return global->SetLocalPropertyIgnoreAttributes(*name,
1434                                                     *value,
1435                                                     attributes);
1436   }
1437 
1438   // Determine if this is a redeclaration of something not
1439   // read-only. In case the result is hidden behind an interceptor we
1440   // need to ask it for the property attributes.
1441   if (!lookup.IsReadOnly()) {
1442     if (lookup.type() != INTERCEPTOR) {
1443       return ThrowRedeclarationError(isolate, "var", name);
1444     }
1445 
1446     PropertyAttributes intercepted = global->GetPropertyAttribute(*name);
1447 
1448     // Throw re-declaration error if the intercepted property is present
1449     // but not read-only.
1450     if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
1451       return ThrowRedeclarationError(isolate, "var", name);
1452     }
1453 
1454     // Restore global object from context (in case of GC) and continue
1455     // with setting the value because the property is either absent or
1456     // read-only. We also have to do redo the lookup.
1457     HandleScope handle_scope(isolate);
1458     Handle<GlobalObject> global(isolate->context()->global());
1459 
1460     // BUG 1213575: Handle the case where we have to set a read-only
1461     // property through an interceptor and only do it if it's
1462     // uninitialized, e.g. the hole. Nirk...
1463     // Passing non-strict mode because the property is writable.
1464     RETURN_IF_EMPTY_HANDLE(isolate,
1465                            SetProperty(global,
1466                                        name,
1467                                        value,
1468                                        attributes,
1469                                        kNonStrictMode));
1470     return *value;
1471   }
1472 
1473   // Set the value, but only we're assigning the initial value to a
1474   // constant. For now, we determine this by checking if the
1475   // current value is the hole.
1476   // Strict mode handling not needed (const disallowed in strict mode).
1477   PropertyType type = lookup.type();
1478   if (type == FIELD) {
1479     FixedArray* properties = global->properties();
1480     int index = lookup.GetFieldIndex();
1481     if (properties->get(index)->IsTheHole()) {
1482       properties->set(index, *value);
1483     }
1484   } else if (type == NORMAL) {
1485     if (global->GetNormalizedProperty(&lookup)->IsTheHole()) {
1486       global->SetNormalizedProperty(&lookup, *value);
1487     }
1488   } else {
1489     // Ignore re-initialization of constants that have already been
1490     // assigned a function value.
1491     ASSERT(lookup.IsReadOnly() && type == CONSTANT_FUNCTION);
1492   }
1493 
1494   // Use the set value as the result of the operation.
1495   return *value;
1496 }
1497 
1498 
RUNTIME_FUNCTION(MaybeObject *,Runtime_InitializeConstContextSlot)1499 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) {
1500   HandleScope scope(isolate);
1501   ASSERT(args.length() == 3);
1502 
1503   Handle<Object> value(args[0], isolate);
1504   ASSERT(!value->IsTheHole());
1505   CONVERT_ARG_CHECKED(Context, context, 1);
1506   Handle<String> name(String::cast(args[2]));
1507 
1508   // Initializations are always done in the function context.
1509   context = Handle<Context>(context->fcontext());
1510 
1511   int index;
1512   PropertyAttributes attributes;
1513   ContextLookupFlags flags = FOLLOW_CHAINS;
1514   Handle<Object> holder =
1515       context->Lookup(name, flags, &index, &attributes);
1516 
1517   // In most situations, the property introduced by the const
1518   // declaration should be present in the context extension object.
1519   // However, because declaration and initialization are separate, the
1520   // property might have been deleted (if it was introduced by eval)
1521   // before we reach the initialization point.
1522   //
1523   // Example:
1524   //
1525   //    function f() { eval("delete x; const x;"); }
1526   //
1527   // In that case, the initialization behaves like a normal assignment
1528   // to property 'x'.
1529   if (index >= 0) {
1530     // Property was found in a context.
1531     if (holder->IsContext()) {
1532       // The holder cannot be the function context.  If it is, there
1533       // should have been a const redeclaration error when declaring
1534       // the const property.
1535       ASSERT(!holder.is_identical_to(context));
1536       if ((attributes & READ_ONLY) == 0) {
1537         Handle<Context>::cast(holder)->set(index, *value);
1538       }
1539     } else {
1540       // The holder is an arguments object.
1541       ASSERT((attributes & READ_ONLY) == 0);
1542       Handle<JSObject> arguments(Handle<JSObject>::cast(holder));
1543       RETURN_IF_EMPTY_HANDLE(
1544           isolate,
1545           SetElement(arguments, index, value, kNonStrictMode));
1546     }
1547     return *value;
1548   }
1549 
1550   // The property could not be found, we introduce it in the global
1551   // context.
1552   if (attributes == ABSENT) {
1553     Handle<JSObject> global = Handle<JSObject>(
1554         isolate->context()->global());
1555     // Strict mode not needed (const disallowed in strict mode).
1556     RETURN_IF_EMPTY_HANDLE(
1557         isolate,
1558         SetProperty(global, name, value, NONE, kNonStrictMode));
1559     return *value;
1560   }
1561 
1562   // The property was present in a context extension object.
1563   Handle<JSObject> context_ext = Handle<JSObject>::cast(holder);
1564 
1565   if (*context_ext == context->extension()) {
1566     // This is the property that was introduced by the const
1567     // declaration.  Set it if it hasn't been set before.  NOTE: We
1568     // cannot use GetProperty() to get the current value as it
1569     // 'unholes' the value.
1570     LookupResult lookup;
1571     context_ext->LocalLookupRealNamedProperty(*name, &lookup);
1572     ASSERT(lookup.IsProperty());  // the property was declared
1573     ASSERT(lookup.IsReadOnly());  // and it was declared as read-only
1574 
1575     PropertyType type = lookup.type();
1576     if (type == FIELD) {
1577       FixedArray* properties = context_ext->properties();
1578       int index = lookup.GetFieldIndex();
1579       if (properties->get(index)->IsTheHole()) {
1580         properties->set(index, *value);
1581       }
1582     } else if (type == NORMAL) {
1583       if (context_ext->GetNormalizedProperty(&lookup)->IsTheHole()) {
1584         context_ext->SetNormalizedProperty(&lookup, *value);
1585       }
1586     } else {
1587       // We should not reach here. Any real, named property should be
1588       // either a field or a dictionary slot.
1589       UNREACHABLE();
1590     }
1591   } else {
1592     // The property was found in a different context extension object.
1593     // Set it if it is not a read-only property.
1594     if ((attributes & READ_ONLY) == 0) {
1595       // Strict mode not needed (const disallowed in strict mode).
1596       RETURN_IF_EMPTY_HANDLE(
1597           isolate,
1598           SetProperty(context_ext, name, value, attributes, kNonStrictMode));
1599     }
1600   }
1601 
1602   return *value;
1603 }
1604 
1605 
RUNTIME_FUNCTION(MaybeObject *,Runtime_OptimizeObjectForAddingMultipleProperties)1606 RUNTIME_FUNCTION(MaybeObject*,
1607                  Runtime_OptimizeObjectForAddingMultipleProperties) {
1608   HandleScope scope(isolate);
1609   ASSERT(args.length() == 2);
1610   CONVERT_ARG_CHECKED(JSObject, object, 0);
1611   CONVERT_SMI_CHECKED(properties, args[1]);
1612   if (object->HasFastProperties()) {
1613     NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties);
1614   }
1615   return *object;
1616 }
1617 
1618 
RUNTIME_FUNCTION(MaybeObject *,Runtime_RegExpExec)1619 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) {
1620   HandleScope scope(isolate);
1621   ASSERT(args.length() == 4);
1622   CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
1623   CONVERT_ARG_CHECKED(String, subject, 1);
1624   // Due to the way the JS calls are constructed this must be less than the
1625   // length of a string, i.e. it is always a Smi.  We check anyway for security.
1626   CONVERT_SMI_CHECKED(index, args[2]);
1627   CONVERT_ARG_CHECKED(JSArray, last_match_info, 3);
1628   RUNTIME_ASSERT(last_match_info->HasFastElements());
1629   RUNTIME_ASSERT(index >= 0);
1630   RUNTIME_ASSERT(index <= subject->length());
1631   isolate->counters()->regexp_entry_runtime()->Increment();
1632   Handle<Object> result = RegExpImpl::Exec(regexp,
1633                                            subject,
1634                                            index,
1635                                            last_match_info);
1636   if (result.is_null()) return Failure::Exception();
1637   return *result;
1638 }
1639 
1640 
RUNTIME_FUNCTION(MaybeObject *,Runtime_RegExpConstructResult)1641 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpConstructResult) {
1642   ASSERT(args.length() == 3);
1643   CONVERT_SMI_CHECKED(elements_count, args[0]);
1644   if (elements_count > JSArray::kMaxFastElementsLength) {
1645     return isolate->ThrowIllegalOperation();
1646   }
1647   Object* new_object;
1648   { MaybeObject* maybe_new_object =
1649         isolate->heap()->AllocateFixedArrayWithHoles(elements_count);
1650     if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
1651   }
1652   FixedArray* elements = FixedArray::cast(new_object);
1653   { MaybeObject* maybe_new_object = isolate->heap()->AllocateRaw(
1654       JSRegExpResult::kSize, NEW_SPACE, OLD_POINTER_SPACE);
1655     if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
1656   }
1657   {
1658     AssertNoAllocation no_gc;
1659     HandleScope scope(isolate);
1660     reinterpret_cast<HeapObject*>(new_object)->
1661         set_map(isolate->global_context()->regexp_result_map());
1662   }
1663   JSArray* array = JSArray::cast(new_object);
1664   array->set_properties(isolate->heap()->empty_fixed_array());
1665   array->set_elements(elements);
1666   array->set_length(Smi::FromInt(elements_count));
1667   // Write in-object properties after the length of the array.
1668   array->InObjectPropertyAtPut(JSRegExpResult::kIndexIndex, args[1]);
1669   array->InObjectPropertyAtPut(JSRegExpResult::kInputIndex, args[2]);
1670   return array;
1671 }
1672 
1673 
RUNTIME_FUNCTION(MaybeObject *,Runtime_RegExpInitializeObject)1674 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) {
1675   AssertNoAllocation no_alloc;
1676   ASSERT(args.length() == 5);
1677   CONVERT_CHECKED(JSRegExp, regexp, args[0]);
1678   CONVERT_CHECKED(String, source, args[1]);
1679 
1680   Object* global = args[2];
1681   if (!global->IsTrue()) global = isolate->heap()->false_value();
1682 
1683   Object* ignoreCase = args[3];
1684   if (!ignoreCase->IsTrue()) ignoreCase = isolate->heap()->false_value();
1685 
1686   Object* multiline = args[4];
1687   if (!multiline->IsTrue()) multiline = isolate->heap()->false_value();
1688 
1689   Map* map = regexp->map();
1690   Object* constructor = map->constructor();
1691   if (constructor->IsJSFunction() &&
1692       JSFunction::cast(constructor)->initial_map() == map) {
1693     // If we still have the original map, set in-object properties directly.
1694     regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, source);
1695     // TODO(lrn): Consider skipping write barrier on booleans as well.
1696     // Both true and false should be in oldspace at all times.
1697     regexp->InObjectPropertyAtPut(JSRegExp::kGlobalFieldIndex, global);
1698     regexp->InObjectPropertyAtPut(JSRegExp::kIgnoreCaseFieldIndex, ignoreCase);
1699     regexp->InObjectPropertyAtPut(JSRegExp::kMultilineFieldIndex, multiline);
1700     regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex,
1701                                   Smi::FromInt(0),
1702                                   SKIP_WRITE_BARRIER);
1703     return regexp;
1704   }
1705 
1706   // Map has changed, so use generic, but slower, method.
1707   PropertyAttributes final =
1708       static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE);
1709   PropertyAttributes writable =
1710       static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
1711   Heap* heap = isolate->heap();
1712   MaybeObject* result;
1713   result = regexp->SetLocalPropertyIgnoreAttributes(heap->source_symbol(),
1714                                                     source,
1715                                                     final);
1716   ASSERT(!result->IsFailure());
1717   result = regexp->SetLocalPropertyIgnoreAttributes(heap->global_symbol(),
1718                                                     global,
1719                                                     final);
1720   ASSERT(!result->IsFailure());
1721   result =
1722       regexp->SetLocalPropertyIgnoreAttributes(heap->ignore_case_symbol(),
1723                                                ignoreCase,
1724                                                final);
1725   ASSERT(!result->IsFailure());
1726   result = regexp->SetLocalPropertyIgnoreAttributes(heap->multiline_symbol(),
1727                                                     multiline,
1728                                                     final);
1729   ASSERT(!result->IsFailure());
1730   result =
1731       regexp->SetLocalPropertyIgnoreAttributes(heap->last_index_symbol(),
1732                                                Smi::FromInt(0),
1733                                                writable);
1734   ASSERT(!result->IsFailure());
1735   USE(result);
1736   return regexp;
1737 }
1738 
1739 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FinishArrayPrototypeSetup)1740 RUNTIME_FUNCTION(MaybeObject*, Runtime_FinishArrayPrototypeSetup) {
1741   HandleScope scope(isolate);
1742   ASSERT(args.length() == 1);
1743   CONVERT_ARG_CHECKED(JSArray, prototype, 0);
1744   // This is necessary to enable fast checks for absence of elements
1745   // on Array.prototype and below.
1746   prototype->set_elements(isolate->heap()->empty_fixed_array());
1747   return Smi::FromInt(0);
1748 }
1749 
1750 
InstallBuiltin(Isolate * isolate,Handle<JSObject> holder,const char * name,Builtins::Name builtin_name)1751 static Handle<JSFunction> InstallBuiltin(Isolate* isolate,
1752                                          Handle<JSObject> holder,
1753                                          const char* name,
1754                                          Builtins::Name builtin_name) {
1755   Handle<String> key = isolate->factory()->LookupAsciiSymbol(name);
1756   Handle<Code> code(isolate->builtins()->builtin(builtin_name));
1757   Handle<JSFunction> optimized =
1758       isolate->factory()->NewFunction(key,
1759                                       JS_OBJECT_TYPE,
1760                                       JSObject::kHeaderSize,
1761                                       code,
1762                                       false);
1763   optimized->shared()->DontAdaptArguments();
1764   SetProperty(holder, key, optimized, NONE, kStrictMode);
1765   return optimized;
1766 }
1767 
1768 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SpecialArrayFunctions)1769 RUNTIME_FUNCTION(MaybeObject*, Runtime_SpecialArrayFunctions) {
1770   HandleScope scope(isolate);
1771   ASSERT(args.length() == 1);
1772   CONVERT_ARG_CHECKED(JSObject, holder, 0);
1773 
1774   InstallBuiltin(isolate, holder, "pop", Builtins::kArrayPop);
1775   InstallBuiltin(isolate, holder, "push", Builtins::kArrayPush);
1776   InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift);
1777   InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift);
1778   InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice);
1779   InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
1780   InstallBuiltin(isolate, holder, "concat", Builtins::kArrayConcat);
1781 
1782   return *holder;
1783 }
1784 
1785 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetGlobalReceiver)1786 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetGlobalReceiver) {
1787   // Returns a real global receiver, not one of builtins object.
1788   Context* global_context =
1789       isolate->context()->global()->global_context();
1790   return global_context->global()->global_receiver();
1791 }
1792 
1793 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MaterializeRegExpLiteral)1794 RUNTIME_FUNCTION(MaybeObject*, Runtime_MaterializeRegExpLiteral) {
1795   HandleScope scope(isolate);
1796   ASSERT(args.length() == 4);
1797   CONVERT_ARG_CHECKED(FixedArray, literals, 0);
1798   int index = Smi::cast(args[1])->value();
1799   Handle<String> pattern = args.at<String>(2);
1800   Handle<String> flags = args.at<String>(3);
1801 
1802   // Get the RegExp function from the context in the literals array.
1803   // This is the RegExp function from the context in which the
1804   // function was created.  We do not use the RegExp function from the
1805   // current global context because this might be the RegExp function
1806   // from another context which we should not have access to.
1807   Handle<JSFunction> constructor =
1808       Handle<JSFunction>(
1809           JSFunction::GlobalContextFromLiterals(*literals)->regexp_function());
1810   // Compute the regular expression literal.
1811   bool has_pending_exception;
1812   Handle<Object> regexp =
1813       RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
1814                                       &has_pending_exception);
1815   if (has_pending_exception) {
1816     ASSERT(isolate->has_pending_exception());
1817     return Failure::Exception();
1818   }
1819   literals->set(index, *regexp);
1820   return *regexp;
1821 }
1822 
1823 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionGetName)1824 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetName) {
1825   NoHandleAllocation ha;
1826   ASSERT(args.length() == 1);
1827 
1828   CONVERT_CHECKED(JSFunction, f, args[0]);
1829   return f->shared()->name();
1830 }
1831 
1832 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionSetName)1833 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetName) {
1834   NoHandleAllocation ha;
1835   ASSERT(args.length() == 2);
1836 
1837   CONVERT_CHECKED(JSFunction, f, args[0]);
1838   CONVERT_CHECKED(String, name, args[1]);
1839   f->shared()->set_name(name);
1840   return isolate->heap()->undefined_value();
1841 }
1842 
1843 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionRemovePrototype)1844 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) {
1845   NoHandleAllocation ha;
1846   ASSERT(args.length() == 1);
1847 
1848   CONVERT_CHECKED(JSFunction, f, args[0]);
1849   Object* obj = f->RemovePrototype();
1850   if (obj->IsFailure()) return obj;
1851 
1852   return isolate->heap()->undefined_value();
1853 }
1854 
1855 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionGetScript)1856 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScript) {
1857   HandleScope scope(isolate);
1858   ASSERT(args.length() == 1);
1859 
1860   CONVERT_CHECKED(JSFunction, fun, args[0]);
1861   Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate);
1862   if (!script->IsScript()) return isolate->heap()->undefined_value();
1863 
1864   return *GetScriptWrapper(Handle<Script>::cast(script));
1865 }
1866 
1867 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionGetSourceCode)1868 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetSourceCode) {
1869   NoHandleAllocation ha;
1870   ASSERT(args.length() == 1);
1871 
1872   CONVERT_CHECKED(JSFunction, f, args[0]);
1873   return f->shared()->GetSourceCode();
1874 }
1875 
1876 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionGetScriptSourcePosition)1877 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScriptSourcePosition) {
1878   NoHandleAllocation ha;
1879   ASSERT(args.length() == 1);
1880 
1881   CONVERT_CHECKED(JSFunction, fun, args[0]);
1882   int pos = fun->shared()->start_position();
1883   return Smi::FromInt(pos);
1884 }
1885 
1886 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionGetPositionForOffset)1887 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetPositionForOffset) {
1888   ASSERT(args.length() == 2);
1889 
1890   CONVERT_CHECKED(Code, code, args[0]);
1891   CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]);
1892 
1893   RUNTIME_ASSERT(0 <= offset && offset < code->Size());
1894 
1895   Address pc = code->address() + offset;
1896   return Smi::FromInt(code->SourcePosition(pc));
1897 }
1898 
1899 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionSetInstanceClassName)1900 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetInstanceClassName) {
1901   NoHandleAllocation ha;
1902   ASSERT(args.length() == 2);
1903 
1904   CONVERT_CHECKED(JSFunction, fun, args[0]);
1905   CONVERT_CHECKED(String, name, args[1]);
1906   fun->SetInstanceClassName(name);
1907   return isolate->heap()->undefined_value();
1908 }
1909 
1910 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionSetLength)1911 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetLength) {
1912   NoHandleAllocation ha;
1913   ASSERT(args.length() == 2);
1914 
1915   CONVERT_CHECKED(JSFunction, fun, args[0]);
1916   CONVERT_CHECKED(Smi, length, args[1]);
1917   fun->shared()->set_length(length->value());
1918   return length;
1919 }
1920 
1921 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionSetPrototype)1922 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) {
1923   NoHandleAllocation ha;
1924   ASSERT(args.length() == 2);
1925 
1926   CONVERT_CHECKED(JSFunction, fun, args[0]);
1927   ASSERT(fun->should_have_prototype());
1928   Object* obj;
1929   { MaybeObject* maybe_obj =
1930         Accessors::FunctionSetPrototype(fun, args[1], NULL);
1931     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1932   }
1933   return args[0];  // return TOS
1934 }
1935 
1936 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionIsAPIFunction)1937 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) {
1938   NoHandleAllocation ha;
1939   ASSERT(args.length() == 1);
1940 
1941   CONVERT_CHECKED(JSFunction, f, args[0]);
1942   return f->shared()->IsApiFunction() ? isolate->heap()->true_value()
1943                                       : isolate->heap()->false_value();
1944 }
1945 
1946 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionIsBuiltin)1947 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) {
1948   NoHandleAllocation ha;
1949   ASSERT(args.length() == 1);
1950 
1951   CONVERT_CHECKED(JSFunction, f, args[0]);
1952   return f->IsBuiltin() ? isolate->heap()->true_value() :
1953                           isolate->heap()->false_value();
1954 }
1955 
1956 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetCode)1957 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
1958   HandleScope scope(isolate);
1959   ASSERT(args.length() == 2);
1960 
1961   CONVERT_ARG_CHECKED(JSFunction, target, 0);
1962   Handle<Object> code = args.at<Object>(1);
1963 
1964   Handle<Context> context(target->context());
1965 
1966   if (!code->IsNull()) {
1967     RUNTIME_ASSERT(code->IsJSFunction());
1968     Handle<JSFunction> fun = Handle<JSFunction>::cast(code);
1969     Handle<SharedFunctionInfo> shared(fun->shared());
1970 
1971     if (!EnsureCompiled(shared, KEEP_EXCEPTION)) {
1972       return Failure::Exception();
1973     }
1974     // Since we don't store the source for this we should never
1975     // optimize this.
1976     shared->code()->set_optimizable(false);
1977 
1978     // Set the code, scope info, formal parameter count,
1979     // and the length of the target function.
1980     target->shared()->set_code(shared->code());
1981     target->ReplaceCode(shared->code());
1982     target->shared()->set_scope_info(shared->scope_info());
1983     target->shared()->set_length(shared->length());
1984     target->shared()->set_formal_parameter_count(
1985         shared->formal_parameter_count());
1986     // Set the source code of the target function to undefined.
1987     // SetCode is only used for built-in constructors like String,
1988     // Array, and Object, and some web code
1989     // doesn't like seeing source code for constructors.
1990     target->shared()->set_script(isolate->heap()->undefined_value());
1991     target->shared()->code()->set_optimizable(false);
1992     // Clear the optimization hints related to the compiled code as these are no
1993     // longer valid when the code is overwritten.
1994     target->shared()->ClearThisPropertyAssignmentsInfo();
1995     context = Handle<Context>(fun->context());
1996 
1997     // Make sure we get a fresh copy of the literal vector to avoid
1998     // cross context contamination.
1999     int number_of_literals = fun->NumberOfLiterals();
2000     Handle<FixedArray> literals =
2001         isolate->factory()->NewFixedArray(number_of_literals, TENURED);
2002     if (number_of_literals > 0) {
2003       // Insert the object, regexp and array functions in the literals
2004       // array prefix.  These are the functions that will be used when
2005       // creating object, regexp and array literals.
2006       literals->set(JSFunction::kLiteralGlobalContextIndex,
2007                     context->global_context());
2008     }
2009     // It's okay to skip the write barrier here because the literals
2010     // are guaranteed to be in old space.
2011     target->set_literals(*literals, SKIP_WRITE_BARRIER);
2012     target->set_next_function_link(isolate->heap()->undefined_value());
2013   }
2014 
2015   target->set_context(*context);
2016   return *target;
2017 }
2018 
2019 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetExpectedNumberOfProperties)2020 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetExpectedNumberOfProperties) {
2021   HandleScope scope(isolate);
2022   ASSERT(args.length() == 2);
2023   CONVERT_ARG_CHECKED(JSFunction, function, 0);
2024   CONVERT_SMI_CHECKED(num, args[1]);
2025   RUNTIME_ASSERT(num >= 0);
2026   SetExpectedNofProperties(function, num);
2027   return isolate->heap()->undefined_value();
2028 }
2029 
2030 
CharFromCode(Isolate * isolate,Object * char_code)2031 MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate,
2032                                                  Object* char_code) {
2033   uint32_t code;
2034   if (char_code->ToArrayIndex(&code)) {
2035     if (code <= 0xffff) {
2036       return isolate->heap()->LookupSingleCharacterStringFromCode(code);
2037     }
2038   }
2039   return isolate->heap()->empty_string();
2040 }
2041 
2042 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringCharCodeAt)2043 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCharCodeAt) {
2044   NoHandleAllocation ha;
2045   ASSERT(args.length() == 2);
2046 
2047   CONVERT_CHECKED(String, subject, args[0]);
2048   Object* index = args[1];
2049   RUNTIME_ASSERT(index->IsNumber());
2050 
2051   uint32_t i = 0;
2052   if (index->IsSmi()) {
2053     int value = Smi::cast(index)->value();
2054     if (value < 0) return isolate->heap()->nan_value();
2055     i = value;
2056   } else {
2057     ASSERT(index->IsHeapNumber());
2058     double value = HeapNumber::cast(index)->value();
2059     i = static_cast<uint32_t>(DoubleToInteger(value));
2060   }
2061 
2062   // Flatten the string.  If someone wants to get a char at an index
2063   // in a cons string, it is likely that more indices will be
2064   // accessed.
2065   Object* flat;
2066   { MaybeObject* maybe_flat = subject->TryFlatten();
2067     if (!maybe_flat->ToObject(&flat)) return maybe_flat;
2068   }
2069   subject = String::cast(flat);
2070 
2071   if (i >= static_cast<uint32_t>(subject->length())) {
2072     return isolate->heap()->nan_value();
2073   }
2074 
2075   return Smi::FromInt(subject->Get(i));
2076 }
2077 
2078 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CharFromCode)2079 RUNTIME_FUNCTION(MaybeObject*, Runtime_CharFromCode) {
2080   NoHandleAllocation ha;
2081   ASSERT(args.length() == 1);
2082   return CharFromCode(isolate, args[0]);
2083 }
2084 
2085 
2086 class FixedArrayBuilder {
2087  public:
FixedArrayBuilder(Isolate * isolate,int initial_capacity)2088   explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity)
2089       : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)),
2090         length_(0) {
2091     // Require a non-zero initial size. Ensures that doubling the size to
2092     // extend the array will work.
2093     ASSERT(initial_capacity > 0);
2094   }
2095 
FixedArrayBuilder(Handle<FixedArray> backing_store)2096   explicit FixedArrayBuilder(Handle<FixedArray> backing_store)
2097       : array_(backing_store),
2098         length_(0) {
2099     // Require a non-zero initial size. Ensures that doubling the size to
2100     // extend the array will work.
2101     ASSERT(backing_store->length() > 0);
2102   }
2103 
HasCapacity(int elements)2104   bool HasCapacity(int elements) {
2105     int length = array_->length();
2106     int required_length = length_ + elements;
2107     return (length >= required_length);
2108   }
2109 
EnsureCapacity(int elements)2110   void EnsureCapacity(int elements) {
2111     int length = array_->length();
2112     int required_length = length_ + elements;
2113     if (length < required_length) {
2114       int new_length = length;
2115       do {
2116         new_length *= 2;
2117       } while (new_length < required_length);
2118       Handle<FixedArray> extended_array =
2119           array_->GetIsolate()->factory()->NewFixedArrayWithHoles(new_length);
2120       array_->CopyTo(0, *extended_array, 0, length_);
2121       array_ = extended_array;
2122     }
2123   }
2124 
Add(Object * value)2125   void Add(Object* value) {
2126     ASSERT(length_ < capacity());
2127     array_->set(length_, value);
2128     length_++;
2129   }
2130 
Add(Smi * value)2131   void Add(Smi* value) {
2132     ASSERT(length_ < capacity());
2133     array_->set(length_, value);
2134     length_++;
2135   }
2136 
array()2137   Handle<FixedArray> array() {
2138     return array_;
2139   }
2140 
length()2141   int length() {
2142     return length_;
2143   }
2144 
capacity()2145   int capacity() {
2146     return array_->length();
2147   }
2148 
ToJSArray()2149   Handle<JSArray> ToJSArray() {
2150     Handle<JSArray> result_array = FACTORY->NewJSArrayWithElements(array_);
2151     result_array->set_length(Smi::FromInt(length_));
2152     return result_array;
2153   }
2154 
ToJSArray(Handle<JSArray> target_array)2155   Handle<JSArray> ToJSArray(Handle<JSArray> target_array) {
2156     target_array->set_elements(*array_);
2157     target_array->set_length(Smi::FromInt(length_));
2158     return target_array;
2159   }
2160 
2161  private:
2162   Handle<FixedArray> array_;
2163   int length_;
2164 };
2165 
2166 
2167 // Forward declarations.
2168 const int kStringBuilderConcatHelperLengthBits = 11;
2169 const int kStringBuilderConcatHelperPositionBits = 19;
2170 
2171 template <typename schar>
2172 static inline void StringBuilderConcatHelper(String*,
2173                                              schar*,
2174                                              FixedArray*,
2175                                              int);
2176 
2177 typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits>
2178     StringBuilderSubstringLength;
2179 typedef BitField<int,
2180                  kStringBuilderConcatHelperLengthBits,
2181                  kStringBuilderConcatHelperPositionBits>
2182     StringBuilderSubstringPosition;
2183 
2184 
2185 class ReplacementStringBuilder {
2186  public:
ReplacementStringBuilder(Heap * heap,Handle<String> subject,int estimated_part_count)2187   ReplacementStringBuilder(Heap* heap,
2188                            Handle<String> subject,
2189                            int estimated_part_count)
2190       : heap_(heap),
2191         array_builder_(heap->isolate(), estimated_part_count),
2192         subject_(subject),
2193         character_count_(0),
2194         is_ascii_(subject->IsAsciiRepresentation()) {
2195     // Require a non-zero initial size. Ensures that doubling the size to
2196     // extend the array will work.
2197     ASSERT(estimated_part_count > 0);
2198   }
2199 
AddSubjectSlice(FixedArrayBuilder * builder,int from,int to)2200   static inline void AddSubjectSlice(FixedArrayBuilder* builder,
2201                                      int from,
2202                                      int to) {
2203     ASSERT(from >= 0);
2204     int length = to - from;
2205     ASSERT(length > 0);
2206     if (StringBuilderSubstringLength::is_valid(length) &&
2207         StringBuilderSubstringPosition::is_valid(from)) {
2208       int encoded_slice = StringBuilderSubstringLength::encode(length) |
2209           StringBuilderSubstringPosition::encode(from);
2210       builder->Add(Smi::FromInt(encoded_slice));
2211     } else {
2212       // Otherwise encode as two smis.
2213       builder->Add(Smi::FromInt(-length));
2214       builder->Add(Smi::FromInt(from));
2215     }
2216   }
2217 
2218 
EnsureCapacity(int elements)2219   void EnsureCapacity(int elements) {
2220     array_builder_.EnsureCapacity(elements);
2221   }
2222 
2223 
AddSubjectSlice(int from,int to)2224   void AddSubjectSlice(int from, int to) {
2225     AddSubjectSlice(&array_builder_, from, to);
2226     IncrementCharacterCount(to - from);
2227   }
2228 
2229 
AddString(Handle<String> string)2230   void AddString(Handle<String> string) {
2231     int length = string->length();
2232     ASSERT(length > 0);
2233     AddElement(*string);
2234     if (!string->IsAsciiRepresentation()) {
2235       is_ascii_ = false;
2236     }
2237     IncrementCharacterCount(length);
2238   }
2239 
2240 
ToString()2241   Handle<String> ToString() {
2242     if (array_builder_.length() == 0) {
2243       return heap_->isolate()->factory()->empty_string();
2244     }
2245 
2246     Handle<String> joined_string;
2247     if (is_ascii_) {
2248       joined_string = NewRawAsciiString(character_count_);
2249       AssertNoAllocation no_alloc;
2250       SeqAsciiString* seq = SeqAsciiString::cast(*joined_string);
2251       char* char_buffer = seq->GetChars();
2252       StringBuilderConcatHelper(*subject_,
2253                                 char_buffer,
2254                                 *array_builder_.array(),
2255                                 array_builder_.length());
2256     } else {
2257       // Non-ASCII.
2258       joined_string = NewRawTwoByteString(character_count_);
2259       AssertNoAllocation no_alloc;
2260       SeqTwoByteString* seq = SeqTwoByteString::cast(*joined_string);
2261       uc16* char_buffer = seq->GetChars();
2262       StringBuilderConcatHelper(*subject_,
2263                                 char_buffer,
2264                                 *array_builder_.array(),
2265                                 array_builder_.length());
2266     }
2267     return joined_string;
2268   }
2269 
2270 
IncrementCharacterCount(int by)2271   void IncrementCharacterCount(int by) {
2272     if (character_count_ > String::kMaxLength - by) {
2273       V8::FatalProcessOutOfMemory("String.replace result too large.");
2274     }
2275     character_count_ += by;
2276   }
2277 
GetParts()2278   Handle<JSArray> GetParts() {
2279     return array_builder_.ToJSArray();
2280   }
2281 
2282  private:
NewRawAsciiString(int size)2283   Handle<String> NewRawAsciiString(int size) {
2284     CALL_HEAP_FUNCTION(heap_->isolate(),
2285                        heap_->AllocateRawAsciiString(size), String);
2286   }
2287 
2288 
NewRawTwoByteString(int size)2289   Handle<String> NewRawTwoByteString(int size) {
2290     CALL_HEAP_FUNCTION(heap_->isolate(),
2291                        heap_->AllocateRawTwoByteString(size), String);
2292   }
2293 
2294 
AddElement(Object * element)2295   void AddElement(Object* element) {
2296     ASSERT(element->IsSmi() || element->IsString());
2297     ASSERT(array_builder_.capacity() > array_builder_.length());
2298     array_builder_.Add(element);
2299   }
2300 
2301   Heap* heap_;
2302   FixedArrayBuilder array_builder_;
2303   Handle<String> subject_;
2304   int character_count_;
2305   bool is_ascii_;
2306 };
2307 
2308 
2309 class CompiledReplacement {
2310  public:
CompiledReplacement()2311   CompiledReplacement()
2312       : parts_(1), replacement_substrings_(0) {}
2313 
2314   void Compile(Handle<String> replacement,
2315                int capture_count,
2316                int subject_length);
2317 
2318   void Apply(ReplacementStringBuilder* builder,
2319              int match_from,
2320              int match_to,
2321              Handle<JSArray> last_match_info);
2322 
2323   // Number of distinct parts of the replacement pattern.
parts()2324   int parts() {
2325     return parts_.length();
2326   }
2327  private:
2328   enum PartType {
2329     SUBJECT_PREFIX = 1,
2330     SUBJECT_SUFFIX,
2331     SUBJECT_CAPTURE,
2332     REPLACEMENT_SUBSTRING,
2333     REPLACEMENT_STRING,
2334 
2335     NUMBER_OF_PART_TYPES
2336   };
2337 
2338   struct ReplacementPart {
SubjectMatchv8::internal::CompiledReplacement::ReplacementPart2339     static inline ReplacementPart SubjectMatch() {
2340       return ReplacementPart(SUBJECT_CAPTURE, 0);
2341     }
SubjectCapturev8::internal::CompiledReplacement::ReplacementPart2342     static inline ReplacementPart SubjectCapture(int capture_index) {
2343       return ReplacementPart(SUBJECT_CAPTURE, capture_index);
2344     }
SubjectPrefixv8::internal::CompiledReplacement::ReplacementPart2345     static inline ReplacementPart SubjectPrefix() {
2346       return ReplacementPart(SUBJECT_PREFIX, 0);
2347     }
SubjectSuffixv8::internal::CompiledReplacement::ReplacementPart2348     static inline ReplacementPart SubjectSuffix(int subject_length) {
2349       return ReplacementPart(SUBJECT_SUFFIX, subject_length);
2350     }
ReplacementStringv8::internal::CompiledReplacement::ReplacementPart2351     static inline ReplacementPart ReplacementString() {
2352       return ReplacementPart(REPLACEMENT_STRING, 0);
2353     }
ReplacementSubStringv8::internal::CompiledReplacement::ReplacementPart2354     static inline ReplacementPart ReplacementSubString(int from, int to) {
2355       ASSERT(from >= 0);
2356       ASSERT(to > from);
2357       return ReplacementPart(-from, to);
2358     }
2359 
2360     // If tag <= 0 then it is the negation of a start index of a substring of
2361     // the replacement pattern, otherwise it's a value from PartType.
ReplacementPartv8::internal::CompiledReplacement::ReplacementPart2362     ReplacementPart(int tag, int data)
2363         : tag(tag), data(data) {
2364       // Must be non-positive or a PartType value.
2365       ASSERT(tag < NUMBER_OF_PART_TYPES);
2366     }
2367     // Either a value of PartType or a non-positive number that is
2368     // the negation of an index into the replacement string.
2369     int tag;
2370     // The data value's interpretation depends on the value of tag:
2371     // tag == SUBJECT_PREFIX ||
2372     // tag == SUBJECT_SUFFIX:  data is unused.
2373     // tag == SUBJECT_CAPTURE: data is the number of the capture.
2374     // tag == REPLACEMENT_SUBSTRING ||
2375     // tag == REPLACEMENT_STRING:    data is index into array of substrings
2376     //                               of the replacement string.
2377     // tag <= 0: Temporary representation of the substring of the replacement
2378     //           string ranging over -tag .. data.
2379     //           Is replaced by REPLACEMENT_{SUB,}STRING when we create the
2380     //           substring objects.
2381     int data;
2382   };
2383 
2384   template<typename Char>
ParseReplacementPattern(ZoneList<ReplacementPart> * parts,Vector<Char> characters,int capture_count,int subject_length)2385   static void ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
2386                                       Vector<Char> characters,
2387                                       int capture_count,
2388                                       int subject_length) {
2389     int length = characters.length();
2390     int last = 0;
2391     for (int i = 0; i < length; i++) {
2392       Char c = characters[i];
2393       if (c == '$') {
2394         int next_index = i + 1;
2395         if (next_index == length) {  // No next character!
2396           break;
2397         }
2398         Char c2 = characters[next_index];
2399         switch (c2) {
2400         case '$':
2401           if (i > last) {
2402             // There is a substring before. Include the first "$".
2403             parts->Add(ReplacementPart::ReplacementSubString(last, next_index));
2404             last = next_index + 1;  // Continue after the second "$".
2405           } else {
2406             // Let the next substring start with the second "$".
2407             last = next_index;
2408           }
2409           i = next_index;
2410           break;
2411         case '`':
2412           if (i > last) {
2413             parts->Add(ReplacementPart::ReplacementSubString(last, i));
2414           }
2415           parts->Add(ReplacementPart::SubjectPrefix());
2416           i = next_index;
2417           last = i + 1;
2418           break;
2419         case '\'':
2420           if (i > last) {
2421             parts->Add(ReplacementPart::ReplacementSubString(last, i));
2422           }
2423           parts->Add(ReplacementPart::SubjectSuffix(subject_length));
2424           i = next_index;
2425           last = i + 1;
2426           break;
2427         case '&':
2428           if (i > last) {
2429             parts->Add(ReplacementPart::ReplacementSubString(last, i));
2430           }
2431           parts->Add(ReplacementPart::SubjectMatch());
2432           i = next_index;
2433           last = i + 1;
2434           break;
2435         case '0':
2436         case '1':
2437         case '2':
2438         case '3':
2439         case '4':
2440         case '5':
2441         case '6':
2442         case '7':
2443         case '8':
2444         case '9': {
2445           int capture_ref = c2 - '0';
2446           if (capture_ref > capture_count) {
2447             i = next_index;
2448             continue;
2449           }
2450           int second_digit_index = next_index + 1;
2451           if (second_digit_index < length) {
2452             // Peek ahead to see if we have two digits.
2453             Char c3 = characters[second_digit_index];
2454             if ('0' <= c3 && c3 <= '9') {  // Double digits.
2455               int double_digit_ref = capture_ref * 10 + c3 - '0';
2456               if (double_digit_ref <= capture_count) {
2457                 next_index = second_digit_index;
2458                 capture_ref = double_digit_ref;
2459               }
2460             }
2461           }
2462           if (capture_ref > 0) {
2463             if (i > last) {
2464               parts->Add(ReplacementPart::ReplacementSubString(last, i));
2465             }
2466             ASSERT(capture_ref <= capture_count);
2467             parts->Add(ReplacementPart::SubjectCapture(capture_ref));
2468             last = next_index + 1;
2469           }
2470           i = next_index;
2471           break;
2472         }
2473         default:
2474           i = next_index;
2475           break;
2476         }
2477       }
2478     }
2479     if (length > last) {
2480       if (last == 0) {
2481         parts->Add(ReplacementPart::ReplacementString());
2482       } else {
2483         parts->Add(ReplacementPart::ReplacementSubString(last, length));
2484       }
2485     }
2486   }
2487 
2488   ZoneList<ReplacementPart> parts_;
2489   ZoneList<Handle<String> > replacement_substrings_;
2490 };
2491 
2492 
Compile(Handle<String> replacement,int capture_count,int subject_length)2493 void CompiledReplacement::Compile(Handle<String> replacement,
2494                                   int capture_count,
2495                                   int subject_length) {
2496   ASSERT(replacement->IsFlat());
2497   if (replacement->IsAsciiRepresentation()) {
2498     AssertNoAllocation no_alloc;
2499     ParseReplacementPattern(&parts_,
2500                             replacement->ToAsciiVector(),
2501                             capture_count,
2502                             subject_length);
2503   } else {
2504     ASSERT(replacement->IsTwoByteRepresentation());
2505     AssertNoAllocation no_alloc;
2506 
2507     ParseReplacementPattern(&parts_,
2508                             replacement->ToUC16Vector(),
2509                             capture_count,
2510                             subject_length);
2511   }
2512   Isolate* isolate = replacement->GetIsolate();
2513   // Find substrings of replacement string and create them as String objects.
2514   int substring_index = 0;
2515   for (int i = 0, n = parts_.length(); i < n; i++) {
2516     int tag = parts_[i].tag;
2517     if (tag <= 0) {  // A replacement string slice.
2518       int from = -tag;
2519       int to = parts_[i].data;
2520       replacement_substrings_.Add(
2521           isolate->factory()->NewSubString(replacement, from, to));
2522       parts_[i].tag = REPLACEMENT_SUBSTRING;
2523       parts_[i].data = substring_index;
2524       substring_index++;
2525     } else if (tag == REPLACEMENT_STRING) {
2526       replacement_substrings_.Add(replacement);
2527       parts_[i].data = substring_index;
2528       substring_index++;
2529     }
2530   }
2531 }
2532 
2533 
Apply(ReplacementStringBuilder * builder,int match_from,int match_to,Handle<JSArray> last_match_info)2534 void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
2535                                 int match_from,
2536                                 int match_to,
2537                                 Handle<JSArray> last_match_info) {
2538   for (int i = 0, n = parts_.length(); i < n; i++) {
2539     ReplacementPart part = parts_[i];
2540     switch (part.tag) {
2541       case SUBJECT_PREFIX:
2542         if (match_from > 0) builder->AddSubjectSlice(0, match_from);
2543         break;
2544       case SUBJECT_SUFFIX: {
2545         int subject_length = part.data;
2546         if (match_to < subject_length) {
2547           builder->AddSubjectSlice(match_to, subject_length);
2548         }
2549         break;
2550       }
2551       case SUBJECT_CAPTURE: {
2552         int capture = part.data;
2553         FixedArray* match_info = FixedArray::cast(last_match_info->elements());
2554         int from = RegExpImpl::GetCapture(match_info, capture * 2);
2555         int to = RegExpImpl::GetCapture(match_info, capture * 2 + 1);
2556         if (from >= 0 && to > from) {
2557           builder->AddSubjectSlice(from, to);
2558         }
2559         break;
2560       }
2561       case REPLACEMENT_SUBSTRING:
2562       case REPLACEMENT_STRING:
2563         builder->AddString(replacement_substrings_[part.data]);
2564         break;
2565       default:
2566         UNREACHABLE();
2567     }
2568   }
2569 }
2570 
2571 
2572 
StringReplaceRegExpWithString(Isolate * isolate,String * subject,JSRegExp * regexp,String * replacement,JSArray * last_match_info)2573 MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithString(
2574     Isolate* isolate,
2575     String* subject,
2576     JSRegExp* regexp,
2577     String* replacement,
2578     JSArray* last_match_info) {
2579   ASSERT(subject->IsFlat());
2580   ASSERT(replacement->IsFlat());
2581 
2582   HandleScope handles(isolate);
2583 
2584   int length = subject->length();
2585   Handle<String> subject_handle(subject);
2586   Handle<JSRegExp> regexp_handle(regexp);
2587   Handle<String> replacement_handle(replacement);
2588   Handle<JSArray> last_match_info_handle(last_match_info);
2589   Handle<Object> match = RegExpImpl::Exec(regexp_handle,
2590                                           subject_handle,
2591                                           0,
2592                                           last_match_info_handle);
2593   if (match.is_null()) {
2594     return Failure::Exception();
2595   }
2596   if (match->IsNull()) {
2597     return *subject_handle;
2598   }
2599 
2600   int capture_count = regexp_handle->CaptureCount();
2601 
2602   // CompiledReplacement uses zone allocation.
2603   CompilationZoneScope zone(DELETE_ON_EXIT);
2604   CompiledReplacement compiled_replacement;
2605   compiled_replacement.Compile(replacement_handle,
2606                                capture_count,
2607                                length);
2608 
2609   bool is_global = regexp_handle->GetFlags().is_global();
2610 
2611   // Guessing the number of parts that the final result string is built
2612   // from. Global regexps can match any number of times, so we guess
2613   // conservatively.
2614   int expected_parts =
2615       (compiled_replacement.parts() + 1) * (is_global ? 4 : 1) + 1;
2616   ReplacementStringBuilder builder(isolate->heap(),
2617                                    subject_handle,
2618                                    expected_parts);
2619 
2620   // Index of end of last match.
2621   int prev = 0;
2622 
2623   // Number of parts added by compiled replacement plus preceeding
2624   // string and possibly suffix after last match.  It is possible for
2625   // all components to use two elements when encoded as two smis.
2626   const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2);
2627   bool matched = true;
2628   do {
2629     ASSERT(last_match_info_handle->HasFastElements());
2630     // Increase the capacity of the builder before entering local handle-scope,
2631     // so its internal buffer can safely allocate a new handle if it grows.
2632     builder.EnsureCapacity(parts_added_per_loop);
2633 
2634     HandleScope loop_scope(isolate);
2635     int start, end;
2636     {
2637       AssertNoAllocation match_info_array_is_not_in_a_handle;
2638       FixedArray* match_info_array =
2639           FixedArray::cast(last_match_info_handle->elements());
2640 
2641       ASSERT_EQ(capture_count * 2 + 2,
2642                 RegExpImpl::GetLastCaptureCount(match_info_array));
2643       start = RegExpImpl::GetCapture(match_info_array, 0);
2644       end = RegExpImpl::GetCapture(match_info_array, 1);
2645     }
2646 
2647     if (prev < start) {
2648       builder.AddSubjectSlice(prev, start);
2649     }
2650     compiled_replacement.Apply(&builder,
2651                                start,
2652                                end,
2653                                last_match_info_handle);
2654     prev = end;
2655 
2656     // Only continue checking for global regexps.
2657     if (!is_global) break;
2658 
2659     // Continue from where the match ended, unless it was an empty match.
2660     int next = end;
2661     if (start == end) {
2662       next = end + 1;
2663       if (next > length) break;
2664     }
2665 
2666     match = RegExpImpl::Exec(regexp_handle,
2667                              subject_handle,
2668                              next,
2669                              last_match_info_handle);
2670     if (match.is_null()) {
2671       return Failure::Exception();
2672     }
2673     matched = !match->IsNull();
2674   } while (matched);
2675 
2676   if (prev < length) {
2677     builder.AddSubjectSlice(prev, length);
2678   }
2679 
2680   return *(builder.ToString());
2681 }
2682 
2683 
2684 template <typename ResultSeqString>
StringReplaceRegExpWithEmptyString(Isolate * isolate,String * subject,JSRegExp * regexp,JSArray * last_match_info)2685 MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithEmptyString(
2686     Isolate* isolate,
2687     String* subject,
2688     JSRegExp* regexp,
2689     JSArray* last_match_info) {
2690   ASSERT(subject->IsFlat());
2691 
2692   HandleScope handles(isolate);
2693 
2694   Handle<String> subject_handle(subject);
2695   Handle<JSRegExp> regexp_handle(regexp);
2696   Handle<JSArray> last_match_info_handle(last_match_info);
2697   Handle<Object> match = RegExpImpl::Exec(regexp_handle,
2698                                           subject_handle,
2699                                           0,
2700                                           last_match_info_handle);
2701   if (match.is_null()) return Failure::Exception();
2702   if (match->IsNull()) return *subject_handle;
2703 
2704   ASSERT(last_match_info_handle->HasFastElements());
2705 
2706   int start, end;
2707   {
2708     AssertNoAllocation match_info_array_is_not_in_a_handle;
2709     FixedArray* match_info_array =
2710         FixedArray::cast(last_match_info_handle->elements());
2711 
2712     start = RegExpImpl::GetCapture(match_info_array, 0);
2713     end = RegExpImpl::GetCapture(match_info_array, 1);
2714   }
2715 
2716   int length = subject_handle->length();
2717   int new_length = length - (end - start);
2718   if (new_length == 0) {
2719     return isolate->heap()->empty_string();
2720   }
2721   Handle<ResultSeqString> answer;
2722   if (ResultSeqString::kHasAsciiEncoding) {
2723     answer = Handle<ResultSeqString>::cast(
2724         isolate->factory()->NewRawAsciiString(new_length));
2725   } else {
2726     answer = Handle<ResultSeqString>::cast(
2727         isolate->factory()->NewRawTwoByteString(new_length));
2728   }
2729 
2730   // If the regexp isn't global, only match once.
2731   if (!regexp_handle->GetFlags().is_global()) {
2732     if (start > 0) {
2733       String::WriteToFlat(*subject_handle,
2734                           answer->GetChars(),
2735                           0,
2736                           start);
2737     }
2738     if (end < length) {
2739       String::WriteToFlat(*subject_handle,
2740                           answer->GetChars() + start,
2741                           end,
2742                           length);
2743     }
2744     return *answer;
2745   }
2746 
2747   int prev = 0;  // Index of end of last match.
2748   int next = 0;  // Start of next search (prev unless last match was empty).
2749   int position = 0;
2750 
2751   do {
2752     if (prev < start) {
2753       // Add substring subject[prev;start] to answer string.
2754       String::WriteToFlat(*subject_handle,
2755                           answer->GetChars() + position,
2756                           prev,
2757                           start);
2758       position += start - prev;
2759     }
2760     prev = end;
2761     next = end;
2762     // Continue from where the match ended, unless it was an empty match.
2763     if (start == end) {
2764       next++;
2765       if (next > length) break;
2766     }
2767     match = RegExpImpl::Exec(regexp_handle,
2768                              subject_handle,
2769                              next,
2770                              last_match_info_handle);
2771     if (match.is_null()) return Failure::Exception();
2772     if (match->IsNull()) break;
2773 
2774     ASSERT(last_match_info_handle->HasFastElements());
2775     HandleScope loop_scope(isolate);
2776     {
2777       AssertNoAllocation match_info_array_is_not_in_a_handle;
2778       FixedArray* match_info_array =
2779           FixedArray::cast(last_match_info_handle->elements());
2780       start = RegExpImpl::GetCapture(match_info_array, 0);
2781       end = RegExpImpl::GetCapture(match_info_array, 1);
2782     }
2783   } while (true);
2784 
2785   if (prev < length) {
2786     // Add substring subject[prev;length] to answer string.
2787     String::WriteToFlat(*subject_handle,
2788                         answer->GetChars() + position,
2789                         prev,
2790                         length);
2791     position += length - prev;
2792   }
2793 
2794   if (position == 0) {
2795     return isolate->heap()->empty_string();
2796   }
2797 
2798   // Shorten string and fill
2799   int string_size = ResultSeqString::SizeFor(position);
2800   int allocated_string_size = ResultSeqString::SizeFor(new_length);
2801   int delta = allocated_string_size - string_size;
2802 
2803   answer->set_length(position);
2804   if (delta == 0) return *answer;
2805 
2806   Address end_of_string = answer->address() + string_size;
2807   isolate->heap()->CreateFillerObjectAt(end_of_string, delta);
2808 
2809   return *answer;
2810 }
2811 
2812 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringReplaceRegExpWithString)2813 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceRegExpWithString) {
2814   ASSERT(args.length() == 4);
2815 
2816   CONVERT_CHECKED(String, subject, args[0]);
2817   if (!subject->IsFlat()) {
2818     Object* flat_subject;
2819     { MaybeObject* maybe_flat_subject = subject->TryFlatten();
2820       if (!maybe_flat_subject->ToObject(&flat_subject)) {
2821         return maybe_flat_subject;
2822       }
2823     }
2824     subject = String::cast(flat_subject);
2825   }
2826 
2827   CONVERT_CHECKED(String, replacement, args[2]);
2828   if (!replacement->IsFlat()) {
2829     Object* flat_replacement;
2830     { MaybeObject* maybe_flat_replacement = replacement->TryFlatten();
2831       if (!maybe_flat_replacement->ToObject(&flat_replacement)) {
2832         return maybe_flat_replacement;
2833       }
2834     }
2835     replacement = String::cast(flat_replacement);
2836   }
2837 
2838   CONVERT_CHECKED(JSRegExp, regexp, args[1]);
2839   CONVERT_CHECKED(JSArray, last_match_info, args[3]);
2840 
2841   ASSERT(last_match_info->HasFastElements());
2842 
2843   if (replacement->length() == 0) {
2844     if (subject->HasOnlyAsciiChars()) {
2845       return StringReplaceRegExpWithEmptyString<SeqAsciiString>(
2846           isolate, subject, regexp, last_match_info);
2847     } else {
2848       return StringReplaceRegExpWithEmptyString<SeqTwoByteString>(
2849           isolate, subject, regexp, last_match_info);
2850     }
2851   }
2852 
2853   return StringReplaceRegExpWithString(isolate,
2854                                        subject,
2855                                        regexp,
2856                                        replacement,
2857                                        last_match_info);
2858 }
2859 
2860 
2861 // Perform string match of pattern on subject, starting at start index.
2862 // Caller must ensure that 0 <= start_index <= sub->length(),
2863 // and should check that pat->length() + start_index <= sub->length().
StringMatch(Isolate * isolate,Handle<String> sub,Handle<String> pat,int start_index)2864 int Runtime::StringMatch(Isolate* isolate,
2865                          Handle<String> sub,
2866                          Handle<String> pat,
2867                          int start_index) {
2868   ASSERT(0 <= start_index);
2869   ASSERT(start_index <= sub->length());
2870 
2871   int pattern_length = pat->length();
2872   if (pattern_length == 0) return start_index;
2873 
2874   int subject_length = sub->length();
2875   if (start_index + pattern_length > subject_length) return -1;
2876 
2877   if (!sub->IsFlat()) FlattenString(sub);
2878   if (!pat->IsFlat()) FlattenString(pat);
2879 
2880   AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
2881   // Extract flattened substrings of cons strings before determining asciiness.
2882   String* seq_sub = *sub;
2883   if (seq_sub->IsConsString()) seq_sub = ConsString::cast(seq_sub)->first();
2884   String* seq_pat = *pat;
2885   if (seq_pat->IsConsString()) seq_pat = ConsString::cast(seq_pat)->first();
2886 
2887   // dispatch on type of strings
2888   if (seq_pat->IsAsciiRepresentation()) {
2889     Vector<const char> pat_vector = seq_pat->ToAsciiVector();
2890     if (seq_sub->IsAsciiRepresentation()) {
2891       return SearchString(isolate,
2892                           seq_sub->ToAsciiVector(),
2893                           pat_vector,
2894                           start_index);
2895     }
2896     return SearchString(isolate,
2897                         seq_sub->ToUC16Vector(),
2898                         pat_vector,
2899                         start_index);
2900   }
2901   Vector<const uc16> pat_vector = seq_pat->ToUC16Vector();
2902   if (seq_sub->IsAsciiRepresentation()) {
2903     return SearchString(isolate,
2904                         seq_sub->ToAsciiVector(),
2905                         pat_vector,
2906                         start_index);
2907   }
2908   return SearchString(isolate,
2909                       seq_sub->ToUC16Vector(),
2910                       pat_vector,
2911                       start_index);
2912 }
2913 
2914 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringIndexOf)2915 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringIndexOf) {
2916   HandleScope scope(isolate);  // create a new handle scope
2917   ASSERT(args.length() == 3);
2918 
2919   CONVERT_ARG_CHECKED(String, sub, 0);
2920   CONVERT_ARG_CHECKED(String, pat, 1);
2921 
2922   Object* index = args[2];
2923   uint32_t start_index;
2924   if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
2925 
2926   RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
2927   int position =
2928       Runtime::StringMatch(isolate, sub, pat, start_index);
2929   return Smi::FromInt(position);
2930 }
2931 
2932 
2933 template <typename schar, typename pchar>
StringMatchBackwards(Vector<const schar> subject,Vector<const pchar> pattern,int idx)2934 static int StringMatchBackwards(Vector<const schar> subject,
2935                                 Vector<const pchar> pattern,
2936                                 int idx) {
2937   int pattern_length = pattern.length();
2938   ASSERT(pattern_length >= 1);
2939   ASSERT(idx + pattern_length <= subject.length());
2940 
2941   if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
2942     for (int i = 0; i < pattern_length; i++) {
2943       uc16 c = pattern[i];
2944       if (c > String::kMaxAsciiCharCode) {
2945         return -1;
2946       }
2947     }
2948   }
2949 
2950   pchar pattern_first_char = pattern[0];
2951   for (int i = idx; i >= 0; i--) {
2952     if (subject[i] != pattern_first_char) continue;
2953     int j = 1;
2954     while (j < pattern_length) {
2955       if (pattern[j] != subject[i+j]) {
2956         break;
2957       }
2958       j++;
2959     }
2960     if (j == pattern_length) {
2961       return i;
2962     }
2963   }
2964   return -1;
2965 }
2966 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringLastIndexOf)2967 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
2968   HandleScope scope(isolate);  // create a new handle scope
2969   ASSERT(args.length() == 3);
2970 
2971   CONVERT_ARG_CHECKED(String, sub, 0);
2972   CONVERT_ARG_CHECKED(String, pat, 1);
2973 
2974   Object* index = args[2];
2975   uint32_t start_index;
2976   if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
2977 
2978   uint32_t pat_length = pat->length();
2979   uint32_t sub_length = sub->length();
2980 
2981   if (start_index + pat_length > sub_length) {
2982     start_index = sub_length - pat_length;
2983   }
2984 
2985   if (pat_length == 0) {
2986     return Smi::FromInt(start_index);
2987   }
2988 
2989   if (!sub->IsFlat()) FlattenString(sub);
2990   if (!pat->IsFlat()) FlattenString(pat);
2991 
2992   AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
2993 
2994   int position = -1;
2995 
2996   if (pat->IsAsciiRepresentation()) {
2997     Vector<const char> pat_vector = pat->ToAsciiVector();
2998     if (sub->IsAsciiRepresentation()) {
2999       position = StringMatchBackwards(sub->ToAsciiVector(),
3000                                       pat_vector,
3001                                       start_index);
3002     } else {
3003       position = StringMatchBackwards(sub->ToUC16Vector(),
3004                                       pat_vector,
3005                                       start_index);
3006     }
3007   } else {
3008     Vector<const uc16> pat_vector = pat->ToUC16Vector();
3009     if (sub->IsAsciiRepresentation()) {
3010       position = StringMatchBackwards(sub->ToAsciiVector(),
3011                                       pat_vector,
3012                                       start_index);
3013     } else {
3014       position = StringMatchBackwards(sub->ToUC16Vector(),
3015                                       pat_vector,
3016                                       start_index);
3017     }
3018   }
3019 
3020   return Smi::FromInt(position);
3021 }
3022 
3023 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringLocaleCompare)3024 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
3025   NoHandleAllocation ha;
3026   ASSERT(args.length() == 2);
3027 
3028   CONVERT_CHECKED(String, str1, args[0]);
3029   CONVERT_CHECKED(String, str2, args[1]);
3030 
3031   if (str1 == str2) return Smi::FromInt(0);  // Equal.
3032   int str1_length = str1->length();
3033   int str2_length = str2->length();
3034 
3035   // Decide trivial cases without flattening.
3036   if (str1_length == 0) {
3037     if (str2_length == 0) return Smi::FromInt(0);  // Equal.
3038     return Smi::FromInt(-str2_length);
3039   } else {
3040     if (str2_length == 0) return Smi::FromInt(str1_length);
3041   }
3042 
3043   int end = str1_length < str2_length ? str1_length : str2_length;
3044 
3045   // No need to flatten if we are going to find the answer on the first
3046   // character.  At this point we know there is at least one character
3047   // in each string, due to the trivial case handling above.
3048   int d = str1->Get(0) - str2->Get(0);
3049   if (d != 0) return Smi::FromInt(d);
3050 
3051   str1->TryFlatten();
3052   str2->TryFlatten();
3053 
3054   StringInputBuffer& buf1 =
3055       *isolate->runtime_state()->string_locale_compare_buf1();
3056   StringInputBuffer& buf2 =
3057       *isolate->runtime_state()->string_locale_compare_buf2();
3058 
3059   buf1.Reset(str1);
3060   buf2.Reset(str2);
3061 
3062   for (int i = 0; i < end; i++) {
3063     uint16_t char1 = buf1.GetNext();
3064     uint16_t char2 = buf2.GetNext();
3065     if (char1 != char2) return Smi::FromInt(char1 - char2);
3066   }
3067 
3068   return Smi::FromInt(str1_length - str2_length);
3069 }
3070 
3071 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SubString)3072 RUNTIME_FUNCTION(MaybeObject*, Runtime_SubString) {
3073   NoHandleAllocation ha;
3074   ASSERT(args.length() == 3);
3075 
3076   CONVERT_CHECKED(String, value, args[0]);
3077   Object* from = args[1];
3078   Object* to = args[2];
3079   int start, end;
3080   // We have a fast integer-only case here to avoid a conversion to double in
3081   // the common case where from and to are Smis.
3082   if (from->IsSmi() && to->IsSmi()) {
3083     start = Smi::cast(from)->value();
3084     end = Smi::cast(to)->value();
3085   } else {
3086     CONVERT_DOUBLE_CHECKED(from_number, from);
3087     CONVERT_DOUBLE_CHECKED(to_number, to);
3088     start = FastD2I(from_number);
3089     end = FastD2I(to_number);
3090   }
3091   RUNTIME_ASSERT(end >= start);
3092   RUNTIME_ASSERT(start >= 0);
3093   RUNTIME_ASSERT(end <= value->length());
3094   isolate->counters()->sub_string_runtime()->Increment();
3095   return value->SubString(start, end);
3096 }
3097 
3098 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringMatch)3099 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) {
3100   ASSERT_EQ(3, args.length());
3101 
3102   CONVERT_ARG_CHECKED(String, subject, 0);
3103   CONVERT_ARG_CHECKED(JSRegExp, regexp, 1);
3104   CONVERT_ARG_CHECKED(JSArray, regexp_info, 2);
3105   HandleScope handles;
3106 
3107   Handle<Object> match = RegExpImpl::Exec(regexp, subject, 0, regexp_info);
3108 
3109   if (match.is_null()) {
3110     return Failure::Exception();
3111   }
3112   if (match->IsNull()) {
3113     return isolate->heap()->null_value();
3114   }
3115   int length = subject->length();
3116 
3117   CompilationZoneScope zone_space(DELETE_ON_EXIT);
3118   ZoneList<int> offsets(8);
3119   do {
3120     int start;
3121     int end;
3122     {
3123       AssertNoAllocation no_alloc;
3124       FixedArray* elements = FixedArray::cast(regexp_info->elements());
3125       start = Smi::cast(elements->get(RegExpImpl::kFirstCapture))->value();
3126       end = Smi::cast(elements->get(RegExpImpl::kFirstCapture + 1))->value();
3127     }
3128     offsets.Add(start);
3129     offsets.Add(end);
3130     int index = start < end ? end : end + 1;
3131     if (index > length) break;
3132     match = RegExpImpl::Exec(regexp, subject, index, regexp_info);
3133     if (match.is_null()) {
3134       return Failure::Exception();
3135     }
3136   } while (!match->IsNull());
3137   int matches = offsets.length() / 2;
3138   Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches);
3139   for (int i = 0; i < matches ; i++) {
3140     int from = offsets.at(i * 2);
3141     int to = offsets.at(i * 2 + 1);
3142     Handle<String> match = isolate->factory()->NewSubString(subject, from, to);
3143     elements->set(i, *match);
3144   }
3145   Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements);
3146   result->set_length(Smi::FromInt(matches));
3147   return *result;
3148 }
3149 
3150 
3151 // Two smis before and after the match, for very long strings.
3152 const int kMaxBuilderEntriesPerRegExpMatch = 5;
3153 
3154 
SetLastMatchInfoNoCaptures(Handle<String> subject,Handle<JSArray> last_match_info,int match_start,int match_end)3155 static void SetLastMatchInfoNoCaptures(Handle<String> subject,
3156                                        Handle<JSArray> last_match_info,
3157                                        int match_start,
3158                                        int match_end) {
3159   // Fill last_match_info with a single capture.
3160   last_match_info->EnsureSize(2 + RegExpImpl::kLastMatchOverhead);
3161   AssertNoAllocation no_gc;
3162   FixedArray* elements = FixedArray::cast(last_match_info->elements());
3163   RegExpImpl::SetLastCaptureCount(elements, 2);
3164   RegExpImpl::SetLastInput(elements, *subject);
3165   RegExpImpl::SetLastSubject(elements, *subject);
3166   RegExpImpl::SetCapture(elements, 0, match_start);
3167   RegExpImpl::SetCapture(elements, 1, match_end);
3168 }
3169 
3170 
3171 template <typename SubjectChar, typename PatternChar>
SearchStringMultiple(Isolate * isolate,Vector<const SubjectChar> subject,Vector<const PatternChar> pattern,String * pattern_string,FixedArrayBuilder * builder,int * match_pos)3172 static bool SearchStringMultiple(Isolate* isolate,
3173                                  Vector<const SubjectChar> subject,
3174                                  Vector<const PatternChar> pattern,
3175                                  String* pattern_string,
3176                                  FixedArrayBuilder* builder,
3177                                  int* match_pos) {
3178   int pos = *match_pos;
3179   int subject_length = subject.length();
3180   int pattern_length = pattern.length();
3181   int max_search_start = subject_length - pattern_length;
3182   StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
3183   while (pos <= max_search_start) {
3184     if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
3185       *match_pos = pos;
3186       return false;
3187     }
3188     // Position of end of previous match.
3189     int match_end = pos + pattern_length;
3190     int new_pos = search.Search(subject, match_end);
3191     if (new_pos >= 0) {
3192       // A match.
3193       if (new_pos > match_end) {
3194         ReplacementStringBuilder::AddSubjectSlice(builder,
3195             match_end,
3196             new_pos);
3197       }
3198       pos = new_pos;
3199       builder->Add(pattern_string);
3200     } else {
3201       break;
3202     }
3203   }
3204 
3205   if (pos < max_search_start) {
3206     ReplacementStringBuilder::AddSubjectSlice(builder,
3207                                               pos + pattern_length,
3208                                               subject_length);
3209   }
3210   *match_pos = pos;
3211   return true;
3212 }
3213 
3214 
SearchStringMultiple(Isolate * isolate,Handle<String> subject,Handle<String> pattern,Handle<JSArray> last_match_info,FixedArrayBuilder * builder)3215 static bool SearchStringMultiple(Isolate* isolate,
3216                                  Handle<String> subject,
3217                                  Handle<String> pattern,
3218                                  Handle<JSArray> last_match_info,
3219                                  FixedArrayBuilder* builder) {
3220   ASSERT(subject->IsFlat());
3221   ASSERT(pattern->IsFlat());
3222 
3223   // Treating as if a previous match was before first character.
3224   int match_pos = -pattern->length();
3225 
3226   for (;;) {  // Break when search complete.
3227     builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3228     AssertNoAllocation no_gc;
3229     if (subject->IsAsciiRepresentation()) {
3230       Vector<const char> subject_vector = subject->ToAsciiVector();
3231       if (pattern->IsAsciiRepresentation()) {
3232         if (SearchStringMultiple(isolate,
3233                                  subject_vector,
3234                                  pattern->ToAsciiVector(),
3235                                  *pattern,
3236                                  builder,
3237                                  &match_pos)) break;
3238       } else {
3239         if (SearchStringMultiple(isolate,
3240                                  subject_vector,
3241                                  pattern->ToUC16Vector(),
3242                                  *pattern,
3243                                  builder,
3244                                  &match_pos)) break;
3245       }
3246     } else {
3247       Vector<const uc16> subject_vector = subject->ToUC16Vector();
3248       if (pattern->IsAsciiRepresentation()) {
3249         if (SearchStringMultiple(isolate,
3250                                  subject_vector,
3251                                  pattern->ToAsciiVector(),
3252                                  *pattern,
3253                                  builder,
3254                                  &match_pos)) break;
3255       } else {
3256         if (SearchStringMultiple(isolate,
3257                                  subject_vector,
3258                                  pattern->ToUC16Vector(),
3259                                  *pattern,
3260                                  builder,
3261                                  &match_pos)) break;
3262       }
3263     }
3264   }
3265 
3266   if (match_pos >= 0) {
3267     SetLastMatchInfoNoCaptures(subject,
3268                                last_match_info,
3269                                match_pos,
3270                                match_pos + pattern->length());
3271     return true;
3272   }
3273   return false;  // No matches at all.
3274 }
3275 
3276 
SearchRegExpNoCaptureMultiple(Isolate * isolate,Handle<String> subject,Handle<JSRegExp> regexp,Handle<JSArray> last_match_array,FixedArrayBuilder * builder)3277 static RegExpImpl::IrregexpResult SearchRegExpNoCaptureMultiple(
3278     Isolate* isolate,
3279     Handle<String> subject,
3280     Handle<JSRegExp> regexp,
3281     Handle<JSArray> last_match_array,
3282     FixedArrayBuilder* builder) {
3283   ASSERT(subject->IsFlat());
3284   int match_start = -1;
3285   int match_end = 0;
3286   int pos = 0;
3287   int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject);
3288   if (required_registers < 0) return RegExpImpl::RE_EXCEPTION;
3289 
3290   OffsetsVector registers(required_registers);
3291   Vector<int32_t> register_vector(registers.vector(), registers.length());
3292   int subject_length = subject->length();
3293 
3294   for (;;) {  // Break on failure, return on exception.
3295     RegExpImpl::IrregexpResult result =
3296         RegExpImpl::IrregexpExecOnce(regexp,
3297                                      subject,
3298                                      pos,
3299                                      register_vector);
3300     if (result == RegExpImpl::RE_SUCCESS) {
3301       match_start = register_vector[0];
3302       builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3303       if (match_end < match_start) {
3304         ReplacementStringBuilder::AddSubjectSlice(builder,
3305                                                   match_end,
3306                                                   match_start);
3307       }
3308       match_end = register_vector[1];
3309       HandleScope loop_scope(isolate);
3310       builder->Add(*isolate->factory()->NewSubString(subject,
3311                                                      match_start,
3312                                                      match_end));
3313       if (match_start != match_end) {
3314         pos = match_end;
3315       } else {
3316         pos = match_end + 1;
3317         if (pos > subject_length) break;
3318       }
3319     } else if (result == RegExpImpl::RE_FAILURE) {
3320       break;
3321     } else {
3322       ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION);
3323       return result;
3324     }
3325   }
3326 
3327   if (match_start >= 0) {
3328     if (match_end < subject_length) {
3329       ReplacementStringBuilder::AddSubjectSlice(builder,
3330                                                 match_end,
3331                                                 subject_length);
3332     }
3333     SetLastMatchInfoNoCaptures(subject,
3334                                last_match_array,
3335                                match_start,
3336                                match_end);
3337     return RegExpImpl::RE_SUCCESS;
3338   } else {
3339     return RegExpImpl::RE_FAILURE;  // No matches at all.
3340   }
3341 }
3342 
3343 
SearchRegExpMultiple(Isolate * isolate,Handle<String> subject,Handle<JSRegExp> regexp,Handle<JSArray> last_match_array,FixedArrayBuilder * builder)3344 static RegExpImpl::IrregexpResult SearchRegExpMultiple(
3345     Isolate* isolate,
3346     Handle<String> subject,
3347     Handle<JSRegExp> regexp,
3348     Handle<JSArray> last_match_array,
3349     FixedArrayBuilder* builder) {
3350 
3351   ASSERT(subject->IsFlat());
3352   int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject);
3353   if (required_registers < 0) return RegExpImpl::RE_EXCEPTION;
3354 
3355   OffsetsVector registers(required_registers);
3356   Vector<int32_t> register_vector(registers.vector(), registers.length());
3357 
3358   RegExpImpl::IrregexpResult result =
3359       RegExpImpl::IrregexpExecOnce(regexp,
3360                                    subject,
3361                                    0,
3362                                    register_vector);
3363 
3364   int capture_count = regexp->CaptureCount();
3365   int subject_length = subject->length();
3366 
3367   // Position to search from.
3368   int pos = 0;
3369   // End of previous match. Differs from pos if match was empty.
3370   int match_end = 0;
3371   if (result == RegExpImpl::RE_SUCCESS) {
3372     // Need to keep a copy of the previous match for creating last_match_info
3373     // at the end, so we have two vectors that we swap between.
3374     OffsetsVector registers2(required_registers);
3375     Vector<int> prev_register_vector(registers2.vector(), registers2.length());
3376 
3377     do {
3378       int match_start = register_vector[0];
3379       builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3380       if (match_end < match_start) {
3381         ReplacementStringBuilder::AddSubjectSlice(builder,
3382                                                   match_end,
3383                                                   match_start);
3384       }
3385       match_end = register_vector[1];
3386 
3387       {
3388         // Avoid accumulating new handles inside loop.
3389         HandleScope temp_scope(isolate);
3390         // Arguments array to replace function is match, captures, index and
3391         // subject, i.e., 3 + capture count in total.
3392         Handle<FixedArray> elements =
3393             isolate->factory()->NewFixedArray(3 + capture_count);
3394         Handle<String> match = isolate->factory()->NewSubString(subject,
3395                                                                 match_start,
3396                                                                 match_end);
3397         elements->set(0, *match);
3398         for (int i = 1; i <= capture_count; i++) {
3399           int start = register_vector[i * 2];
3400           if (start >= 0) {
3401             int end = register_vector[i * 2 + 1];
3402             ASSERT(start <= end);
3403             Handle<String> substring = isolate->factory()->NewSubString(subject,
3404                                                                         start,
3405                                                                         end);
3406             elements->set(i, *substring);
3407           } else {
3408             ASSERT(register_vector[i * 2 + 1] < 0);
3409             elements->set(i, isolate->heap()->undefined_value());
3410           }
3411         }
3412         elements->set(capture_count + 1, Smi::FromInt(match_start));
3413         elements->set(capture_count + 2, *subject);
3414         builder->Add(*isolate->factory()->NewJSArrayWithElements(elements));
3415       }
3416       // Swap register vectors, so the last successful match is in
3417       // prev_register_vector.
3418       Vector<int32_t> tmp = prev_register_vector;
3419       prev_register_vector = register_vector;
3420       register_vector = tmp;
3421 
3422       if (match_end > match_start) {
3423         pos = match_end;
3424       } else {
3425         pos = match_end + 1;
3426         if (pos > subject_length) {
3427           break;
3428         }
3429       }
3430 
3431       result = RegExpImpl::IrregexpExecOnce(regexp,
3432                                             subject,
3433                                             pos,
3434                                             register_vector);
3435     } while (result == RegExpImpl::RE_SUCCESS);
3436 
3437     if (result != RegExpImpl::RE_EXCEPTION) {
3438       // Finished matching, with at least one match.
3439       if (match_end < subject_length) {
3440         ReplacementStringBuilder::AddSubjectSlice(builder,
3441                                                   match_end,
3442                                                   subject_length);
3443       }
3444 
3445       int last_match_capture_count = (capture_count + 1) * 2;
3446       int last_match_array_size =
3447           last_match_capture_count + RegExpImpl::kLastMatchOverhead;
3448       last_match_array->EnsureSize(last_match_array_size);
3449       AssertNoAllocation no_gc;
3450       FixedArray* elements = FixedArray::cast(last_match_array->elements());
3451       RegExpImpl::SetLastCaptureCount(elements, last_match_capture_count);
3452       RegExpImpl::SetLastSubject(elements, *subject);
3453       RegExpImpl::SetLastInput(elements, *subject);
3454       for (int i = 0; i < last_match_capture_count; i++) {
3455         RegExpImpl::SetCapture(elements, i, prev_register_vector[i]);
3456       }
3457       return RegExpImpl::RE_SUCCESS;
3458     }
3459   }
3460   // No matches at all, return failure or exception result directly.
3461   return result;
3462 }
3463 
3464 
RUNTIME_FUNCTION(MaybeObject *,Runtime_RegExpExecMultiple)3465 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) {
3466   ASSERT(args.length() == 4);
3467   HandleScope handles(isolate);
3468 
3469   CONVERT_ARG_CHECKED(String, subject, 1);
3470   if (!subject->IsFlat()) { FlattenString(subject); }
3471   CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
3472   CONVERT_ARG_CHECKED(JSArray, last_match_info, 2);
3473   CONVERT_ARG_CHECKED(JSArray, result_array, 3);
3474 
3475   ASSERT(last_match_info->HasFastElements());
3476   ASSERT(regexp->GetFlags().is_global());
3477   Handle<FixedArray> result_elements;
3478   if (result_array->HasFastElements()) {
3479     result_elements =
3480         Handle<FixedArray>(FixedArray::cast(result_array->elements()));
3481   } else {
3482     result_elements = isolate->factory()->NewFixedArrayWithHoles(16);
3483   }
3484   FixedArrayBuilder builder(result_elements);
3485 
3486   if (regexp->TypeTag() == JSRegExp::ATOM) {
3487     Handle<String> pattern(
3488         String::cast(regexp->DataAt(JSRegExp::kAtomPatternIndex)));
3489     ASSERT(pattern->IsFlat());
3490     if (SearchStringMultiple(isolate, subject, pattern,
3491                              last_match_info, &builder)) {
3492       return *builder.ToJSArray(result_array);
3493     }
3494     return isolate->heap()->null_value();
3495   }
3496 
3497   ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP);
3498 
3499   RegExpImpl::IrregexpResult result;
3500   if (regexp->CaptureCount() == 0) {
3501     result = SearchRegExpNoCaptureMultiple(isolate,
3502                                            subject,
3503                                            regexp,
3504                                            last_match_info,
3505                                            &builder);
3506   } else {
3507     result = SearchRegExpMultiple(isolate,
3508                                   subject,
3509                                   regexp,
3510                                   last_match_info,
3511                                   &builder);
3512   }
3513   if (result == RegExpImpl::RE_SUCCESS) return *builder.ToJSArray(result_array);
3514   if (result == RegExpImpl::RE_FAILURE) return isolate->heap()->null_value();
3515   ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION);
3516   return Failure::Exception();
3517 }
3518 
3519 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToRadixString)3520 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) {
3521   NoHandleAllocation ha;
3522   ASSERT(args.length() == 2);
3523 
3524   // Fast case where the result is a one character string.
3525   if (args[0]->IsSmi() && args[1]->IsSmi()) {
3526     int value = Smi::cast(args[0])->value();
3527     int radix = Smi::cast(args[1])->value();
3528     if (value >= 0 && value < radix) {
3529       RUNTIME_ASSERT(radix <= 36);
3530       // Character array used for conversion.
3531       static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
3532       return isolate->heap()->
3533           LookupSingleCharacterStringFromCode(kCharTable[value]);
3534     }
3535   }
3536 
3537   // Slow case.
3538   CONVERT_DOUBLE_CHECKED(value, args[0]);
3539   if (isnan(value)) {
3540     return isolate->heap()->AllocateStringFromAscii(CStrVector("NaN"));
3541   }
3542   if (isinf(value)) {
3543     if (value < 0) {
3544       return isolate->heap()->AllocateStringFromAscii(CStrVector("-Infinity"));
3545     }
3546     return isolate->heap()->AllocateStringFromAscii(CStrVector("Infinity"));
3547   }
3548   CONVERT_DOUBLE_CHECKED(radix_number, args[1]);
3549   int radix = FastD2I(radix_number);
3550   RUNTIME_ASSERT(2 <= radix && radix <= 36);
3551   char* str = DoubleToRadixCString(value, radix);
3552   MaybeObject* result =
3553       isolate->heap()->AllocateStringFromAscii(CStrVector(str));
3554   DeleteArray(str);
3555   return result;
3556 }
3557 
3558 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToFixed)3559 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) {
3560   NoHandleAllocation ha;
3561   ASSERT(args.length() == 2);
3562 
3563   CONVERT_DOUBLE_CHECKED(value, args[0]);
3564   if (isnan(value)) {
3565     return isolate->heap()->AllocateStringFromAscii(CStrVector("NaN"));
3566   }
3567   if (isinf(value)) {
3568     if (value < 0) {
3569       return isolate->heap()->AllocateStringFromAscii(CStrVector("-Infinity"));
3570     }
3571     return isolate->heap()->AllocateStringFromAscii(CStrVector("Infinity"));
3572   }
3573   CONVERT_DOUBLE_CHECKED(f_number, args[1]);
3574   int f = FastD2I(f_number);
3575   RUNTIME_ASSERT(f >= 0);
3576   char* str = DoubleToFixedCString(value, f);
3577   MaybeObject* res =
3578       isolate->heap()->AllocateStringFromAscii(CStrVector(str));
3579   DeleteArray(str);
3580   return res;
3581 }
3582 
3583 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToExponential)3584 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) {
3585   NoHandleAllocation ha;
3586   ASSERT(args.length() == 2);
3587 
3588   CONVERT_DOUBLE_CHECKED(value, args[0]);
3589   if (isnan(value)) {
3590     return isolate->heap()->AllocateStringFromAscii(CStrVector("NaN"));
3591   }
3592   if (isinf(value)) {
3593     if (value < 0) {
3594       return isolate->heap()->AllocateStringFromAscii(CStrVector("-Infinity"));
3595     }
3596     return isolate->heap()->AllocateStringFromAscii(CStrVector("Infinity"));
3597   }
3598   CONVERT_DOUBLE_CHECKED(f_number, args[1]);
3599   int f = FastD2I(f_number);
3600   RUNTIME_ASSERT(f >= -1 && f <= 20);
3601   char* str = DoubleToExponentialCString(value, f);
3602   MaybeObject* res =
3603       isolate->heap()->AllocateStringFromAscii(CStrVector(str));
3604   DeleteArray(str);
3605   return res;
3606 }
3607 
3608 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToPrecision)3609 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) {
3610   NoHandleAllocation ha;
3611   ASSERT(args.length() == 2);
3612 
3613   CONVERT_DOUBLE_CHECKED(value, args[0]);
3614   if (isnan(value)) {
3615     return isolate->heap()->AllocateStringFromAscii(CStrVector("NaN"));
3616   }
3617   if (isinf(value)) {
3618     if (value < 0) {
3619       return isolate->heap()->AllocateStringFromAscii(CStrVector("-Infinity"));
3620     }
3621     return isolate->heap()->AllocateStringFromAscii(CStrVector("Infinity"));
3622   }
3623   CONVERT_DOUBLE_CHECKED(f_number, args[1]);
3624   int f = FastD2I(f_number);
3625   RUNTIME_ASSERT(f >= 1 && f <= 21);
3626   char* str = DoubleToPrecisionCString(value, f);
3627   MaybeObject* res =
3628       isolate->heap()->AllocateStringFromAscii(CStrVector(str));
3629   DeleteArray(str);
3630   return res;
3631 }
3632 
3633 
3634 // Returns a single character string where first character equals
3635 // string->Get(index).
GetCharAt(Handle<String> string,uint32_t index)3636 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
3637   if (index < static_cast<uint32_t>(string->length())) {
3638     string->TryFlatten();
3639     return LookupSingleCharacterStringFromCode(
3640         string->Get(index));
3641   }
3642   return Execution::CharAt(string, index);
3643 }
3644 
3645 
GetElementOrCharAt(Isolate * isolate,Handle<Object> object,uint32_t index)3646 MaybeObject* Runtime::GetElementOrCharAt(Isolate* isolate,
3647                                          Handle<Object> object,
3648                                          uint32_t index) {
3649   // Handle [] indexing on Strings
3650   if (object->IsString()) {
3651     Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
3652     if (!result->IsUndefined()) return *result;
3653   }
3654 
3655   // Handle [] indexing on String objects
3656   if (object->IsStringObjectWithCharacterAt(index)) {
3657     Handle<JSValue> js_value = Handle<JSValue>::cast(object);
3658     Handle<Object> result =
3659         GetCharAt(Handle<String>(String::cast(js_value->value())), index);
3660     if (!result->IsUndefined()) return *result;
3661   }
3662 
3663   if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
3664     Handle<Object> prototype = GetPrototype(object);
3665     return prototype->GetElement(index);
3666   }
3667 
3668   return GetElement(object, index);
3669 }
3670 
3671 
GetElement(Handle<Object> object,uint32_t index)3672 MaybeObject* Runtime::GetElement(Handle<Object> object, uint32_t index) {
3673   return object->GetElement(index);
3674 }
3675 
3676 
GetObjectProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key)3677 MaybeObject* Runtime::GetObjectProperty(Isolate* isolate,
3678                                         Handle<Object> object,
3679                                         Handle<Object> key) {
3680   HandleScope scope(isolate);
3681 
3682   if (object->IsUndefined() || object->IsNull()) {
3683     Handle<Object> args[2] = { key, object };
3684     Handle<Object> error =
3685         isolate->factory()->NewTypeError("non_object_property_load",
3686                                          HandleVector(args, 2));
3687     return isolate->Throw(*error);
3688   }
3689 
3690   // Check if the given key is an array index.
3691   uint32_t index;
3692   if (key->ToArrayIndex(&index)) {
3693     return GetElementOrCharAt(isolate, object, index);
3694   }
3695 
3696   // Convert the key to a string - possibly by calling back into JavaScript.
3697   Handle<String> name;
3698   if (key->IsString()) {
3699     name = Handle<String>::cast(key);
3700   } else {
3701     bool has_pending_exception = false;
3702     Handle<Object> converted =
3703         Execution::ToString(key, &has_pending_exception);
3704     if (has_pending_exception) return Failure::Exception();
3705     name = Handle<String>::cast(converted);
3706   }
3707 
3708   // Check if the name is trivially convertible to an index and get
3709   // the element if so.
3710   if (name->AsArrayIndex(&index)) {
3711     return GetElementOrCharAt(isolate, object, index);
3712   } else {
3713     PropertyAttributes attr;
3714     return object->GetProperty(*name, &attr);
3715   }
3716 }
3717 
3718 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetProperty)3719 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetProperty) {
3720   NoHandleAllocation ha;
3721   ASSERT(args.length() == 2);
3722 
3723   Handle<Object> object = args.at<Object>(0);
3724   Handle<Object> key = args.at<Object>(1);
3725 
3726   return Runtime::GetObjectProperty(isolate, object, key);
3727 }
3728 
3729 
3730 // KeyedStringGetProperty is called from KeyedLoadIC::GenerateGeneric.
RUNTIME_FUNCTION(MaybeObject *,Runtime_KeyedGetProperty)3731 RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
3732   NoHandleAllocation ha;
3733   ASSERT(args.length() == 2);
3734 
3735   // Fast cases for getting named properties of the receiver JSObject
3736   // itself.
3737   //
3738   // The global proxy objects has to be excluded since LocalLookup on
3739   // the global proxy object can return a valid result even though the
3740   // global proxy object never has properties.  This is the case
3741   // because the global proxy object forwards everything to its hidden
3742   // prototype including local lookups.
3743   //
3744   // Additionally, we need to make sure that we do not cache results
3745   // for objects that require access checks.
3746   if (args[0]->IsJSObject() &&
3747       !args[0]->IsJSGlobalProxy() &&
3748       !args[0]->IsAccessCheckNeeded() &&
3749       args[1]->IsString()) {
3750     JSObject* receiver = JSObject::cast(args[0]);
3751     String* key = String::cast(args[1]);
3752     if (receiver->HasFastProperties()) {
3753       // Attempt to use lookup cache.
3754       Map* receiver_map = receiver->map();
3755       KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache();
3756       int offset = keyed_lookup_cache->Lookup(receiver_map, key);
3757       if (offset != -1) {
3758         Object* value = receiver->FastPropertyAt(offset);
3759         return value->IsTheHole() ? isolate->heap()->undefined_value() : value;
3760       }
3761       // Lookup cache miss.  Perform lookup and update the cache if appropriate.
3762       LookupResult result;
3763       receiver->LocalLookup(key, &result);
3764       if (result.IsProperty() && result.type() == FIELD) {
3765         int offset = result.GetFieldIndex();
3766         keyed_lookup_cache->Update(receiver_map, key, offset);
3767         return receiver->FastPropertyAt(offset);
3768       }
3769     } else {
3770       // Attempt dictionary lookup.
3771       StringDictionary* dictionary = receiver->property_dictionary();
3772       int entry = dictionary->FindEntry(key);
3773       if ((entry != StringDictionary::kNotFound) &&
3774           (dictionary->DetailsAt(entry).type() == NORMAL)) {
3775         Object* value = dictionary->ValueAt(entry);
3776         if (!receiver->IsGlobalObject()) return value;
3777         value = JSGlobalPropertyCell::cast(value)->value();
3778         if (!value->IsTheHole()) return value;
3779         // If value is the hole do the general lookup.
3780       }
3781     }
3782   } else if (args[0]->IsString() && args[1]->IsSmi()) {
3783     // Fast case for string indexing using [] with a smi index.
3784     HandleScope scope(isolate);
3785     Handle<String> str = args.at<String>(0);
3786     int index = Smi::cast(args[1])->value();
3787     if (index >= 0 && index < str->length()) {
3788       Handle<Object> result = GetCharAt(str, index);
3789       return *result;
3790     }
3791   }
3792 
3793   // Fall back to GetObjectProperty.
3794   return Runtime::GetObjectProperty(isolate,
3795                                     args.at<Object>(0),
3796                                     args.at<Object>(1));
3797 }
3798 
3799 // Implements part of 8.12.9 DefineOwnProperty.
3800 // There are 3 cases that lead here:
3801 // Step 4b - define a new accessor property.
3802 // Steps 9c & 12 - replace an existing data property with an accessor property.
3803 // Step 12 - update an existing accessor property with an accessor or generic
3804 //           descriptor.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DefineOrRedefineAccessorProperty)3805 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) {
3806   ASSERT(args.length() == 5);
3807   HandleScope scope(isolate);
3808   CONVERT_ARG_CHECKED(JSObject, obj, 0);
3809   CONVERT_CHECKED(String, name, args[1]);
3810   CONVERT_CHECKED(Smi, flag_setter, args[2]);
3811   Object* fun = args[3];
3812   RUNTIME_ASSERT(fun->IsJSFunction() || fun->IsUndefined());
3813   CONVERT_CHECKED(Smi, flag_attr, args[4]);
3814   int unchecked = flag_attr->value();
3815   RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
3816   RUNTIME_ASSERT(!obj->IsNull());
3817   LookupResult result;
3818   obj->LocalLookupRealNamedProperty(name, &result);
3819 
3820   PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
3821   // If an existing property is either FIELD, NORMAL or CONSTANT_FUNCTION
3822   // delete it to avoid running into trouble in DefineAccessor, which
3823   // handles this incorrectly if the property is readonly (does nothing)
3824   if (result.IsProperty() &&
3825       (result.type() == FIELD || result.type() == NORMAL
3826        || result.type() == CONSTANT_FUNCTION)) {
3827     Object* ok;
3828     { MaybeObject* maybe_ok =
3829           obj->DeleteProperty(name, JSObject::NORMAL_DELETION);
3830       if (!maybe_ok->ToObject(&ok)) return maybe_ok;
3831     }
3832   }
3833   return obj->DefineAccessor(name, flag_setter->value() == 0, fun, attr);
3834 }
3835 
3836 // Implements part of 8.12.9 DefineOwnProperty.
3837 // There are 3 cases that lead here:
3838 // Step 4a - define a new data property.
3839 // Steps 9b & 12 - replace an existing accessor property with a data property.
3840 // Step 12 - update an existing data property with a data or generic
3841 //           descriptor.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DefineOrRedefineDataProperty)3842 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
3843   ASSERT(args.length() == 4);
3844   HandleScope scope(isolate);
3845   CONVERT_ARG_CHECKED(JSObject, js_object, 0);
3846   CONVERT_ARG_CHECKED(String, name, 1);
3847   Handle<Object> obj_value = args.at<Object>(2);
3848 
3849   CONVERT_CHECKED(Smi, flag, args[3]);
3850   int unchecked = flag->value();
3851   RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
3852 
3853   PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
3854 
3855   // Check if this is an element.
3856   uint32_t index;
3857   bool is_element = name->AsArrayIndex(&index);
3858 
3859   // Special case for elements if any of the flags are true.
3860   // If elements are in fast case we always implicitly assume that:
3861   // DONT_DELETE: false, DONT_ENUM: false, READ_ONLY: false.
3862   if (((unchecked & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) &&
3863       is_element) {
3864     // Normalize the elements to enable attributes on the property.
3865     if (js_object->IsJSGlobalProxy()) {
3866       // We do not need to do access checks here since these has already
3867       // been performed by the call to GetOwnProperty.
3868       Handle<Object> proto(js_object->GetPrototype());
3869       // If proxy is detached, ignore the assignment. Alternatively,
3870       // we could throw an exception.
3871       if (proto->IsNull()) return *obj_value;
3872       js_object = Handle<JSObject>::cast(proto);
3873     }
3874     NormalizeElements(js_object);
3875     Handle<NumberDictionary> dictionary(js_object->element_dictionary());
3876     // Make sure that we never go back to fast case.
3877     dictionary->set_requires_slow_elements();
3878     PropertyDetails details = PropertyDetails(attr, NORMAL);
3879     NumberDictionarySet(dictionary, index, obj_value, details);
3880     return *obj_value;
3881   }
3882 
3883   LookupResult result;
3884   js_object->LookupRealNamedProperty(*name, &result);
3885 
3886   // To be compatible with safari we do not change the value on API objects
3887   // in defineProperty. Firefox disagrees here, and actually changes the value.
3888   if (result.IsProperty() &&
3889       (result.type() == CALLBACKS) &&
3890       result.GetCallbackObject()->IsAccessorInfo()) {
3891     return isolate->heap()->undefined_value();
3892   }
3893 
3894   // Take special care when attributes are different and there is already
3895   // a property. For simplicity we normalize the property which enables us
3896   // to not worry about changing the instance_descriptor and creating a new
3897   // map. The current version of SetObjectProperty does not handle attributes
3898   // correctly in the case where a property is a field and is reset with
3899   // new attributes.
3900   if (result.IsProperty() &&
3901       (attr != result.GetAttributes() || result.type() == CALLBACKS)) {
3902     // New attributes - normalize to avoid writing to instance descriptor
3903     if (js_object->IsJSGlobalProxy()) {
3904       // Since the result is a property, the prototype will exist so
3905       // we don't have to check for null.
3906       js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype()));
3907     }
3908     NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
3909     // Use IgnoreAttributes version since a readonly property may be
3910     // overridden and SetProperty does not allow this.
3911     return js_object->SetLocalPropertyIgnoreAttributes(*name,
3912                                                        *obj_value,
3913                                                        attr);
3914   }
3915 
3916   return Runtime::ForceSetObjectProperty(isolate,
3917                                          js_object,
3918                                          name,
3919                                          obj_value,
3920                                          attr);
3921 }
3922 
3923 
SetObjectProperty(Isolate * isolate,Handle<Object> object,Handle<Object> key,Handle<Object> value,PropertyAttributes attr,StrictModeFlag strict_mode)3924 MaybeObject* Runtime::SetObjectProperty(Isolate* isolate,
3925                                         Handle<Object> object,
3926                                         Handle<Object> key,
3927                                         Handle<Object> value,
3928                                         PropertyAttributes attr,
3929                                         StrictModeFlag strict_mode) {
3930   HandleScope scope(isolate);
3931 
3932   if (object->IsUndefined() || object->IsNull()) {
3933     Handle<Object> args[2] = { key, object };
3934     Handle<Object> error =
3935         isolate->factory()->NewTypeError("non_object_property_store",
3936                                          HandleVector(args, 2));
3937     return isolate->Throw(*error);
3938   }
3939 
3940   // If the object isn't a JavaScript object, we ignore the store.
3941   if (!object->IsJSObject()) return *value;
3942 
3943   Handle<JSObject> js_object = Handle<JSObject>::cast(object);
3944 
3945   // Check if the given key is an array index.
3946   uint32_t index;
3947   if (key->ToArrayIndex(&index)) {
3948     // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
3949     // of a string using [] notation.  We need to support this too in
3950     // JavaScript.
3951     // In the case of a String object we just need to redirect the assignment to
3952     // the underlying string if the index is in range.  Since the underlying
3953     // string does nothing with the assignment then we can ignore such
3954     // assignments.
3955     if (js_object->IsStringObjectWithCharacterAt(index)) {
3956       return *value;
3957     }
3958 
3959     Handle<Object> result = SetElement(js_object, index, value, strict_mode);
3960     if (result.is_null()) return Failure::Exception();
3961     return *value;
3962   }
3963 
3964   if (key->IsString()) {
3965     Handle<Object> result;
3966     if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
3967       result = SetElement(js_object, index, value, strict_mode);
3968     } else {
3969       Handle<String> key_string = Handle<String>::cast(key);
3970       key_string->TryFlatten();
3971       result = SetProperty(js_object, key_string, value, attr, strict_mode);
3972     }
3973     if (result.is_null()) return Failure::Exception();
3974     return *value;
3975   }
3976 
3977   // Call-back into JavaScript to convert the key to a string.
3978   bool has_pending_exception = false;
3979   Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
3980   if (has_pending_exception) return Failure::Exception();
3981   Handle<String> name = Handle<String>::cast(converted);
3982 
3983   if (name->AsArrayIndex(&index)) {
3984     return js_object->SetElement(index, *value, strict_mode);
3985   } else {
3986     return js_object->SetProperty(*name, *value, attr, strict_mode);
3987   }
3988 }
3989 
3990 
ForceSetObjectProperty(Isolate * isolate,Handle<JSObject> js_object,Handle<Object> key,Handle<Object> value,PropertyAttributes attr)3991 MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate,
3992                                              Handle<JSObject> js_object,
3993                                              Handle<Object> key,
3994                                              Handle<Object> value,
3995                                              PropertyAttributes attr) {
3996   HandleScope scope(isolate);
3997 
3998   // Check if the given key is an array index.
3999   uint32_t index;
4000   if (key->ToArrayIndex(&index)) {
4001     // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
4002     // of a string using [] notation.  We need to support this too in
4003     // JavaScript.
4004     // In the case of a String object we just need to redirect the assignment to
4005     // the underlying string if the index is in range.  Since the underlying
4006     // string does nothing with the assignment then we can ignore such
4007     // assignments.
4008     if (js_object->IsStringObjectWithCharacterAt(index)) {
4009       return *value;
4010     }
4011 
4012     return js_object->SetElement(index, *value, kNonStrictMode);
4013   }
4014 
4015   if (key->IsString()) {
4016     if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
4017       return js_object->SetElement(index, *value, kNonStrictMode);
4018     } else {
4019       Handle<String> key_string = Handle<String>::cast(key);
4020       key_string->TryFlatten();
4021       return js_object->SetLocalPropertyIgnoreAttributes(*key_string,
4022                                                          *value,
4023                                                          attr);
4024     }
4025   }
4026 
4027   // Call-back into JavaScript to convert the key to a string.
4028   bool has_pending_exception = false;
4029   Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
4030   if (has_pending_exception) return Failure::Exception();
4031   Handle<String> name = Handle<String>::cast(converted);
4032 
4033   if (name->AsArrayIndex(&index)) {
4034     return js_object->SetElement(index, *value, kNonStrictMode);
4035   } else {
4036     return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr);
4037   }
4038 }
4039 
4040 
ForceDeleteObjectProperty(Isolate * isolate,Handle<JSObject> js_object,Handle<Object> key)4041 MaybeObject* Runtime::ForceDeleteObjectProperty(Isolate* isolate,
4042                                                 Handle<JSObject> js_object,
4043                                                 Handle<Object> key) {
4044   HandleScope scope(isolate);
4045 
4046   // Check if the given key is an array index.
4047   uint32_t index;
4048   if (key->ToArrayIndex(&index)) {
4049     // In Firefox/SpiderMonkey, Safari and Opera you can access the
4050     // characters of a string using [] notation.  In the case of a
4051     // String object we just need to redirect the deletion to the
4052     // underlying string if the index is in range.  Since the
4053     // underlying string does nothing with the deletion, we can ignore
4054     // such deletions.
4055     if (js_object->IsStringObjectWithCharacterAt(index)) {
4056       return isolate->heap()->true_value();
4057     }
4058 
4059     return js_object->DeleteElement(index, JSObject::FORCE_DELETION);
4060   }
4061 
4062   Handle<String> key_string;
4063   if (key->IsString()) {
4064     key_string = Handle<String>::cast(key);
4065   } else {
4066     // Call-back into JavaScript to convert the key to a string.
4067     bool has_pending_exception = false;
4068     Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
4069     if (has_pending_exception) return Failure::Exception();
4070     key_string = Handle<String>::cast(converted);
4071   }
4072 
4073   key_string->TryFlatten();
4074   return js_object->DeleteProperty(*key_string, JSObject::FORCE_DELETION);
4075 }
4076 
4077 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetProperty)4078 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) {
4079   NoHandleAllocation ha;
4080   RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
4081 
4082   Handle<Object> object = args.at<Object>(0);
4083   Handle<Object> key = args.at<Object>(1);
4084   Handle<Object> value = args.at<Object>(2);
4085   CONVERT_SMI_CHECKED(unchecked_attributes, args[3]);
4086   RUNTIME_ASSERT(
4087       (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4088   // Compute attributes.
4089   PropertyAttributes attributes =
4090       static_cast<PropertyAttributes>(unchecked_attributes);
4091 
4092   StrictModeFlag strict_mode = kNonStrictMode;
4093   if (args.length() == 5) {
4094     CONVERT_SMI_CHECKED(strict_unchecked, args[4]);
4095     RUNTIME_ASSERT(strict_unchecked == kStrictMode ||
4096                    strict_unchecked == kNonStrictMode);
4097     strict_mode = static_cast<StrictModeFlag>(strict_unchecked);
4098   }
4099 
4100   return Runtime::SetObjectProperty(isolate,
4101                                     object,
4102                                     key,
4103                                     value,
4104                                     attributes,
4105                                     strict_mode);
4106 }
4107 
4108 
4109 // Set a local property, even if it is READ_ONLY.  If the property does not
4110 // exist, it will be added with attributes NONE.
RUNTIME_FUNCTION(MaybeObject *,Runtime_IgnoreAttributesAndSetProperty)4111 RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) {
4112   NoHandleAllocation ha;
4113   RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
4114   CONVERT_CHECKED(JSObject, object, args[0]);
4115   CONVERT_CHECKED(String, name, args[1]);
4116   // Compute attributes.
4117   PropertyAttributes attributes = NONE;
4118   if (args.length() == 4) {
4119     CONVERT_CHECKED(Smi, value_obj, args[3]);
4120     int unchecked_value = value_obj->value();
4121     // Only attribute bits should be set.
4122     RUNTIME_ASSERT(
4123         (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4124     attributes = static_cast<PropertyAttributes>(unchecked_value);
4125   }
4126 
4127   return object->
4128       SetLocalPropertyIgnoreAttributes(name, args[2], attributes);
4129 }
4130 
4131 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DeleteProperty)4132 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteProperty) {
4133   NoHandleAllocation ha;
4134   ASSERT(args.length() == 3);
4135 
4136   CONVERT_CHECKED(JSObject, object, args[0]);
4137   CONVERT_CHECKED(String, key, args[1]);
4138   CONVERT_SMI_CHECKED(strict, args[2]);
4139   return object->DeleteProperty(key, (strict == kStrictMode)
4140                                       ? JSObject::STRICT_DELETION
4141                                       : JSObject::NORMAL_DELETION);
4142 }
4143 
4144 
HasLocalPropertyImplementation(Isolate * isolate,Handle<JSObject> object,Handle<String> key)4145 static Object* HasLocalPropertyImplementation(Isolate* isolate,
4146                                               Handle<JSObject> object,
4147                                               Handle<String> key) {
4148   if (object->HasLocalProperty(*key)) return isolate->heap()->true_value();
4149   // Handle hidden prototypes.  If there's a hidden prototype above this thing
4150   // then we have to check it for properties, because they are supposed to
4151   // look like they are on this object.
4152   Handle<Object> proto(object->GetPrototype());
4153   if (proto->IsJSObject() &&
4154       Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) {
4155     return HasLocalPropertyImplementation(isolate,
4156                                           Handle<JSObject>::cast(proto),
4157                                           key);
4158   }
4159   return isolate->heap()->false_value();
4160 }
4161 
4162 
RUNTIME_FUNCTION(MaybeObject *,Runtime_HasLocalProperty)4163 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) {
4164   NoHandleAllocation ha;
4165   ASSERT(args.length() == 2);
4166   CONVERT_CHECKED(String, key, args[1]);
4167 
4168   Object* obj = args[0];
4169   // Only JS objects can have properties.
4170   if (obj->IsJSObject()) {
4171     JSObject* object = JSObject::cast(obj);
4172     // Fast case - no interceptors.
4173     if (object->HasRealNamedProperty(key)) return isolate->heap()->true_value();
4174     // Slow case.  Either it's not there or we have an interceptor.  We should
4175     // have handles for this kind of deal.
4176     HandleScope scope(isolate);
4177     return HasLocalPropertyImplementation(isolate,
4178                                           Handle<JSObject>(object),
4179                                           Handle<String>(key));
4180   } else if (obj->IsString()) {
4181     // Well, there is one exception:  Handle [] on strings.
4182     uint32_t index;
4183     if (key->AsArrayIndex(&index)) {
4184       String* string = String::cast(obj);
4185       if (index < static_cast<uint32_t>(string->length()))
4186         return isolate->heap()->true_value();
4187     }
4188   }
4189   return isolate->heap()->false_value();
4190 }
4191 
4192 
RUNTIME_FUNCTION(MaybeObject *,Runtime_HasProperty)4193 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) {
4194   NoHandleAllocation na;
4195   ASSERT(args.length() == 2);
4196 
4197   // Only JS objects can have properties.
4198   if (args[0]->IsJSObject()) {
4199     JSObject* object = JSObject::cast(args[0]);
4200     CONVERT_CHECKED(String, key, args[1]);
4201     if (object->HasProperty(key)) return isolate->heap()->true_value();
4202   }
4203   return isolate->heap()->false_value();
4204 }
4205 
4206 
RUNTIME_FUNCTION(MaybeObject *,Runtime_HasElement)4207 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasElement) {
4208   NoHandleAllocation na;
4209   ASSERT(args.length() == 2);
4210 
4211   // Only JS objects can have elements.
4212   if (args[0]->IsJSObject()) {
4213     JSObject* object = JSObject::cast(args[0]);
4214     CONVERT_CHECKED(Smi, index_obj, args[1]);
4215     uint32_t index = index_obj->value();
4216     if (object->HasElement(index)) return isolate->heap()->true_value();
4217   }
4218   return isolate->heap()->false_value();
4219 }
4220 
4221 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsPropertyEnumerable)4222 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) {
4223   NoHandleAllocation ha;
4224   ASSERT(args.length() == 2);
4225 
4226   CONVERT_CHECKED(JSObject, object, args[0]);
4227   CONVERT_CHECKED(String, key, args[1]);
4228 
4229   uint32_t index;
4230   if (key->AsArrayIndex(&index)) {
4231     return isolate->heap()->ToBoolean(object->HasElement(index));
4232   }
4233 
4234   PropertyAttributes att = object->GetLocalPropertyAttribute(key);
4235   return isolate->heap()->ToBoolean(att != ABSENT && (att & DONT_ENUM) == 0);
4236 }
4237 
4238 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetPropertyNames)4239 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNames) {
4240   HandleScope scope(isolate);
4241   ASSERT(args.length() == 1);
4242   CONVERT_ARG_CHECKED(JSObject, object, 0);
4243   return *GetKeysFor(object);
4244 }
4245 
4246 
4247 // Returns either a FixedArray as Runtime_GetPropertyNames,
4248 // or, if the given object has an enum cache that contains
4249 // all enumerable properties of the object and its prototypes
4250 // have none, the map of the object. This is used to speed up
4251 // the check for deletions during a for-in.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetPropertyNamesFast)4252 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNamesFast) {
4253   ASSERT(args.length() == 1);
4254 
4255   CONVERT_CHECKED(JSObject, raw_object, args[0]);
4256 
4257   if (raw_object->IsSimpleEnum()) return raw_object->map();
4258 
4259   HandleScope scope(isolate);
4260   Handle<JSObject> object(raw_object);
4261   Handle<FixedArray> content = GetKeysInFixedArrayFor(object,
4262                                                       INCLUDE_PROTOS);
4263 
4264   // Test again, since cache may have been built by preceding call.
4265   if (object->IsSimpleEnum()) return object->map();
4266 
4267   return *content;
4268 }
4269 
4270 
4271 // Find the length of the prototype chain that is to to handled as one. If a
4272 // prototype object is hidden it is to be viewed as part of the the object it
4273 // is prototype for.
LocalPrototypeChainLength(JSObject * obj)4274 static int LocalPrototypeChainLength(JSObject* obj) {
4275   int count = 1;
4276   Object* proto = obj->GetPrototype();
4277   while (proto->IsJSObject() &&
4278          JSObject::cast(proto)->map()->is_hidden_prototype()) {
4279     count++;
4280     proto = JSObject::cast(proto)->GetPrototype();
4281   }
4282   return count;
4283 }
4284 
4285 
4286 // Return the names of the local named properties.
4287 // args[0]: object
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetLocalPropertyNames)4288 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) {
4289   HandleScope scope(isolate);
4290   ASSERT(args.length() == 1);
4291   if (!args[0]->IsJSObject()) {
4292     return isolate->heap()->undefined_value();
4293   }
4294   CONVERT_ARG_CHECKED(JSObject, obj, 0);
4295 
4296   // Skip the global proxy as it has no properties and always delegates to the
4297   // real global object.
4298   if (obj->IsJSGlobalProxy()) {
4299     // Only collect names if access is permitted.
4300     if (obj->IsAccessCheckNeeded() &&
4301         !isolate->MayNamedAccess(*obj,
4302                                  isolate->heap()->undefined_value(),
4303                                  v8::ACCESS_KEYS)) {
4304       isolate->ReportFailedAccessCheck(*obj, v8::ACCESS_KEYS);
4305       return *isolate->factory()->NewJSArray(0);
4306     }
4307     obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
4308   }
4309 
4310   // Find the number of objects making up this.
4311   int length = LocalPrototypeChainLength(*obj);
4312 
4313   // Find the number of local properties for each of the objects.
4314   ScopedVector<int> local_property_count(length);
4315   int total_property_count = 0;
4316   Handle<JSObject> jsproto = obj;
4317   for (int i = 0; i < length; i++) {
4318     // Only collect names if access is permitted.
4319     if (jsproto->IsAccessCheckNeeded() &&
4320         !isolate->MayNamedAccess(*jsproto,
4321                                  isolate->heap()->undefined_value(),
4322                                  v8::ACCESS_KEYS)) {
4323       isolate->ReportFailedAccessCheck(*jsproto, v8::ACCESS_KEYS);
4324       return *isolate->factory()->NewJSArray(0);
4325     }
4326     int n;
4327     n = jsproto->NumberOfLocalProperties(static_cast<PropertyAttributes>(NONE));
4328     local_property_count[i] = n;
4329     total_property_count += n;
4330     if (i < length - 1) {
4331       jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
4332     }
4333   }
4334 
4335   // Allocate an array with storage for all the property names.
4336   Handle<FixedArray> names =
4337       isolate->factory()->NewFixedArray(total_property_count);
4338 
4339   // Get the property names.
4340   jsproto = obj;
4341   int proto_with_hidden_properties = 0;
4342   int next_copy_index = 0;
4343   for (int i = 0; i < length; i++) {
4344     jsproto->GetLocalPropertyNames(*names, next_copy_index);
4345     next_copy_index += local_property_count[i];
4346     if (!GetHiddenProperties(jsproto, false)->IsUndefined()) {
4347       proto_with_hidden_properties++;
4348     }
4349     if (i < length - 1) {
4350       jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
4351     }
4352   }
4353 
4354   // Filter out name of hidden propeties object.
4355   if (proto_with_hidden_properties > 0) {
4356     Handle<FixedArray> old_names = names;
4357     names = isolate->factory()->NewFixedArray(
4358         names->length() - proto_with_hidden_properties);
4359     int dest_pos = 0;
4360     for (int i = 0; i < total_property_count; i++) {
4361       Object* name = old_names->get(i);
4362       if (name == isolate->heap()->hidden_symbol()) {
4363         continue;
4364       }
4365       names->set(dest_pos++, name);
4366     }
4367   }
4368 
4369   return *isolate->factory()->NewJSArrayWithElements(names);
4370 }
4371 
4372 
4373 // Return the names of the local indexed properties.
4374 // args[0]: object
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetLocalElementNames)4375 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalElementNames) {
4376   HandleScope scope(isolate);
4377   ASSERT(args.length() == 1);
4378   if (!args[0]->IsJSObject()) {
4379     return isolate->heap()->undefined_value();
4380   }
4381   CONVERT_ARG_CHECKED(JSObject, obj, 0);
4382 
4383   int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
4384   Handle<FixedArray> names = isolate->factory()->NewFixedArray(n);
4385   obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
4386   return *isolate->factory()->NewJSArrayWithElements(names);
4387 }
4388 
4389 
4390 // Return information on whether an object has a named or indexed interceptor.
4391 // args[0]: object
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetInterceptorInfo)4392 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetInterceptorInfo) {
4393   HandleScope scope(isolate);
4394   ASSERT(args.length() == 1);
4395   if (!args[0]->IsJSObject()) {
4396     return Smi::FromInt(0);
4397   }
4398   CONVERT_ARG_CHECKED(JSObject, obj, 0);
4399 
4400   int result = 0;
4401   if (obj->HasNamedInterceptor()) result |= 2;
4402   if (obj->HasIndexedInterceptor()) result |= 1;
4403 
4404   return Smi::FromInt(result);
4405 }
4406 
4407 
4408 // Return property names from named interceptor.
4409 // args[0]: object
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetNamedInterceptorPropertyNames)4410 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetNamedInterceptorPropertyNames) {
4411   HandleScope scope(isolate);
4412   ASSERT(args.length() == 1);
4413   CONVERT_ARG_CHECKED(JSObject, obj, 0);
4414 
4415   if (obj->HasNamedInterceptor()) {
4416     v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
4417     if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
4418   }
4419   return isolate->heap()->undefined_value();
4420 }
4421 
4422 
4423 // Return element names from indexed interceptor.
4424 // args[0]: object
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetIndexedInterceptorElementNames)4425 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetIndexedInterceptorElementNames) {
4426   HandleScope scope(isolate);
4427   ASSERT(args.length() == 1);
4428   CONVERT_ARG_CHECKED(JSObject, obj, 0);
4429 
4430   if (obj->HasIndexedInterceptor()) {
4431     v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
4432     if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
4433   }
4434   return isolate->heap()->undefined_value();
4435 }
4436 
4437 
RUNTIME_FUNCTION(MaybeObject *,Runtime_LocalKeys)4438 RUNTIME_FUNCTION(MaybeObject*, Runtime_LocalKeys) {
4439   ASSERT_EQ(args.length(), 1);
4440   CONVERT_CHECKED(JSObject, raw_object, args[0]);
4441   HandleScope scope(isolate);
4442   Handle<JSObject> object(raw_object);
4443 
4444   if (object->IsJSGlobalProxy()) {
4445     // Do access checks before going to the global object.
4446     if (object->IsAccessCheckNeeded() &&
4447         !isolate->MayNamedAccess(*object, isolate->heap()->undefined_value(),
4448                              v8::ACCESS_KEYS)) {
4449       isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
4450       return *isolate->factory()->NewJSArray(0);
4451     }
4452 
4453     Handle<Object> proto(object->GetPrototype());
4454     // If proxy is detached we simply return an empty array.
4455     if (proto->IsNull()) return *isolate->factory()->NewJSArray(0);
4456     object = Handle<JSObject>::cast(proto);
4457   }
4458 
4459   Handle<FixedArray> contents = GetKeysInFixedArrayFor(object,
4460                                                        LOCAL_ONLY);
4461   // Some fast paths through GetKeysInFixedArrayFor reuse a cached
4462   // property array and since the result is mutable we have to create
4463   // a fresh clone on each invocation.
4464   int length = contents->length();
4465   Handle<FixedArray> copy = isolate->factory()->NewFixedArray(length);
4466   for (int i = 0; i < length; i++) {
4467     Object* entry = contents->get(i);
4468     if (entry->IsString()) {
4469       copy->set(i, entry);
4470     } else {
4471       ASSERT(entry->IsNumber());
4472       HandleScope scope(isolate);
4473       Handle<Object> entry_handle(entry, isolate);
4474       Handle<Object> entry_str =
4475           isolate->factory()->NumberToString(entry_handle);
4476       copy->set(i, *entry_str);
4477     }
4478   }
4479   return *isolate->factory()->NewJSArrayWithElements(copy);
4480 }
4481 
4482 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetArgumentsProperty)4483 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
4484   NoHandleAllocation ha;
4485   ASSERT(args.length() == 1);
4486 
4487   // Compute the frame holding the arguments.
4488   JavaScriptFrameIterator it(isolate);
4489   it.AdvanceToArgumentsFrame();
4490   JavaScriptFrame* frame = it.frame();
4491 
4492   // Get the actual number of provided arguments.
4493   const uint32_t n = frame->ComputeParametersCount();
4494 
4495   // Try to convert the key to an index. If successful and within
4496   // index return the the argument from the frame.
4497   uint32_t index;
4498   if (args[0]->ToArrayIndex(&index) && index < n) {
4499     return frame->GetParameter(index);
4500   }
4501 
4502   // Convert the key to a string.
4503   HandleScope scope(isolate);
4504   bool exception = false;
4505   Handle<Object> converted =
4506       Execution::ToString(args.at<Object>(0), &exception);
4507   if (exception) return Failure::Exception();
4508   Handle<String> key = Handle<String>::cast(converted);
4509 
4510   // Try to convert the string key into an array index.
4511   if (key->AsArrayIndex(&index)) {
4512     if (index < n) {
4513       return frame->GetParameter(index);
4514     } else {
4515       return isolate->initial_object_prototype()->GetElement(index);
4516     }
4517   }
4518 
4519   // Handle special arguments properties.
4520   if (key->Equals(isolate->heap()->length_symbol())) return Smi::FromInt(n);
4521   if (key->Equals(isolate->heap()->callee_symbol())) {
4522     Object* function = frame->function();
4523     if (function->IsJSFunction() &&
4524         JSFunction::cast(function)->shared()->strict_mode()) {
4525       return isolate->Throw(*isolate->factory()->NewTypeError(
4526           "strict_arguments_callee", HandleVector<Object>(NULL, 0)));
4527     }
4528     return function;
4529   }
4530 
4531   // Lookup in the initial Object.prototype object.
4532   return isolate->initial_object_prototype()->GetProperty(*key);
4533 }
4534 
4535 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ToFastProperties)4536 RUNTIME_FUNCTION(MaybeObject*, Runtime_ToFastProperties) {
4537   HandleScope scope(isolate);
4538 
4539   ASSERT(args.length() == 1);
4540   Handle<Object> object = args.at<Object>(0);
4541   if (object->IsJSObject()) {
4542     Handle<JSObject> js_object = Handle<JSObject>::cast(object);
4543     if (!js_object->HasFastProperties() && !js_object->IsGlobalObject()) {
4544       MaybeObject* ok = js_object->TransformToFastProperties(0);
4545       if (ok->IsRetryAfterGC()) return ok;
4546     }
4547   }
4548   return *object;
4549 }
4550 
4551 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ToSlowProperties)4552 RUNTIME_FUNCTION(MaybeObject*, Runtime_ToSlowProperties) {
4553   HandleScope scope(isolate);
4554 
4555   ASSERT(args.length() == 1);
4556   Handle<Object> object = args.at<Object>(0);
4557   if (object->IsJSObject() && !object->IsJSGlobalProxy()) {
4558     Handle<JSObject> js_object = Handle<JSObject>::cast(object);
4559     NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
4560   }
4561   return *object;
4562 }
4563 
4564 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ToBool)4565 RUNTIME_FUNCTION(MaybeObject*, Runtime_ToBool) {
4566   NoHandleAllocation ha;
4567   ASSERT(args.length() == 1);
4568 
4569   return args[0]->ToBoolean();
4570 }
4571 
4572 
4573 // Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
4574 // Possible optimizations: put the type string into the oddballs.
RUNTIME_FUNCTION(MaybeObject *,Runtime_Typeof)4575 RUNTIME_FUNCTION(MaybeObject*, Runtime_Typeof) {
4576   NoHandleAllocation ha;
4577 
4578   Object* obj = args[0];
4579   if (obj->IsNumber()) return isolate->heap()->number_symbol();
4580   HeapObject* heap_obj = HeapObject::cast(obj);
4581 
4582   // typeof an undetectable object is 'undefined'
4583   if (heap_obj->map()->is_undetectable()) {
4584     return isolate->heap()->undefined_symbol();
4585   }
4586 
4587   InstanceType instance_type = heap_obj->map()->instance_type();
4588   if (instance_type < FIRST_NONSTRING_TYPE) {
4589     return isolate->heap()->string_symbol();
4590   }
4591 
4592   switch (instance_type) {
4593     case ODDBALL_TYPE:
4594       if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
4595         return isolate->heap()->boolean_symbol();
4596       }
4597       if (heap_obj->IsNull()) {
4598         return isolate->heap()->object_symbol();
4599       }
4600       ASSERT(heap_obj->IsUndefined());
4601       return isolate->heap()->undefined_symbol();
4602     case JS_FUNCTION_TYPE: case JS_REGEXP_TYPE:
4603       return isolate->heap()->function_symbol();
4604     default:
4605       // For any kind of object not handled above, the spec rule for
4606       // host objects gives that it is okay to return "object"
4607       return isolate->heap()->object_symbol();
4608   }
4609 }
4610 
4611 
AreDigits(const char * s,int from,int to)4612 static bool AreDigits(const char*s, int from, int to) {
4613   for (int i = from; i < to; i++) {
4614     if (s[i] < '0' || s[i] > '9') return false;
4615   }
4616 
4617   return true;
4618 }
4619 
4620 
ParseDecimalInteger(const char * s,int from,int to)4621 static int ParseDecimalInteger(const char*s, int from, int to) {
4622   ASSERT(to - from < 10);  // Overflow is not possible.
4623   ASSERT(from < to);
4624   int d = s[from] - '0';
4625 
4626   for (int i = from + 1; i < to; i++) {
4627     d = 10 * d + (s[i] - '0');
4628   }
4629 
4630   return d;
4631 }
4632 
4633 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringToNumber)4634 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
4635   NoHandleAllocation ha;
4636   ASSERT(args.length() == 1);
4637   CONVERT_CHECKED(String, subject, args[0]);
4638   subject->TryFlatten();
4639 
4640   // Fast case: short integer or some sorts of junk values.
4641   int len = subject->length();
4642   if (subject->IsSeqAsciiString()) {
4643     if (len == 0) return Smi::FromInt(0);
4644 
4645     char const* data = SeqAsciiString::cast(subject)->GetChars();
4646     bool minus = (data[0] == '-');
4647     int start_pos = (minus ? 1 : 0);
4648 
4649     if (start_pos == len) {
4650       return isolate->heap()->nan_value();
4651     } else if (data[start_pos] > '9') {
4652       // Fast check for a junk value. A valid string may start from a
4653       // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit or
4654       // the 'I' character ('Infinity'). All of that have codes not greater than
4655       // '9' except 'I'.
4656       if (data[start_pos] != 'I') {
4657         return isolate->heap()->nan_value();
4658       }
4659     } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
4660       // The maximal/minimal smi has 10 digits. If the string has less digits we
4661       // know it will fit into the smi-data type.
4662       int d = ParseDecimalInteger(data, start_pos, len);
4663       if (minus) {
4664         if (d == 0) return isolate->heap()->minus_zero_value();
4665         d = -d;
4666       } else if (!subject->HasHashCode() &&
4667                  len <= String::kMaxArrayIndexSize &&
4668                  (len == 1 || data[0] != '0')) {
4669         // String hash is not calculated yet but all the data are present.
4670         // Update the hash field to speed up sequential convertions.
4671         uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
4672 #ifdef DEBUG
4673         subject->Hash();  // Force hash calculation.
4674         ASSERT_EQ(static_cast<int>(subject->hash_field()),
4675                   static_cast<int>(hash));
4676 #endif
4677         subject->set_hash_field(hash);
4678       }
4679       return Smi::FromInt(d);
4680     }
4681   }
4682 
4683   // Slower case.
4684   return isolate->heap()->NumberFromDouble(
4685       StringToDouble(isolate->unicode_cache(), subject, ALLOW_HEX));
4686 }
4687 
4688 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringFromCharCodeArray)4689 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringFromCharCodeArray) {
4690   NoHandleAllocation ha;
4691   ASSERT(args.length() == 1);
4692 
4693   CONVERT_CHECKED(JSArray, codes, args[0]);
4694   int length = Smi::cast(codes->length())->value();
4695 
4696   // Check if the string can be ASCII.
4697   int i;
4698   for (i = 0; i < length; i++) {
4699     Object* element;
4700     { MaybeObject* maybe_element = codes->GetElement(i);
4701       // We probably can't get an exception here, but just in order to enforce
4702       // the checking of inputs in the runtime calls we check here.
4703       if (!maybe_element->ToObject(&element)) return maybe_element;
4704     }
4705     CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
4706     if ((chr & 0xffff) > String::kMaxAsciiCharCode)
4707       break;
4708   }
4709 
4710   MaybeObject* maybe_object = NULL;
4711   if (i == length) {  // The string is ASCII.
4712     maybe_object = isolate->heap()->AllocateRawAsciiString(length);
4713   } else {  // The string is not ASCII.
4714     maybe_object = isolate->heap()->AllocateRawTwoByteString(length);
4715   }
4716 
4717   Object* object = NULL;
4718   if (!maybe_object->ToObject(&object)) return maybe_object;
4719   String* result = String::cast(object);
4720   for (int i = 0; i < length; i++) {
4721     Object* element;
4722     { MaybeObject* maybe_element = codes->GetElement(i);
4723       if (!maybe_element->ToObject(&element)) return maybe_element;
4724     }
4725     CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
4726     result->Set(i, chr & 0xffff);
4727   }
4728   return result;
4729 }
4730 
4731 
4732 // kNotEscaped is generated by the following:
4733 //
4734 // #!/bin/perl
4735 // for (my $i = 0; $i < 256; $i++) {
4736 //   print "\n" if $i % 16 == 0;
4737 //   my $c = chr($i);
4738 //   my $escaped = 1;
4739 //   $escaped = 0 if $c =~ m#[A-Za-z0-9@*_+./-]#;
4740 //   print $escaped ? "0, " : "1, ";
4741 // }
4742 
4743 
IsNotEscaped(uint16_t character)4744 static bool IsNotEscaped(uint16_t character) {
4745   // Only for 8 bit characters, the rest are always escaped (in a different way)
4746   ASSERT(character < 256);
4747   static const char kNotEscaped[256] = {
4748     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4749     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4750     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
4751     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
4752     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
4753     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
4754     0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
4755     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
4756     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4757     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4758     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4759     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4760     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4761     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4762     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4763     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4764   };
4765   return kNotEscaped[character] != 0;
4766 }
4767 
4768 
RUNTIME_FUNCTION(MaybeObject *,Runtime_URIEscape)4769 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIEscape) {
4770   const char hex_chars[] = "0123456789ABCDEF";
4771   NoHandleAllocation ha;
4772   ASSERT(args.length() == 1);
4773   CONVERT_CHECKED(String, source, args[0]);
4774 
4775   source->TryFlatten();
4776 
4777   int escaped_length = 0;
4778   int length = source->length();
4779   {
4780     Access<StringInputBuffer> buffer(
4781         isolate->runtime_state()->string_input_buffer());
4782     buffer->Reset(source);
4783     while (buffer->has_more()) {
4784       uint16_t character = buffer->GetNext();
4785       if (character >= 256) {
4786         escaped_length += 6;
4787       } else if (IsNotEscaped(character)) {
4788         escaped_length++;
4789       } else {
4790         escaped_length += 3;
4791       }
4792       // We don't allow strings that are longer than a maximal length.
4793       ASSERT(String::kMaxLength < 0x7fffffff - 6);  // Cannot overflow.
4794       if (escaped_length > String::kMaxLength) {
4795         isolate->context()->mark_out_of_memory();
4796         return Failure::OutOfMemoryException();
4797       }
4798     }
4799   }
4800   // No length change implies no change.  Return original string if no change.
4801   if (escaped_length == length) {
4802     return source;
4803   }
4804   Object* o;
4805   { MaybeObject* maybe_o =
4806         isolate->heap()->AllocateRawAsciiString(escaped_length);
4807     if (!maybe_o->ToObject(&o)) return maybe_o;
4808   }
4809   String* destination = String::cast(o);
4810   int dest_position = 0;
4811 
4812   Access<StringInputBuffer> buffer(
4813       isolate->runtime_state()->string_input_buffer());
4814   buffer->Rewind();
4815   while (buffer->has_more()) {
4816     uint16_t chr = buffer->GetNext();
4817     if (chr >= 256) {
4818       destination->Set(dest_position, '%');
4819       destination->Set(dest_position+1, 'u');
4820       destination->Set(dest_position+2, hex_chars[chr >> 12]);
4821       destination->Set(dest_position+3, hex_chars[(chr >> 8) & 0xf]);
4822       destination->Set(dest_position+4, hex_chars[(chr >> 4) & 0xf]);
4823       destination->Set(dest_position+5, hex_chars[chr & 0xf]);
4824       dest_position += 6;
4825     } else if (IsNotEscaped(chr)) {
4826       destination->Set(dest_position, chr);
4827       dest_position++;
4828     } else {
4829       destination->Set(dest_position, '%');
4830       destination->Set(dest_position+1, hex_chars[chr >> 4]);
4831       destination->Set(dest_position+2, hex_chars[chr & 0xf]);
4832       dest_position += 3;
4833     }
4834   }
4835   return destination;
4836 }
4837 
4838 
TwoDigitHex(uint16_t character1,uint16_t character2)4839 static inline int TwoDigitHex(uint16_t character1, uint16_t character2) {
4840   static const signed char kHexValue['g'] = {
4841     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
4842     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
4843     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
4844     0,  1,  2,   3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
4845     -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
4846     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
4847     -1, 10, 11, 12, 13, 14, 15 };
4848 
4849   if (character1 > 'f') return -1;
4850   int hi = kHexValue[character1];
4851   if (hi == -1) return -1;
4852   if (character2 > 'f') return -1;
4853   int lo = kHexValue[character2];
4854   if (lo == -1) return -1;
4855   return (hi << 4) + lo;
4856 }
4857 
4858 
Unescape(String * source,int i,int length,int * step)4859 static inline int Unescape(String* source,
4860                            int i,
4861                            int length,
4862                            int* step) {
4863   uint16_t character = source->Get(i);
4864   int32_t hi = 0;
4865   int32_t lo = 0;
4866   if (character == '%' &&
4867       i <= length - 6 &&
4868       source->Get(i + 1) == 'u' &&
4869       (hi = TwoDigitHex(source->Get(i + 2),
4870                         source->Get(i + 3))) != -1 &&
4871       (lo = TwoDigitHex(source->Get(i + 4),
4872                         source->Get(i + 5))) != -1) {
4873     *step = 6;
4874     return (hi << 8) + lo;
4875   } else if (character == '%' &&
4876       i <= length - 3 &&
4877       (lo = TwoDigitHex(source->Get(i + 1),
4878                         source->Get(i + 2))) != -1) {
4879     *step = 3;
4880     return lo;
4881   } else {
4882     *step = 1;
4883     return character;
4884   }
4885 }
4886 
4887 
RUNTIME_FUNCTION(MaybeObject *,Runtime_URIUnescape)4888 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) {
4889   NoHandleAllocation ha;
4890   ASSERT(args.length() == 1);
4891   CONVERT_CHECKED(String, source, args[0]);
4892 
4893   source->TryFlatten();
4894 
4895   bool ascii = true;
4896   int length = source->length();
4897 
4898   int unescaped_length = 0;
4899   for (int i = 0; i < length; unescaped_length++) {
4900     int step;
4901     if (Unescape(source, i, length, &step) > String::kMaxAsciiCharCode) {
4902       ascii = false;
4903     }
4904     i += step;
4905   }
4906 
4907   // No length change implies no change.  Return original string if no change.
4908   if (unescaped_length == length)
4909     return source;
4910 
4911   Object* o;
4912   { MaybeObject* maybe_o =
4913         ascii ?
4914         isolate->heap()->AllocateRawAsciiString(unescaped_length) :
4915         isolate->heap()->AllocateRawTwoByteString(unescaped_length);
4916     if (!maybe_o->ToObject(&o)) return maybe_o;
4917   }
4918   String* destination = String::cast(o);
4919 
4920   int dest_position = 0;
4921   for (int i = 0; i < length; dest_position++) {
4922     int step;
4923     destination->Set(dest_position, Unescape(source, i, length, &step));
4924     i += step;
4925   }
4926   return destination;
4927 }
4928 
4929 
4930 static const unsigned int kQuoteTableLength = 128u;
4931 
4932 static const int kJsonQuotesCharactersPerEntry = 8;
4933 static const char* const JsonQuotes =
4934     "\\u0000  \\u0001  \\u0002  \\u0003  "
4935     "\\u0004  \\u0005  \\u0006  \\u0007  "
4936     "\\b      \\t      \\n      \\u000b  "
4937     "\\f      \\r      \\u000e  \\u000f  "
4938     "\\u0010  \\u0011  \\u0012  \\u0013  "
4939     "\\u0014  \\u0015  \\u0016  \\u0017  "
4940     "\\u0018  \\u0019  \\u001a  \\u001b  "
4941     "\\u001c  \\u001d  \\u001e  \\u001f  "
4942     "        !       \\\"      #       "
4943     "$       %       &       '       "
4944     "(       )       *       +       "
4945     ",       -       .       /       "
4946     "0       1       2       3       "
4947     "4       5       6       7       "
4948     "8       9       :       ;       "
4949     "<       =       >       ?       "
4950     "@       A       B       C       "
4951     "D       E       F       G       "
4952     "H       I       J       K       "
4953     "L       M       N       O       "
4954     "P       Q       R       S       "
4955     "T       U       V       W       "
4956     "X       Y       Z       [       "
4957     "\\\\      ]       ^       _       "
4958     "`       a       b       c       "
4959     "d       e       f       g       "
4960     "h       i       j       k       "
4961     "l       m       n       o       "
4962     "p       q       r       s       "
4963     "t       u       v       w       "
4964     "x       y       z       {       "
4965     "|       }       ~       \177       ";
4966 
4967 
4968 // For a string that is less than 32k characters it should always be
4969 // possible to allocate it in new space.
4970 static const int kMaxGuaranteedNewSpaceString = 32 * 1024;
4971 
4972 
4973 // Doing JSON quoting cannot make the string more than this many times larger.
4974 static const int kJsonQuoteWorstCaseBlowup = 6;
4975 
4976 
4977 // Covers the entire ASCII range (all other characters are unchanged by JSON
4978 // quoting).
4979 static const byte JsonQuoteLengths[kQuoteTableLength] = {
4980     6, 6, 6, 6, 6, 6, 6, 6,
4981     2, 2, 2, 6, 2, 2, 6, 6,
4982     6, 6, 6, 6, 6, 6, 6, 6,
4983     6, 6, 6, 6, 6, 6, 6, 6,
4984     1, 1, 2, 1, 1, 1, 1, 1,
4985     1, 1, 1, 1, 1, 1, 1, 1,
4986     1, 1, 1, 1, 1, 1, 1, 1,
4987     1, 1, 1, 1, 1, 1, 1, 1,
4988     1, 1, 1, 1, 1, 1, 1, 1,
4989     1, 1, 1, 1, 1, 1, 1, 1,
4990     1, 1, 1, 1, 1, 1, 1, 1,
4991     1, 1, 1, 1, 2, 1, 1, 1,
4992     1, 1, 1, 1, 1, 1, 1, 1,
4993     1, 1, 1, 1, 1, 1, 1, 1,
4994     1, 1, 1, 1, 1, 1, 1, 1,
4995     1, 1, 1, 1, 1, 1, 1, 1,
4996 };
4997 
4998 
4999 template <typename StringType>
5000 MaybeObject* AllocateRawString(Isolate* isolate, int length);
5001 
5002 
5003 template <>
AllocateRawString(Isolate * isolate,int length)5004 MaybeObject* AllocateRawString<SeqTwoByteString>(Isolate* isolate, int length) {
5005   return isolate->heap()->AllocateRawTwoByteString(length);
5006 }
5007 
5008 
5009 template <>
AllocateRawString(Isolate * isolate,int length)5010 MaybeObject* AllocateRawString<SeqAsciiString>(Isolate* isolate, int length) {
5011   return isolate->heap()->AllocateRawAsciiString(length);
5012 }
5013 
5014 
5015 template <typename Char, typename StringType, bool comma>
SlowQuoteJsonString(Isolate * isolate,Vector<const Char> characters)5016 static MaybeObject* SlowQuoteJsonString(Isolate* isolate,
5017                                         Vector<const Char> characters) {
5018   int length = characters.length();
5019   const Char* read_cursor = characters.start();
5020   const Char* end = read_cursor + length;
5021   const int kSpaceForQuotes = 2 + (comma ? 1 :0);
5022   int quoted_length = kSpaceForQuotes;
5023   while (read_cursor < end) {
5024     Char c = *(read_cursor++);
5025     if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) {
5026       quoted_length++;
5027     } else {
5028       quoted_length += JsonQuoteLengths[static_cast<unsigned>(c)];
5029     }
5030   }
5031   MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
5032                                                          quoted_length);
5033   Object* new_object;
5034   if (!new_alloc->ToObject(&new_object)) {
5035     return new_alloc;
5036   }
5037   StringType* new_string = StringType::cast(new_object);
5038 
5039   Char* write_cursor = reinterpret_cast<Char*>(
5040       new_string->address() + SeqAsciiString::kHeaderSize);
5041   if (comma) *(write_cursor++) = ',';
5042   *(write_cursor++) = '"';
5043 
5044   read_cursor = characters.start();
5045   while (read_cursor < end) {
5046     Char c = *(read_cursor++);
5047     if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) {
5048       *(write_cursor++) = c;
5049     } else {
5050       int len = JsonQuoteLengths[static_cast<unsigned>(c)];
5051       const char* replacement = JsonQuotes +
5052           static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry;
5053       for (int i = 0; i < len; i++) {
5054         *write_cursor++ = *replacement++;
5055       }
5056     }
5057   }
5058   *(write_cursor++) = '"';
5059   return new_string;
5060 }
5061 
5062 
5063 template <typename Char, typename StringType, bool comma>
QuoteJsonString(Isolate * isolate,Vector<const Char> characters)5064 static MaybeObject* QuoteJsonString(Isolate* isolate,
5065                                     Vector<const Char> characters) {
5066   int length = characters.length();
5067   isolate->counters()->quote_json_char_count()->Increment(length);
5068   const int kSpaceForQuotes = 2 + (comma ? 1 :0);
5069   int worst_case_length = length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes;
5070   if (worst_case_length > kMaxGuaranteedNewSpaceString) {
5071     return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters);
5072   }
5073 
5074   MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
5075                                                          worst_case_length);
5076   Object* new_object;
5077   if (!new_alloc->ToObject(&new_object)) {
5078     return new_alloc;
5079   }
5080   if (!isolate->heap()->new_space()->Contains(new_object)) {
5081     // Even if our string is small enough to fit in new space we still have to
5082     // handle it being allocated in old space as may happen in the third
5083     // attempt.  See CALL_AND_RETRY in heap-inl.h and similar code in
5084     // CEntryStub::GenerateCore.
5085     return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters);
5086   }
5087   StringType* new_string = StringType::cast(new_object);
5088   ASSERT(isolate->heap()->new_space()->Contains(new_string));
5089 
5090   STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize);
5091   Char* write_cursor = reinterpret_cast<Char*>(
5092       new_string->address() + SeqAsciiString::kHeaderSize);
5093   if (comma) *(write_cursor++) = ',';
5094   *(write_cursor++) = '"';
5095 
5096   const Char* read_cursor = characters.start();
5097   const Char* end = read_cursor + length;
5098   while (read_cursor < end) {
5099     Char c = *(read_cursor++);
5100     if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) {
5101       *(write_cursor++) = c;
5102     } else {
5103       int len = JsonQuoteLengths[static_cast<unsigned>(c)];
5104       const char* replacement = JsonQuotes +
5105           static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry;
5106       write_cursor[0] = replacement[0];
5107       if (len > 1) {
5108         write_cursor[1] = replacement[1];
5109         if (len > 2) {
5110           ASSERT(len == 6);
5111           write_cursor[2] = replacement[2];
5112           write_cursor[3] = replacement[3];
5113           write_cursor[4] = replacement[4];
5114           write_cursor[5] = replacement[5];
5115         }
5116       }
5117       write_cursor += len;
5118     }
5119   }
5120   *(write_cursor++) = '"';
5121 
5122   int final_length = static_cast<int>(
5123       write_cursor - reinterpret_cast<Char*>(
5124           new_string->address() + SeqAsciiString::kHeaderSize));
5125   isolate->heap()->new_space()->
5126       template ShrinkStringAtAllocationBoundary<StringType>(
5127           new_string, final_length);
5128   return new_string;
5129 }
5130 
5131 
RUNTIME_FUNCTION(MaybeObject *,Runtime_QuoteJSONString)5132 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONString) {
5133   NoHandleAllocation ha;
5134   CONVERT_CHECKED(String, str, args[0]);
5135   if (!str->IsFlat()) {
5136     MaybeObject* try_flatten = str->TryFlatten();
5137     Object* flat;
5138     if (!try_flatten->ToObject(&flat)) {
5139       return try_flatten;
5140     }
5141     str = String::cast(flat);
5142     ASSERT(str->IsFlat());
5143   }
5144   if (str->IsTwoByteRepresentation()) {
5145     return QuoteJsonString<uc16, SeqTwoByteString, false>(isolate,
5146                                                           str->ToUC16Vector());
5147   } else {
5148     return QuoteJsonString<char, SeqAsciiString, false>(isolate,
5149                                                         str->ToAsciiVector());
5150   }
5151 }
5152 
5153 
RUNTIME_FUNCTION(MaybeObject *,Runtime_QuoteJSONStringComma)5154 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringComma) {
5155   NoHandleAllocation ha;
5156   CONVERT_CHECKED(String, str, args[0]);
5157   if (!str->IsFlat()) {
5158     MaybeObject* try_flatten = str->TryFlatten();
5159     Object* flat;
5160     if (!try_flatten->ToObject(&flat)) {
5161       return try_flatten;
5162     }
5163     str = String::cast(flat);
5164     ASSERT(str->IsFlat());
5165   }
5166   if (str->IsTwoByteRepresentation()) {
5167     return QuoteJsonString<uc16, SeqTwoByteString, true>(isolate,
5168                                                          str->ToUC16Vector());
5169   } else {
5170     return QuoteJsonString<char, SeqAsciiString, true>(isolate,
5171                                                        str->ToAsciiVector());
5172   }
5173 }
5174 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringParseInt)5175 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) {
5176   NoHandleAllocation ha;
5177 
5178   CONVERT_CHECKED(String, s, args[0]);
5179   CONVERT_SMI_CHECKED(radix, args[1]);
5180 
5181   s->TryFlatten();
5182 
5183   RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
5184   double value = StringToInt(isolate->unicode_cache(), s, radix);
5185   return isolate->heap()->NumberFromDouble(value);
5186 }
5187 
5188 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringParseFloat)5189 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) {
5190   NoHandleAllocation ha;
5191   CONVERT_CHECKED(String, str, args[0]);
5192 
5193   // ECMA-262 section 15.1.2.3, empty string is NaN
5194   double value = StringToDouble(isolate->unicode_cache(),
5195                                 str, ALLOW_TRAILING_JUNK, OS::nan_value());
5196 
5197   // Create a number object from the value.
5198   return isolate->heap()->NumberFromDouble(value);
5199 }
5200 
5201 
5202 template <class Converter>
ConvertCaseHelper(Isolate * isolate,String * s,int length,int input_string_length,unibrow::Mapping<Converter,128> * mapping)5203 MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
5204     Isolate* isolate,
5205     String* s,
5206     int length,
5207     int input_string_length,
5208     unibrow::Mapping<Converter, 128>* mapping) {
5209   // We try this twice, once with the assumption that the result is no longer
5210   // than the input and, if that assumption breaks, again with the exact
5211   // length.  This may not be pretty, but it is nicer than what was here before
5212   // and I hereby claim my vaffel-is.
5213   //
5214   // Allocate the resulting string.
5215   //
5216   // NOTE: This assumes that the upper/lower case of an ascii
5217   // character is also ascii.  This is currently the case, but it
5218   // might break in the future if we implement more context and locale
5219   // dependent upper/lower conversions.
5220   Object* o;
5221   { MaybeObject* maybe_o = s->IsAsciiRepresentation()
5222         ? isolate->heap()->AllocateRawAsciiString(length)
5223         : isolate->heap()->AllocateRawTwoByteString(length);
5224     if (!maybe_o->ToObject(&o)) return maybe_o;
5225   }
5226   String* result = String::cast(o);
5227   bool has_changed_character = false;
5228 
5229   // Convert all characters to upper case, assuming that they will fit
5230   // in the buffer
5231   Access<StringInputBuffer> buffer(
5232       isolate->runtime_state()->string_input_buffer());
5233   buffer->Reset(s);
5234   unibrow::uchar chars[Converter::kMaxWidth];
5235   // We can assume that the string is not empty
5236   uc32 current = buffer->GetNext();
5237   for (int i = 0; i < length;) {
5238     bool has_next = buffer->has_more();
5239     uc32 next = has_next ? buffer->GetNext() : 0;
5240     int char_length = mapping->get(current, next, chars);
5241     if (char_length == 0) {
5242       // The case conversion of this character is the character itself.
5243       result->Set(i, current);
5244       i++;
5245     } else if (char_length == 1) {
5246       // Common case: converting the letter resulted in one character.
5247       ASSERT(static_cast<uc32>(chars[0]) != current);
5248       result->Set(i, chars[0]);
5249       has_changed_character = true;
5250       i++;
5251     } else if (length == input_string_length) {
5252       // We've assumed that the result would be as long as the
5253       // input but here is a character that converts to several
5254       // characters.  No matter, we calculate the exact length
5255       // of the result and try the whole thing again.
5256       //
5257       // Note that this leaves room for optimization.  We could just
5258       // memcpy what we already have to the result string.  Also,
5259       // the result string is the last object allocated we could
5260       // "realloc" it and probably, in the vast majority of cases,
5261       // extend the existing string to be able to hold the full
5262       // result.
5263       int next_length = 0;
5264       if (has_next) {
5265         next_length = mapping->get(next, 0, chars);
5266         if (next_length == 0) next_length = 1;
5267       }
5268       int current_length = i + char_length + next_length;
5269       while (buffer->has_more()) {
5270         current = buffer->GetNext();
5271         // NOTE: we use 0 as the next character here because, while
5272         // the next character may affect what a character converts to,
5273         // it does not in any case affect the length of what it convert
5274         // to.
5275         int char_length = mapping->get(current, 0, chars);
5276         if (char_length == 0) char_length = 1;
5277         current_length += char_length;
5278         if (current_length > Smi::kMaxValue) {
5279           isolate->context()->mark_out_of_memory();
5280           return Failure::OutOfMemoryException();
5281         }
5282       }
5283       // Try again with the real length.
5284       return Smi::FromInt(current_length);
5285     } else {
5286       for (int j = 0; j < char_length; j++) {
5287         result->Set(i, chars[j]);
5288         i++;
5289       }
5290       has_changed_character = true;
5291     }
5292     current = next;
5293   }
5294   if (has_changed_character) {
5295     return result;
5296   } else {
5297     // If we didn't actually change anything in doing the conversion
5298     // we simple return the result and let the converted string
5299     // become garbage; there is no reason to keep two identical strings
5300     // alive.
5301     return s;
5302   }
5303 }
5304 
5305 
5306 namespace {
5307 
5308 static const uintptr_t kOneInEveryByte = kUintptrAllBitsSet / 0xFF;
5309 
5310 
5311 // Given a word and two range boundaries returns a word with high bit
5312 // set in every byte iff the corresponding input byte was strictly in
5313 // the range (m, n). All the other bits in the result are cleared.
5314 // This function is only useful when it can be inlined and the
5315 // boundaries are statically known.
5316 // Requires: all bytes in the input word and the boundaries must be
5317 // ascii (less than 0x7F).
AsciiRangeMask(uintptr_t w,char m,char n)5318 static inline uintptr_t AsciiRangeMask(uintptr_t w, char m, char n) {
5319   // Every byte in an ascii string is less than or equal to 0x7F.
5320   ASSERT((w & (kOneInEveryByte * 0x7F)) == w);
5321   // Use strict inequalities since in edge cases the function could be
5322   // further simplified.
5323   ASSERT(0 < m && m < n && n < 0x7F);
5324   // Has high bit set in every w byte less than n.
5325   uintptr_t tmp1 = kOneInEveryByte * (0x7F + n) - w;
5326   // Has high bit set in every w byte greater than m.
5327   uintptr_t tmp2 = w + kOneInEveryByte * (0x7F - m);
5328   return (tmp1 & tmp2 & (kOneInEveryByte * 0x80));
5329 }
5330 
5331 
5332 enum AsciiCaseConversion {
5333   ASCII_TO_LOWER,
5334   ASCII_TO_UPPER
5335 };
5336 
5337 
5338 template <AsciiCaseConversion dir>
5339 struct FastAsciiConverter {
Convertv8::internal::__anona08bcc200111::FastAsciiConverter5340   static bool Convert(char* dst, char* src, int length) {
5341 #ifdef DEBUG
5342     char* saved_dst = dst;
5343     char* saved_src = src;
5344 #endif
5345     // We rely on the distance between upper and lower case letters
5346     // being a known power of 2.
5347     ASSERT('a' - 'A' == (1 << 5));
5348     // Boundaries for the range of input characters than require conversion.
5349     const char lo = (dir == ASCII_TO_LOWER) ? 'A' - 1 : 'a' - 1;
5350     const char hi = (dir == ASCII_TO_LOWER) ? 'Z' + 1 : 'z' + 1;
5351     bool changed = false;
5352     char* const limit = src + length;
5353 #ifdef V8_HOST_CAN_READ_UNALIGNED
5354     // Process the prefix of the input that requires no conversion one
5355     // (machine) word at a time.
5356     while (src <= limit - sizeof(uintptr_t)) {
5357       uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
5358       if (AsciiRangeMask(w, lo, hi) != 0) {
5359         changed = true;
5360         break;
5361       }
5362       *reinterpret_cast<uintptr_t*>(dst) = w;
5363       src += sizeof(uintptr_t);
5364       dst += sizeof(uintptr_t);
5365     }
5366     // Process the remainder of the input performing conversion when
5367     // required one word at a time.
5368     while (src <= limit - sizeof(uintptr_t)) {
5369       uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
5370       uintptr_t m = AsciiRangeMask(w, lo, hi);
5371       // The mask has high (7th) bit set in every byte that needs
5372       // conversion and we know that the distance between cases is
5373       // 1 << 5.
5374       *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2);
5375       src += sizeof(uintptr_t);
5376       dst += sizeof(uintptr_t);
5377     }
5378 #endif
5379     // Process the last few bytes of the input (or the whole input if
5380     // unaligned access is not supported).
5381     while (src < limit) {
5382       char c = *src;
5383       if (lo < c && c < hi) {
5384         c ^= (1 << 5);
5385         changed = true;
5386       }
5387       *dst = c;
5388       ++src;
5389       ++dst;
5390     }
5391 #ifdef DEBUG
5392     CheckConvert(saved_dst, saved_src, length, changed);
5393 #endif
5394     return changed;
5395   }
5396 
5397 #ifdef DEBUG
CheckConvertv8::internal::__anona08bcc200111::FastAsciiConverter5398   static void CheckConvert(char* dst, char* src, int length, bool changed) {
5399     bool expected_changed = false;
5400     for (int i = 0; i < length; i++) {
5401       if (dst[i] == src[i]) continue;
5402       expected_changed = true;
5403       if (dir == ASCII_TO_LOWER) {
5404         ASSERT('A' <= src[i] && src[i] <= 'Z');
5405         ASSERT(dst[i] == src[i] + ('a' - 'A'));
5406       } else {
5407         ASSERT(dir == ASCII_TO_UPPER);
5408         ASSERT('a' <= src[i] && src[i] <= 'z');
5409         ASSERT(dst[i] == src[i] - ('a' - 'A'));
5410       }
5411     }
5412     ASSERT(expected_changed == changed);
5413   }
5414 #endif
5415 };
5416 
5417 
5418 struct ToLowerTraits {
5419   typedef unibrow::ToLowercase UnibrowConverter;
5420 
5421   typedef FastAsciiConverter<ASCII_TO_LOWER> AsciiConverter;
5422 };
5423 
5424 
5425 struct ToUpperTraits {
5426   typedef unibrow::ToUppercase UnibrowConverter;
5427 
5428   typedef FastAsciiConverter<ASCII_TO_UPPER> AsciiConverter;
5429 };
5430 
5431 }  // namespace
5432 
5433 
5434 template <typename ConvertTraits>
ConvertCase(Arguments args,Isolate * isolate,unibrow::Mapping<typename ConvertTraits::UnibrowConverter,128> * mapping)5435 MUST_USE_RESULT static MaybeObject* ConvertCase(
5436     Arguments args,
5437     Isolate* isolate,
5438     unibrow::Mapping<typename ConvertTraits::UnibrowConverter, 128>* mapping) {
5439   NoHandleAllocation ha;
5440   CONVERT_CHECKED(String, s, args[0]);
5441   s = s->TryFlattenGetString();
5442 
5443   const int length = s->length();
5444   // Assume that the string is not empty; we need this assumption later
5445   if (length == 0) return s;
5446 
5447   // Simpler handling of ascii strings.
5448   //
5449   // NOTE: This assumes that the upper/lower case of an ascii
5450   // character is also ascii.  This is currently the case, but it
5451   // might break in the future if we implement more context and locale
5452   // dependent upper/lower conversions.
5453   if (s->IsSeqAsciiString()) {
5454     Object* o;
5455     { MaybeObject* maybe_o = isolate->heap()->AllocateRawAsciiString(length);
5456       if (!maybe_o->ToObject(&o)) return maybe_o;
5457     }
5458     SeqAsciiString* result = SeqAsciiString::cast(o);
5459     bool has_changed_character = ConvertTraits::AsciiConverter::Convert(
5460         result->GetChars(), SeqAsciiString::cast(s)->GetChars(), length);
5461     return has_changed_character ? result : s;
5462   }
5463 
5464   Object* answer;
5465   { MaybeObject* maybe_answer =
5466         ConvertCaseHelper(isolate, s, length, length, mapping);
5467     if (!maybe_answer->ToObject(&answer)) return maybe_answer;
5468   }
5469   if (answer->IsSmi()) {
5470     // Retry with correct length.
5471     { MaybeObject* maybe_answer =
5472           ConvertCaseHelper(isolate,
5473                             s, Smi::cast(answer)->value(), length, mapping);
5474       if (!maybe_answer->ToObject(&answer)) return maybe_answer;
5475     }
5476   }
5477   return answer;
5478 }
5479 
5480 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringToLowerCase)5481 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) {
5482   return ConvertCase<ToLowerTraits>(
5483       args, isolate, isolate->runtime_state()->to_lower_mapping());
5484 }
5485 
5486 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringToUpperCase)5487 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToUpperCase) {
5488   return ConvertCase<ToUpperTraits>(
5489       args, isolate, isolate->runtime_state()->to_upper_mapping());
5490 }
5491 
5492 
IsTrimWhiteSpace(unibrow::uchar c)5493 static inline bool IsTrimWhiteSpace(unibrow::uchar c) {
5494   return unibrow::WhiteSpace::Is(c) || c == 0x200b;
5495 }
5496 
5497 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringTrim)5498 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringTrim) {
5499   NoHandleAllocation ha;
5500   ASSERT(args.length() == 3);
5501 
5502   CONVERT_CHECKED(String, s, args[0]);
5503   CONVERT_BOOLEAN_CHECKED(trimLeft, args[1]);
5504   CONVERT_BOOLEAN_CHECKED(trimRight, args[2]);
5505 
5506   s->TryFlatten();
5507   int length = s->length();
5508 
5509   int left = 0;
5510   if (trimLeft) {
5511     while (left < length && IsTrimWhiteSpace(s->Get(left))) {
5512       left++;
5513     }
5514   }
5515 
5516   int right = length;
5517   if (trimRight) {
5518     while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) {
5519       right--;
5520     }
5521   }
5522   return s->SubString(left, right);
5523 }
5524 
5525 
5526 template <typename SubjectChar, typename PatternChar>
FindStringIndices(Isolate * isolate,Vector<const SubjectChar> subject,Vector<const PatternChar> pattern,ZoneList<int> * indices,unsigned int limit)5527 void FindStringIndices(Isolate* isolate,
5528                        Vector<const SubjectChar> subject,
5529                        Vector<const PatternChar> pattern,
5530                        ZoneList<int>* indices,
5531                        unsigned int limit) {
5532   ASSERT(limit > 0);
5533   // Collect indices of pattern in subject, and the end-of-string index.
5534   // Stop after finding at most limit values.
5535   StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
5536   int pattern_length = pattern.length();
5537   int index = 0;
5538   while (limit > 0) {
5539     index = search.Search(subject, index);
5540     if (index < 0) return;
5541     indices->Add(index);
5542     index += pattern_length;
5543     limit--;
5544   }
5545 }
5546 
5547 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringSplit)5548 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
5549   ASSERT(args.length() == 3);
5550   HandleScope handle_scope(isolate);
5551   CONVERT_ARG_CHECKED(String, subject, 0);
5552   CONVERT_ARG_CHECKED(String, pattern, 1);
5553   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]);
5554 
5555   int subject_length = subject->length();
5556   int pattern_length = pattern->length();
5557   RUNTIME_ASSERT(pattern_length > 0);
5558 
5559   // The limit can be very large (0xffffffffu), but since the pattern
5560   // isn't empty, we can never create more parts than ~half the length
5561   // of the subject.
5562 
5563   if (!subject->IsFlat()) FlattenString(subject);
5564 
5565   static const int kMaxInitialListCapacity = 16;
5566 
5567   ZoneScope scope(DELETE_ON_EXIT);
5568 
5569   // Find (up to limit) indices of separator and end-of-string in subject
5570   int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit);
5571   ZoneList<int> indices(initial_capacity);
5572   if (!pattern->IsFlat()) FlattenString(pattern);
5573 
5574   // No allocation block.
5575   {
5576     AssertNoAllocation nogc;
5577     if (subject->IsAsciiRepresentation()) {
5578       Vector<const char> subject_vector = subject->ToAsciiVector();
5579       if (pattern->IsAsciiRepresentation()) {
5580         FindStringIndices(isolate,
5581                           subject_vector,
5582                           pattern->ToAsciiVector(),
5583                           &indices,
5584                           limit);
5585       } else {
5586         FindStringIndices(isolate,
5587                           subject_vector,
5588                           pattern->ToUC16Vector(),
5589                           &indices,
5590                           limit);
5591       }
5592     } else {
5593       Vector<const uc16> subject_vector = subject->ToUC16Vector();
5594       if (pattern->IsAsciiRepresentation()) {
5595         FindStringIndices(isolate,
5596                           subject_vector,
5597                           pattern->ToAsciiVector(),
5598                           &indices,
5599                           limit);
5600       } else {
5601         FindStringIndices(isolate,
5602                           subject_vector,
5603                           pattern->ToUC16Vector(),
5604                           &indices,
5605                           limit);
5606       }
5607     }
5608   }
5609 
5610   if (static_cast<uint32_t>(indices.length()) < limit) {
5611     indices.Add(subject_length);
5612   }
5613 
5614   // The list indices now contains the end of each part to create.
5615 
5616   // Create JSArray of substrings separated by separator.
5617   int part_count = indices.length();
5618 
5619   Handle<JSArray> result = isolate->factory()->NewJSArray(part_count);
5620   result->set_length(Smi::FromInt(part_count));
5621 
5622   ASSERT(result->HasFastElements());
5623 
5624   if (part_count == 1 && indices.at(0) == subject_length) {
5625     FixedArray::cast(result->elements())->set(0, *subject);
5626     return *result;
5627   }
5628 
5629   Handle<FixedArray> elements(FixedArray::cast(result->elements()));
5630   int part_start = 0;
5631   for (int i = 0; i < part_count; i++) {
5632     HandleScope local_loop_handle;
5633     int part_end = indices.at(i);
5634     Handle<String> substring =
5635         isolate->factory()->NewSubString(subject, part_start, part_end);
5636     elements->set(i, *substring);
5637     part_start = part_end + pattern_length;
5638   }
5639 
5640   return *result;
5641 }
5642 
5643 
5644 // Copies ascii characters to the given fixed array looking up
5645 // one-char strings in the cache. Gives up on the first char that is
5646 // not in the cache and fills the remainder with smi zeros. Returns
5647 // the length of the successfully copied prefix.
CopyCachedAsciiCharsToArray(Heap * heap,const char * chars,FixedArray * elements,int length)5648 static int CopyCachedAsciiCharsToArray(Heap* heap,
5649                                        const char* chars,
5650                                        FixedArray* elements,
5651                                        int length) {
5652   AssertNoAllocation nogc;
5653   FixedArray* ascii_cache = heap->single_character_string_cache();
5654   Object* undefined = heap->undefined_value();
5655   int i;
5656   for (i = 0; i < length; ++i) {
5657     Object* value = ascii_cache->get(chars[i]);
5658     if (value == undefined) break;
5659     ASSERT(!heap->InNewSpace(value));
5660     elements->set(i, value, SKIP_WRITE_BARRIER);
5661   }
5662   if (i < length) {
5663     ASSERT(Smi::FromInt(0) == 0);
5664     memset(elements->data_start() + i, 0, kPointerSize * (length - i));
5665   }
5666 #ifdef DEBUG
5667   for (int j = 0; j < length; ++j) {
5668     Object* element = elements->get(j);
5669     ASSERT(element == Smi::FromInt(0) ||
5670            (element->IsString() && String::cast(element)->LooksValid()));
5671   }
5672 #endif
5673   return i;
5674 }
5675 
5676 
5677 // Converts a String to JSArray.
5678 // For example, "foo" => ["f", "o", "o"].
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringToArray)5679 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToArray) {
5680   HandleScope scope(isolate);
5681   ASSERT(args.length() == 2);
5682   CONVERT_ARG_CHECKED(String, s, 0);
5683   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
5684 
5685   s->TryFlatten();
5686   const int length = static_cast<int>(Min<uint32_t>(s->length(), limit));
5687 
5688   Handle<FixedArray> elements;
5689   if (s->IsFlat() && s->IsAsciiRepresentation()) {
5690     Object* obj;
5691     { MaybeObject* maybe_obj =
5692           isolate->heap()->AllocateUninitializedFixedArray(length);
5693       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
5694     }
5695     elements = Handle<FixedArray>(FixedArray::cast(obj), isolate);
5696 
5697     Vector<const char> chars = s->ToAsciiVector();
5698     // Note, this will initialize all elements (not only the prefix)
5699     // to prevent GC from seeing partially initialized array.
5700     int num_copied_from_cache = CopyCachedAsciiCharsToArray(isolate->heap(),
5701                                                             chars.start(),
5702                                                             *elements,
5703                                                             length);
5704 
5705     for (int i = num_copied_from_cache; i < length; ++i) {
5706       Handle<Object> str = LookupSingleCharacterStringFromCode(chars[i]);
5707       elements->set(i, *str);
5708     }
5709   } else {
5710     elements = isolate->factory()->NewFixedArray(length);
5711     for (int i = 0; i < length; ++i) {
5712       Handle<Object> str = LookupSingleCharacterStringFromCode(s->Get(i));
5713       elements->set(i, *str);
5714     }
5715   }
5716 
5717 #ifdef DEBUG
5718   for (int i = 0; i < length; ++i) {
5719     ASSERT(String::cast(elements->get(i))->length() == 1);
5720   }
5721 #endif
5722 
5723   return *isolate->factory()->NewJSArrayWithElements(elements);
5724 }
5725 
5726 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewStringWrapper)5727 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStringWrapper) {
5728   NoHandleAllocation ha;
5729   ASSERT(args.length() == 1);
5730   CONVERT_CHECKED(String, value, args[0]);
5731   return value->ToObject();
5732 }
5733 
5734 
IsUpperCaseChar(RuntimeState * runtime_state,uint16_t ch)5735 bool Runtime::IsUpperCaseChar(RuntimeState* runtime_state, uint16_t ch) {
5736   unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth];
5737   int char_length = runtime_state->to_upper_mapping()->get(ch, 0, chars);
5738   return char_length == 0;
5739 }
5740 
5741 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToString)5742 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToString) {
5743   NoHandleAllocation ha;
5744   ASSERT(args.length() == 1);
5745 
5746   Object* number = args[0];
5747   RUNTIME_ASSERT(number->IsNumber());
5748 
5749   return isolate->heap()->NumberToString(number);
5750 }
5751 
5752 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToStringSkipCache)5753 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToStringSkipCache) {
5754   NoHandleAllocation ha;
5755   ASSERT(args.length() == 1);
5756 
5757   Object* number = args[0];
5758   RUNTIME_ASSERT(number->IsNumber());
5759 
5760   return isolate->heap()->NumberToString(number, false);
5761 }
5762 
5763 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToInteger)5764 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToInteger) {
5765   NoHandleAllocation ha;
5766   ASSERT(args.length() == 1);
5767 
5768   CONVERT_DOUBLE_CHECKED(number, args[0]);
5769 
5770   // We do not include 0 so that we don't have to treat +0 / -0 cases.
5771   if (number > 0 && number <= Smi::kMaxValue) {
5772     return Smi::FromInt(static_cast<int>(number));
5773   }
5774   return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
5775 }
5776 
5777 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToIntegerMapMinusZero)5778 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToIntegerMapMinusZero) {
5779   NoHandleAllocation ha;
5780   ASSERT(args.length() == 1);
5781 
5782   CONVERT_DOUBLE_CHECKED(number, args[0]);
5783 
5784   // We do not include 0 so that we don't have to treat +0 / -0 cases.
5785   if (number > 0 && number <= Smi::kMaxValue) {
5786     return Smi::FromInt(static_cast<int>(number));
5787   }
5788 
5789   double double_value = DoubleToInteger(number);
5790   // Map both -0 and +0 to +0.
5791   if (double_value == 0) double_value = 0;
5792 
5793   return isolate->heap()->NumberFromDouble(double_value);
5794 }
5795 
5796 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToJSUint32)5797 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSUint32) {
5798   NoHandleAllocation ha;
5799   ASSERT(args.length() == 1);
5800 
5801   CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]);
5802   return isolate->heap()->NumberFromUint32(number);
5803 }
5804 
5805 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToJSInt32)5806 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSInt32) {
5807   NoHandleAllocation ha;
5808   ASSERT(args.length() == 1);
5809 
5810   CONVERT_DOUBLE_CHECKED(number, args[0]);
5811 
5812   // We do not include 0 so that we don't have to treat +0 / -0 cases.
5813   if (number > 0 && number <= Smi::kMaxValue) {
5814     return Smi::FromInt(static_cast<int>(number));
5815   }
5816   return isolate->heap()->NumberFromInt32(DoubleToInt32(number));
5817 }
5818 
5819 
5820 // Converts a Number to a Smi, if possible. Returns NaN if the number is not
5821 // a small integer.
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberToSmi)5822 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToSmi) {
5823   NoHandleAllocation ha;
5824   ASSERT(args.length() == 1);
5825 
5826   Object* obj = args[0];
5827   if (obj->IsSmi()) {
5828     return obj;
5829   }
5830   if (obj->IsHeapNumber()) {
5831     double value = HeapNumber::cast(obj)->value();
5832     int int_value = FastD2I(value);
5833     if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
5834       return Smi::FromInt(int_value);
5835     }
5836   }
5837   return isolate->heap()->nan_value();
5838 }
5839 
5840 
RUNTIME_FUNCTION(MaybeObject *,Runtime_AllocateHeapNumber)5841 RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateHeapNumber) {
5842   NoHandleAllocation ha;
5843   ASSERT(args.length() == 0);
5844   return isolate->heap()->AllocateHeapNumber(0);
5845 }
5846 
5847 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberAdd)5848 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAdd) {
5849   NoHandleAllocation ha;
5850   ASSERT(args.length() == 2);
5851 
5852   CONVERT_DOUBLE_CHECKED(x, args[0]);
5853   CONVERT_DOUBLE_CHECKED(y, args[1]);
5854   return isolate->heap()->NumberFromDouble(x + y);
5855 }
5856 
5857 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberSub)5858 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSub) {
5859   NoHandleAllocation ha;
5860   ASSERT(args.length() == 2);
5861 
5862   CONVERT_DOUBLE_CHECKED(x, args[0]);
5863   CONVERT_DOUBLE_CHECKED(y, args[1]);
5864   return isolate->heap()->NumberFromDouble(x - y);
5865 }
5866 
5867 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberMul)5868 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMul) {
5869   NoHandleAllocation ha;
5870   ASSERT(args.length() == 2);
5871 
5872   CONVERT_DOUBLE_CHECKED(x, args[0]);
5873   CONVERT_DOUBLE_CHECKED(y, args[1]);
5874   return isolate->heap()->NumberFromDouble(x * y);
5875 }
5876 
5877 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberUnaryMinus)5878 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberUnaryMinus) {
5879   NoHandleAllocation ha;
5880   ASSERT(args.length() == 1);
5881 
5882   CONVERT_DOUBLE_CHECKED(x, args[0]);
5883   return isolate->heap()->NumberFromDouble(-x);
5884 }
5885 
5886 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberAlloc)5887 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAlloc) {
5888   NoHandleAllocation ha;
5889   ASSERT(args.length() == 0);
5890 
5891   return isolate->heap()->NumberFromDouble(9876543210.0);
5892 }
5893 
5894 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberDiv)5895 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberDiv) {
5896   NoHandleAllocation ha;
5897   ASSERT(args.length() == 2);
5898 
5899   CONVERT_DOUBLE_CHECKED(x, args[0]);
5900   CONVERT_DOUBLE_CHECKED(y, args[1]);
5901   return isolate->heap()->NumberFromDouble(x / y);
5902 }
5903 
5904 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberMod)5905 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMod) {
5906   NoHandleAllocation ha;
5907   ASSERT(args.length() == 2);
5908 
5909   CONVERT_DOUBLE_CHECKED(x, args[0]);
5910   CONVERT_DOUBLE_CHECKED(y, args[1]);
5911 
5912   x = modulo(x, y);
5913   // NumberFromDouble may return a Smi instead of a Number object
5914   return isolate->heap()->NumberFromDouble(x);
5915 }
5916 
5917 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringAdd)5918 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringAdd) {
5919   NoHandleAllocation ha;
5920   ASSERT(args.length() == 2);
5921   CONVERT_CHECKED(String, str1, args[0]);
5922   CONVERT_CHECKED(String, str2, args[1]);
5923   isolate->counters()->string_add_runtime()->Increment();
5924   return isolate->heap()->AllocateConsString(str1, str2);
5925 }
5926 
5927 
5928 template <typename sinkchar>
StringBuilderConcatHelper(String * special,sinkchar * sink,FixedArray * fixed_array,int array_length)5929 static inline void StringBuilderConcatHelper(String* special,
5930                                              sinkchar* sink,
5931                                              FixedArray* fixed_array,
5932                                              int array_length) {
5933   int position = 0;
5934   for (int i = 0; i < array_length; i++) {
5935     Object* element = fixed_array->get(i);
5936     if (element->IsSmi()) {
5937       // Smi encoding of position and length.
5938       int encoded_slice = Smi::cast(element)->value();
5939       int pos;
5940       int len;
5941       if (encoded_slice > 0) {
5942         // Position and length encoded in one smi.
5943         pos = StringBuilderSubstringPosition::decode(encoded_slice);
5944         len = StringBuilderSubstringLength::decode(encoded_slice);
5945       } else {
5946         // Position and length encoded in two smis.
5947         Object* obj = fixed_array->get(++i);
5948         ASSERT(obj->IsSmi());
5949         pos = Smi::cast(obj)->value();
5950         len = -encoded_slice;
5951       }
5952       String::WriteToFlat(special,
5953                           sink + position,
5954                           pos,
5955                           pos + len);
5956       position += len;
5957     } else {
5958       String* string = String::cast(element);
5959       int element_length = string->length();
5960       String::WriteToFlat(string, sink + position, 0, element_length);
5961       position += element_length;
5962     }
5963   }
5964 }
5965 
5966 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringBuilderConcat)5967 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
5968   NoHandleAllocation ha;
5969   ASSERT(args.length() == 3);
5970   CONVERT_CHECKED(JSArray, array, args[0]);
5971   if (!args[1]->IsSmi()) {
5972     isolate->context()->mark_out_of_memory();
5973     return Failure::OutOfMemoryException();
5974   }
5975   int array_length = Smi::cast(args[1])->value();
5976   CONVERT_CHECKED(String, special, args[2]);
5977 
5978   // This assumption is used by the slice encoding in one or two smis.
5979   ASSERT(Smi::kMaxValue >= String::kMaxLength);
5980 
5981   int special_length = special->length();
5982   if (!array->HasFastElements()) {
5983     return isolate->Throw(isolate->heap()->illegal_argument_symbol());
5984   }
5985   FixedArray* fixed_array = FixedArray::cast(array->elements());
5986   if (fixed_array->length() < array_length) {
5987     array_length = fixed_array->length();
5988   }
5989 
5990   if (array_length == 0) {
5991     return isolate->heap()->empty_string();
5992   } else if (array_length == 1) {
5993     Object* first = fixed_array->get(0);
5994     if (first->IsString()) return first;
5995   }
5996 
5997   bool ascii = special->HasOnlyAsciiChars();
5998   int position = 0;
5999   for (int i = 0; i < array_length; i++) {
6000     int increment = 0;
6001     Object* elt = fixed_array->get(i);
6002     if (elt->IsSmi()) {
6003       // Smi encoding of position and length.
6004       int smi_value = Smi::cast(elt)->value();
6005       int pos;
6006       int len;
6007       if (smi_value > 0) {
6008         // Position and length encoded in one smi.
6009         pos = StringBuilderSubstringPosition::decode(smi_value);
6010         len = StringBuilderSubstringLength::decode(smi_value);
6011       } else {
6012         // Position and length encoded in two smis.
6013         len = -smi_value;
6014         // Get the position and check that it is a positive smi.
6015         i++;
6016         if (i >= array_length) {
6017           return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6018         }
6019         Object* next_smi = fixed_array->get(i);
6020         if (!next_smi->IsSmi()) {
6021           return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6022         }
6023         pos = Smi::cast(next_smi)->value();
6024         if (pos < 0) {
6025           return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6026         }
6027       }
6028       ASSERT(pos >= 0);
6029       ASSERT(len >= 0);
6030       if (pos > special_length || len > special_length - pos) {
6031         return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6032       }
6033       increment = len;
6034     } else if (elt->IsString()) {
6035       String* element = String::cast(elt);
6036       int element_length = element->length();
6037       increment = element_length;
6038       if (ascii && !element->HasOnlyAsciiChars()) {
6039         ascii = false;
6040       }
6041     } else {
6042       return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6043     }
6044     if (increment > String::kMaxLength - position) {
6045       isolate->context()->mark_out_of_memory();
6046       return Failure::OutOfMemoryException();
6047     }
6048     position += increment;
6049   }
6050 
6051   int length = position;
6052   Object* object;
6053 
6054   if (ascii) {
6055     { MaybeObject* maybe_object =
6056           isolate->heap()->AllocateRawAsciiString(length);
6057       if (!maybe_object->ToObject(&object)) return maybe_object;
6058     }
6059     SeqAsciiString* answer = SeqAsciiString::cast(object);
6060     StringBuilderConcatHelper(special,
6061                               answer->GetChars(),
6062                               fixed_array,
6063                               array_length);
6064     return answer;
6065   } else {
6066     { MaybeObject* maybe_object =
6067           isolate->heap()->AllocateRawTwoByteString(length);
6068       if (!maybe_object->ToObject(&object)) return maybe_object;
6069     }
6070     SeqTwoByteString* answer = SeqTwoByteString::cast(object);
6071     StringBuilderConcatHelper(special,
6072                               answer->GetChars(),
6073                               fixed_array,
6074                               array_length);
6075     return answer;
6076   }
6077 }
6078 
6079 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringBuilderJoin)6080 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
6081   NoHandleAllocation ha;
6082   ASSERT(args.length() == 3);
6083   CONVERT_CHECKED(JSArray, array, args[0]);
6084   if (!args[1]->IsSmi()) {
6085     isolate->context()->mark_out_of_memory();
6086     return Failure::OutOfMemoryException();
6087   }
6088   int array_length = Smi::cast(args[1])->value();
6089   CONVERT_CHECKED(String, separator, args[2]);
6090 
6091   if (!array->HasFastElements()) {
6092     return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6093   }
6094   FixedArray* fixed_array = FixedArray::cast(array->elements());
6095   if (fixed_array->length() < array_length) {
6096     array_length = fixed_array->length();
6097   }
6098 
6099   if (array_length == 0) {
6100     return isolate->heap()->empty_string();
6101   } else if (array_length == 1) {
6102     Object* first = fixed_array->get(0);
6103     if (first->IsString()) return first;
6104   }
6105 
6106   int separator_length = separator->length();
6107   int max_nof_separators =
6108       (String::kMaxLength + separator_length - 1) / separator_length;
6109   if (max_nof_separators < (array_length - 1)) {
6110       isolate->context()->mark_out_of_memory();
6111       return Failure::OutOfMemoryException();
6112   }
6113   int length = (array_length - 1) * separator_length;
6114   for (int i = 0; i < array_length; i++) {
6115     Object* element_obj = fixed_array->get(i);
6116     if (!element_obj->IsString()) {
6117       // TODO(1161): handle this case.
6118       return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6119     }
6120     String* element = String::cast(element_obj);
6121     int increment = element->length();
6122     if (increment > String::kMaxLength - length) {
6123       isolate->context()->mark_out_of_memory();
6124       return Failure::OutOfMemoryException();
6125     }
6126     length += increment;
6127   }
6128 
6129   Object* object;
6130   { MaybeObject* maybe_object =
6131         isolate->heap()->AllocateRawTwoByteString(length);
6132     if (!maybe_object->ToObject(&object)) return maybe_object;
6133   }
6134   SeqTwoByteString* answer = SeqTwoByteString::cast(object);
6135 
6136   uc16* sink = answer->GetChars();
6137 #ifdef DEBUG
6138   uc16* end = sink + length;
6139 #endif
6140 
6141   String* first = String::cast(fixed_array->get(0));
6142   int first_length = first->length();
6143   String::WriteToFlat(first, sink, 0, first_length);
6144   sink += first_length;
6145 
6146   for (int i = 1; i < array_length; i++) {
6147     ASSERT(sink + separator_length <= end);
6148     String::WriteToFlat(separator, sink, 0, separator_length);
6149     sink += separator_length;
6150 
6151     String* element = String::cast(fixed_array->get(i));
6152     int element_length = element->length();
6153     ASSERT(sink + element_length <= end);
6154     String::WriteToFlat(element, sink, 0, element_length);
6155     sink += element_length;
6156   }
6157   ASSERT(sink == end);
6158 
6159   ASSERT(!answer->HasOnlyAsciiChars());  // Use %_FastAsciiArrayJoin instead.
6160   return answer;
6161 }
6162 
6163 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberOr)6164 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberOr) {
6165   NoHandleAllocation ha;
6166   ASSERT(args.length() == 2);
6167 
6168   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
6169   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
6170   return isolate->heap()->NumberFromInt32(x | y);
6171 }
6172 
6173 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberAnd)6174 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAnd) {
6175   NoHandleAllocation ha;
6176   ASSERT(args.length() == 2);
6177 
6178   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
6179   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
6180   return isolate->heap()->NumberFromInt32(x & y);
6181 }
6182 
6183 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberXor)6184 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberXor) {
6185   NoHandleAllocation ha;
6186   ASSERT(args.length() == 2);
6187 
6188   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
6189   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
6190   return isolate->heap()->NumberFromInt32(x ^ y);
6191 }
6192 
6193 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberNot)6194 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberNot) {
6195   NoHandleAllocation ha;
6196   ASSERT(args.length() == 1);
6197 
6198   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
6199   return isolate->heap()->NumberFromInt32(~x);
6200 }
6201 
6202 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberShl)6203 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShl) {
6204   NoHandleAllocation ha;
6205   ASSERT(args.length() == 2);
6206 
6207   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
6208   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
6209   return isolate->heap()->NumberFromInt32(x << (y & 0x1f));
6210 }
6211 
6212 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberShr)6213 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShr) {
6214   NoHandleAllocation ha;
6215   ASSERT(args.length() == 2);
6216 
6217   CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
6218   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
6219   return isolate->heap()->NumberFromUint32(x >> (y & 0x1f));
6220 }
6221 
6222 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberSar)6223 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSar) {
6224   NoHandleAllocation ha;
6225   ASSERT(args.length() == 2);
6226 
6227   CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
6228   CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
6229   return isolate->heap()->NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f));
6230 }
6231 
6232 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberEquals)6233 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberEquals) {
6234   NoHandleAllocation ha;
6235   ASSERT(args.length() == 2);
6236 
6237   CONVERT_DOUBLE_CHECKED(x, args[0]);
6238   CONVERT_DOUBLE_CHECKED(y, args[1]);
6239   if (isnan(x)) return Smi::FromInt(NOT_EQUAL);
6240   if (isnan(y)) return Smi::FromInt(NOT_EQUAL);
6241   if (x == y) return Smi::FromInt(EQUAL);
6242   Object* result;
6243   if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
6244     result = Smi::FromInt(EQUAL);
6245   } else {
6246     result = Smi::FromInt(NOT_EQUAL);
6247   }
6248   return result;
6249 }
6250 
6251 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringEquals)6252 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) {
6253   NoHandleAllocation ha;
6254   ASSERT(args.length() == 2);
6255 
6256   CONVERT_CHECKED(String, x, args[0]);
6257   CONVERT_CHECKED(String, y, args[1]);
6258 
6259   bool not_equal = !x->Equals(y);
6260   // This is slightly convoluted because the value that signifies
6261   // equality is 0 and inequality is 1 so we have to negate the result
6262   // from String::Equals.
6263   ASSERT(not_equal == 0 || not_equal == 1);
6264   STATIC_CHECK(EQUAL == 0);
6265   STATIC_CHECK(NOT_EQUAL == 1);
6266   return Smi::FromInt(not_equal);
6267 }
6268 
6269 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NumberCompare)6270 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberCompare) {
6271   NoHandleAllocation ha;
6272   ASSERT(args.length() == 3);
6273 
6274   CONVERT_DOUBLE_CHECKED(x, args[0]);
6275   CONVERT_DOUBLE_CHECKED(y, args[1]);
6276   if (isnan(x) || isnan(y)) return args[2];
6277   if (x == y) return Smi::FromInt(EQUAL);
6278   if (isless(x, y)) return Smi::FromInt(LESS);
6279   return Smi::FromInt(GREATER);
6280 }
6281 
6282 
6283 // Compare two Smis as if they were converted to strings and then
6284 // compared lexicographically.
RUNTIME_FUNCTION(MaybeObject *,Runtime_SmiLexicographicCompare)6285 RUNTIME_FUNCTION(MaybeObject*, Runtime_SmiLexicographicCompare) {
6286   NoHandleAllocation ha;
6287   ASSERT(args.length() == 2);
6288 
6289   // Extract the integer values from the Smis.
6290   CONVERT_CHECKED(Smi, x, args[0]);
6291   CONVERT_CHECKED(Smi, y, args[1]);
6292   int x_value = x->value();
6293   int y_value = y->value();
6294 
6295   // If the integers are equal so are the string representations.
6296   if (x_value == y_value) return Smi::FromInt(EQUAL);
6297 
6298   // If one of the integers are zero the normal integer order is the
6299   // same as the lexicographic order of the string representations.
6300   if (x_value == 0 || y_value == 0) return Smi::FromInt(x_value - y_value);
6301 
6302   // If only one of the integers is negative the negative number is
6303   // smallest because the char code of '-' is less than the char code
6304   // of any digit.  Otherwise, we make both values positive.
6305   if (x_value < 0 || y_value < 0) {
6306     if (y_value >= 0) return Smi::FromInt(LESS);
6307     if (x_value >= 0) return Smi::FromInt(GREATER);
6308     x_value = -x_value;
6309     y_value = -y_value;
6310   }
6311 
6312   // Arrays for the individual characters of the two Smis.  Smis are
6313   // 31 bit integers and 10 decimal digits are therefore enough.
6314   // TODO(isolates): maybe we should simply allocate 20 bytes on the stack.
6315   int* x_elms = isolate->runtime_state()->smi_lexicographic_compare_x_elms();
6316   int* y_elms = isolate->runtime_state()->smi_lexicographic_compare_y_elms();
6317 
6318 
6319   // Convert the integers to arrays of their decimal digits.
6320   int x_index = 0;
6321   int y_index = 0;
6322   while (x_value > 0) {
6323     x_elms[x_index++] = x_value % 10;
6324     x_value /= 10;
6325   }
6326   while (y_value > 0) {
6327     y_elms[y_index++] = y_value % 10;
6328     y_value /= 10;
6329   }
6330 
6331   // Loop through the arrays of decimal digits finding the first place
6332   // where they differ.
6333   while (--x_index >= 0 && --y_index >= 0) {
6334     int diff = x_elms[x_index] - y_elms[y_index];
6335     if (diff != 0) return Smi::FromInt(diff);
6336   }
6337 
6338   // If one array is a suffix of the other array, the longest array is
6339   // the representation of the largest of the Smis in the
6340   // lexicographic ordering.
6341   return Smi::FromInt(x_index - y_index);
6342 }
6343 
6344 
StringInputBufferCompare(RuntimeState * state,String * x,String * y)6345 static Object* StringInputBufferCompare(RuntimeState* state,
6346                                         String* x,
6347                                         String* y) {
6348   StringInputBuffer& bufx = *state->string_input_buffer_compare_bufx();
6349   StringInputBuffer& bufy = *state->string_input_buffer_compare_bufy();
6350   bufx.Reset(x);
6351   bufy.Reset(y);
6352   while (bufx.has_more() && bufy.has_more()) {
6353     int d = bufx.GetNext() - bufy.GetNext();
6354     if (d < 0) return Smi::FromInt(LESS);
6355     else if (d > 0) return Smi::FromInt(GREATER);
6356   }
6357 
6358   // x is (non-trivial) prefix of y:
6359   if (bufy.has_more()) return Smi::FromInt(LESS);
6360   // y is prefix of x:
6361   return Smi::FromInt(bufx.has_more() ? GREATER : EQUAL);
6362 }
6363 
6364 
FlatStringCompare(String * x,String * y)6365 static Object* FlatStringCompare(String* x, String* y) {
6366   ASSERT(x->IsFlat());
6367   ASSERT(y->IsFlat());
6368   Object* equal_prefix_result = Smi::FromInt(EQUAL);
6369   int prefix_length = x->length();
6370   if (y->length() < prefix_length) {
6371     prefix_length = y->length();
6372     equal_prefix_result = Smi::FromInt(GREATER);
6373   } else if (y->length() > prefix_length) {
6374     equal_prefix_result = Smi::FromInt(LESS);
6375   }
6376   int r;
6377   if (x->IsAsciiRepresentation()) {
6378     Vector<const char> x_chars = x->ToAsciiVector();
6379     if (y->IsAsciiRepresentation()) {
6380       Vector<const char> y_chars = y->ToAsciiVector();
6381       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
6382     } else {
6383       Vector<const uc16> y_chars = y->ToUC16Vector();
6384       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
6385     }
6386   } else {
6387     Vector<const uc16> x_chars = x->ToUC16Vector();
6388     if (y->IsAsciiRepresentation()) {
6389       Vector<const char> y_chars = y->ToAsciiVector();
6390       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
6391     } else {
6392       Vector<const uc16> y_chars = y->ToUC16Vector();
6393       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
6394     }
6395   }
6396   Object* result;
6397   if (r == 0) {
6398     result = equal_prefix_result;
6399   } else {
6400     result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
6401   }
6402   ASSERT(result ==
6403       StringInputBufferCompare(Isolate::Current()->runtime_state(), x, y));
6404   return result;
6405 }
6406 
6407 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StringCompare)6408 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCompare) {
6409   NoHandleAllocation ha;
6410   ASSERT(args.length() == 2);
6411 
6412   CONVERT_CHECKED(String, x, args[0]);
6413   CONVERT_CHECKED(String, y, args[1]);
6414 
6415   isolate->counters()->string_compare_runtime()->Increment();
6416 
6417   // A few fast case tests before we flatten.
6418   if (x == y) return Smi::FromInt(EQUAL);
6419   if (y->length() == 0) {
6420     if (x->length() == 0) return Smi::FromInt(EQUAL);
6421     return Smi::FromInt(GREATER);
6422   } else if (x->length() == 0) {
6423     return Smi::FromInt(LESS);
6424   }
6425 
6426   int d = x->Get(0) - y->Get(0);
6427   if (d < 0) return Smi::FromInt(LESS);
6428   else if (d > 0) return Smi::FromInt(GREATER);
6429 
6430   Object* obj;
6431   { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(x);
6432     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
6433   }
6434   { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(y);
6435     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
6436   }
6437 
6438   return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
6439       : StringInputBufferCompare(isolate->runtime_state(), x, y);
6440 }
6441 
6442 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_acos)6443 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_acos) {
6444   NoHandleAllocation ha;
6445   ASSERT(args.length() == 1);
6446   isolate->counters()->math_acos()->Increment();
6447 
6448   CONVERT_DOUBLE_CHECKED(x, args[0]);
6449   return isolate->transcendental_cache()->Get(TranscendentalCache::ACOS, x);
6450 }
6451 
6452 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_asin)6453 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_asin) {
6454   NoHandleAllocation ha;
6455   ASSERT(args.length() == 1);
6456   isolate->counters()->math_asin()->Increment();
6457 
6458   CONVERT_DOUBLE_CHECKED(x, args[0]);
6459   return isolate->transcendental_cache()->Get(TranscendentalCache::ASIN, x);
6460 }
6461 
6462 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_atan)6463 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan) {
6464   NoHandleAllocation ha;
6465   ASSERT(args.length() == 1);
6466   isolate->counters()->math_atan()->Increment();
6467 
6468   CONVERT_DOUBLE_CHECKED(x, args[0]);
6469   return isolate->transcendental_cache()->Get(TranscendentalCache::ATAN, x);
6470 }
6471 
6472 
6473 static const double kPiDividedBy4 = 0.78539816339744830962;
6474 
6475 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_atan2)6476 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan2) {
6477   NoHandleAllocation ha;
6478   ASSERT(args.length() == 2);
6479   isolate->counters()->math_atan2()->Increment();
6480 
6481   CONVERT_DOUBLE_CHECKED(x, args[0]);
6482   CONVERT_DOUBLE_CHECKED(y, args[1]);
6483   double result;
6484   if (isinf(x) && isinf(y)) {
6485     // Make sure that the result in case of two infinite arguments
6486     // is a multiple of Pi / 4. The sign of the result is determined
6487     // by the first argument (x) and the sign of the second argument
6488     // determines the multiplier: one or three.
6489     int multiplier = (x < 0) ? -1 : 1;
6490     if (y < 0) multiplier *= 3;
6491     result = multiplier * kPiDividedBy4;
6492   } else {
6493     result = atan2(x, y);
6494   }
6495   return isolate->heap()->AllocateHeapNumber(result);
6496 }
6497 
6498 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_ceil)6499 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_ceil) {
6500   NoHandleAllocation ha;
6501   ASSERT(args.length() == 1);
6502   isolate->counters()->math_ceil()->Increment();
6503 
6504   CONVERT_DOUBLE_CHECKED(x, args[0]);
6505   return isolate->heap()->NumberFromDouble(ceiling(x));
6506 }
6507 
6508 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_cos)6509 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_cos) {
6510   NoHandleAllocation ha;
6511   ASSERT(args.length() == 1);
6512   isolate->counters()->math_cos()->Increment();
6513 
6514   CONVERT_DOUBLE_CHECKED(x, args[0]);
6515   return isolate->transcendental_cache()->Get(TranscendentalCache::COS, x);
6516 }
6517 
6518 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_exp)6519 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_exp) {
6520   NoHandleAllocation ha;
6521   ASSERT(args.length() == 1);
6522   isolate->counters()->math_exp()->Increment();
6523 
6524   CONVERT_DOUBLE_CHECKED(x, args[0]);
6525   return isolate->transcendental_cache()->Get(TranscendentalCache::EXP, x);
6526 }
6527 
6528 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_floor)6529 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_floor) {
6530   NoHandleAllocation ha;
6531   ASSERT(args.length() == 1);
6532   isolate->counters()->math_floor()->Increment();
6533 
6534   CONVERT_DOUBLE_CHECKED(x, args[0]);
6535   return isolate->heap()->NumberFromDouble(floor(x));
6536 }
6537 
6538 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_log)6539 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_log) {
6540   NoHandleAllocation ha;
6541   ASSERT(args.length() == 1);
6542   isolate->counters()->math_log()->Increment();
6543 
6544   CONVERT_DOUBLE_CHECKED(x, args[0]);
6545   return isolate->transcendental_cache()->Get(TranscendentalCache::LOG, x);
6546 }
6547 
6548 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_pow)6549 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow) {
6550   NoHandleAllocation ha;
6551   ASSERT(args.length() == 2);
6552   isolate->counters()->math_pow()->Increment();
6553 
6554   CONVERT_DOUBLE_CHECKED(x, args[0]);
6555 
6556   // If the second argument is a smi, it is much faster to call the
6557   // custom powi() function than the generic pow().
6558   if (args[1]->IsSmi()) {
6559     int y = Smi::cast(args[1])->value();
6560     return isolate->heap()->NumberFromDouble(power_double_int(x, y));
6561   }
6562 
6563   CONVERT_DOUBLE_CHECKED(y, args[1]);
6564   return isolate->heap()->AllocateHeapNumber(power_double_double(x, y));
6565 }
6566 
6567 // Fast version of Math.pow if we know that y is not an integer and
6568 // y is not -0.5 or 0.5. Used as slowcase from codegen.
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_pow_cfunction)6569 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow_cfunction) {
6570   NoHandleAllocation ha;
6571   ASSERT(args.length() == 2);
6572   CONVERT_DOUBLE_CHECKED(x, args[0]);
6573   CONVERT_DOUBLE_CHECKED(y, args[1]);
6574   if (y == 0) {
6575     return Smi::FromInt(1);
6576   } else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
6577     return isolate->heap()->nan_value();
6578   } else {
6579     return isolate->heap()->AllocateHeapNumber(pow(x, y));
6580   }
6581 }
6582 
6583 
RUNTIME_FUNCTION(MaybeObject *,Runtime_RoundNumber)6584 RUNTIME_FUNCTION(MaybeObject*, Runtime_RoundNumber) {
6585   NoHandleAllocation ha;
6586   ASSERT(args.length() == 1);
6587   isolate->counters()->math_round()->Increment();
6588 
6589   if (!args[0]->IsHeapNumber()) {
6590     // Must be smi. Return the argument unchanged for all the other types
6591     // to make fuzz-natives test happy.
6592     return args[0];
6593   }
6594 
6595   HeapNumber* number = reinterpret_cast<HeapNumber*>(args[0]);
6596 
6597   double value = number->value();
6598   int exponent = number->get_exponent();
6599   int sign = number->get_sign();
6600 
6601   // We compare with kSmiValueSize - 3 because (2^30 - 0.1) has exponent 29 and
6602   // should be rounded to 2^30, which is not smi.
6603   if (!sign && exponent <= kSmiValueSize - 3) {
6604     return Smi::FromInt(static_cast<int>(value + 0.5));
6605   }
6606 
6607   // If the magnitude is big enough, there's no place for fraction part. If we
6608   // try to add 0.5 to this number, 1.0 will be added instead.
6609   if (exponent >= 52) {
6610     return number;
6611   }
6612 
6613   if (sign && value >= -0.5) return isolate->heap()->minus_zero_value();
6614 
6615   // Do not call NumberFromDouble() to avoid extra checks.
6616   return isolate->heap()->AllocateHeapNumber(floor(value + 0.5));
6617 }
6618 
6619 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_sin)6620 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sin) {
6621   NoHandleAllocation ha;
6622   ASSERT(args.length() == 1);
6623   isolate->counters()->math_sin()->Increment();
6624 
6625   CONVERT_DOUBLE_CHECKED(x, args[0]);
6626   return isolate->transcendental_cache()->Get(TranscendentalCache::SIN, x);
6627 }
6628 
6629 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_sqrt)6630 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sqrt) {
6631   NoHandleAllocation ha;
6632   ASSERT(args.length() == 1);
6633   isolate->counters()->math_sqrt()->Increment();
6634 
6635   CONVERT_DOUBLE_CHECKED(x, args[0]);
6636   return isolate->heap()->AllocateHeapNumber(sqrt(x));
6637 }
6638 
6639 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Math_tan)6640 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_tan) {
6641   NoHandleAllocation ha;
6642   ASSERT(args.length() == 1);
6643   isolate->counters()->math_tan()->Increment();
6644 
6645   CONVERT_DOUBLE_CHECKED(x, args[0]);
6646   return isolate->transcendental_cache()->Get(TranscendentalCache::TAN, x);
6647 }
6648 
6649 
MakeDay(int year,int month,int day)6650 static int MakeDay(int year, int month, int day) {
6651   static const int day_from_month[] = {0, 31, 59, 90, 120, 151,
6652                                        181, 212, 243, 273, 304, 334};
6653   static const int day_from_month_leap[] = {0, 31, 60, 91, 121, 152,
6654                                             182, 213, 244, 274, 305, 335};
6655 
6656   year += month / 12;
6657   month %= 12;
6658   if (month < 0) {
6659     year--;
6660     month += 12;
6661   }
6662 
6663   ASSERT(month >= 0);
6664   ASSERT(month < 12);
6665 
6666   // year_delta is an arbitrary number such that:
6667   // a) year_delta = -1 (mod 400)
6668   // b) year + year_delta > 0 for years in the range defined by
6669   //    ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of
6670   //    Jan 1 1970. This is required so that we don't run into integer
6671   //    division of negative numbers.
6672   // c) there shouldn't be an overflow for 32-bit integers in the following
6673   //    operations.
6674   static const int year_delta = 399999;
6675   static const int base_day = 365 * (1970 + year_delta) +
6676                               (1970 + year_delta) / 4 -
6677                               (1970 + year_delta) / 100 +
6678                               (1970 + year_delta) / 400;
6679 
6680   int year1 = year + year_delta;
6681   int day_from_year = 365 * year1 +
6682                       year1 / 4 -
6683                       year1 / 100 +
6684                       year1 / 400 -
6685                       base_day;
6686 
6687   if (year % 4 || (year % 100 == 0 && year % 400 != 0)) {
6688     return day_from_year + day_from_month[month] + day - 1;
6689   }
6690 
6691   return day_from_year + day_from_month_leap[month] + day - 1;
6692 }
6693 
6694 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DateMakeDay)6695 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateMakeDay) {
6696   NoHandleAllocation ha;
6697   ASSERT(args.length() == 3);
6698 
6699   CONVERT_SMI_CHECKED(year, args[0]);
6700   CONVERT_SMI_CHECKED(month, args[1]);
6701   CONVERT_SMI_CHECKED(date, args[2]);
6702 
6703   return Smi::FromInt(MakeDay(year, month, date));
6704 }
6705 
6706 
6707 static const int kDays4Years[] = {0, 365, 2 * 365, 3 * 365 + 1};
6708 static const int kDaysIn4Years = 4 * 365 + 1;
6709 static const int kDaysIn100Years = 25 * kDaysIn4Years - 1;
6710 static const int kDaysIn400Years = 4 * kDaysIn100Years + 1;
6711 static const int kDays1970to2000 = 30 * 365 + 7;
6712 static const int kDaysOffset = 1000 * kDaysIn400Years + 5 * kDaysIn400Years -
6713                                kDays1970to2000;
6714 static const int kYearsOffset = 400000;
6715 
6716 static const char kDayInYear[] = {
6717       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6718       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6719       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6720       22, 23, 24, 25, 26, 27, 28,
6721       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6722       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6723       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6724       22, 23, 24, 25, 26, 27, 28, 29, 30,
6725       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6726       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6727       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6728       22, 23, 24, 25, 26, 27, 28, 29, 30,
6729       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6730       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6731       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6732       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6733       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6734       22, 23, 24, 25, 26, 27, 28, 29, 30,
6735       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6736       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6737       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6738       22, 23, 24, 25, 26, 27, 28, 29, 30,
6739       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6740       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6741 
6742       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6743       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6744       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6745       22, 23, 24, 25, 26, 27, 28,
6746       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6747       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6748       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6749       22, 23, 24, 25, 26, 27, 28, 29, 30,
6750       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6751       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6752       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6753       22, 23, 24, 25, 26, 27, 28, 29, 30,
6754       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6755       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6756       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6757       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6758       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6759       22, 23, 24, 25, 26, 27, 28, 29, 30,
6760       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6761       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6762       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6763       22, 23, 24, 25, 26, 27, 28, 29, 30,
6764       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6765       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6766 
6767       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6768       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6769       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6770       22, 23, 24, 25, 26, 27, 28, 29,
6771       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6772       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6773       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6774       22, 23, 24, 25, 26, 27, 28, 29, 30,
6775       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6776       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6777       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6778       22, 23, 24, 25, 26, 27, 28, 29, 30,
6779       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6780       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6781       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6782       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6783       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6784       22, 23, 24, 25, 26, 27, 28, 29, 30,
6785       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6786       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6787       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6788       22, 23, 24, 25, 26, 27, 28, 29, 30,
6789       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6790       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6791 
6792       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6793       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6794       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6795       22, 23, 24, 25, 26, 27, 28,
6796       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6797       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6798       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6799       22, 23, 24, 25, 26, 27, 28, 29, 30,
6800       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6801       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6802       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6803       22, 23, 24, 25, 26, 27, 28, 29, 30,
6804       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6805       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6806       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6807       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6808       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6809       22, 23, 24, 25, 26, 27, 28, 29, 30,
6810       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6811       22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
6812       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6813       22, 23, 24, 25, 26, 27, 28, 29, 30,
6814       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
6815       22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
6816 
6817 static const char kMonthInYear[] = {
6818       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6819       0, 0, 0, 0, 0, 0,
6820       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
6821       1, 1, 1,
6822       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
6823       2, 2, 2, 2, 2, 2,
6824       3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
6825       3, 3, 3, 3, 3,
6826       4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
6827       4, 4, 4, 4, 4, 4,
6828       5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6829       5, 5, 5, 5, 5,
6830       6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6831       6, 6, 6, 6, 6, 6,
6832       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
6833       7, 7, 7, 7, 7, 7,
6834       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
6835       8, 8, 8, 8, 8,
6836       9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
6837       9, 9, 9, 9, 9, 9,
6838       10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
6839       10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
6840       11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
6841       11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
6842 
6843       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6844       0, 0, 0, 0, 0, 0,
6845       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
6846       1, 1, 1,
6847       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
6848       2, 2, 2, 2, 2, 2,
6849       3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
6850       3, 3, 3, 3, 3,
6851       4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
6852       4, 4, 4, 4, 4, 4,
6853       5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6854       5, 5, 5, 5, 5,
6855       6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6856       6, 6, 6, 6, 6, 6,
6857       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
6858       7, 7, 7, 7, 7, 7,
6859       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
6860       8, 8, 8, 8, 8,
6861       9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
6862       9, 9, 9, 9, 9, 9,
6863       10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
6864       10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
6865       11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
6866       11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
6867 
6868       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6869       0, 0, 0, 0, 0, 0,
6870       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
6871       1, 1, 1, 1,
6872       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
6873       2, 2, 2, 2, 2, 2,
6874       3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
6875       3, 3, 3, 3, 3,
6876       4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
6877       4, 4, 4, 4, 4, 4,
6878       5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6879       5, 5, 5, 5, 5,
6880       6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6881       6, 6, 6, 6, 6, 6,
6882       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
6883       7, 7, 7, 7, 7, 7,
6884       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
6885       8, 8, 8, 8, 8,
6886       9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
6887       9, 9, 9, 9, 9, 9,
6888       10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
6889       10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
6890       11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
6891       11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
6892 
6893       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6894       0, 0, 0, 0, 0, 0,
6895       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
6896       1, 1, 1,
6897       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
6898       2, 2, 2, 2, 2, 2,
6899       3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
6900       3, 3, 3, 3, 3,
6901       4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
6902       4, 4, 4, 4, 4, 4,
6903       5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6904       5, 5, 5, 5, 5,
6905       6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6906       6, 6, 6, 6, 6, 6,
6907       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
6908       7, 7, 7, 7, 7, 7,
6909       8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
6910       8, 8, 8, 8, 8,
6911       9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
6912       9, 9, 9, 9, 9, 9,
6913       10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
6914       10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
6915       11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
6916       11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11};
6917 
6918 
6919 // This function works for dates from 1970 to 2099.
DateYMDFromTimeAfter1970(int date,int & year,int & month,int & day)6920 static inline void DateYMDFromTimeAfter1970(int date,
6921                                             int& year, int& month, int& day) {
6922 #ifdef DEBUG
6923   int save_date = date;  // Need this for ASSERT in the end.
6924 #endif
6925 
6926   year = 1970 + (4 * date + 2) / kDaysIn4Years;
6927   date %= kDaysIn4Years;
6928 
6929   month = kMonthInYear[date];
6930   day = kDayInYear[date];
6931 
6932   ASSERT(MakeDay(year, month, day) == save_date);
6933 }
6934 
6935 
DateYMDFromTimeSlow(int date,int & year,int & month,int & day)6936 static inline void DateYMDFromTimeSlow(int date,
6937                                        int& year, int& month, int& day) {
6938 #ifdef DEBUG
6939   int save_date = date;  // Need this for ASSERT in the end.
6940 #endif
6941 
6942   date += kDaysOffset;
6943   year = 400 * (date / kDaysIn400Years) - kYearsOffset;
6944   date %= kDaysIn400Years;
6945 
6946   ASSERT(MakeDay(year, 0, 1) + date == save_date);
6947 
6948   date--;
6949   int yd1 = date / kDaysIn100Years;
6950   date %= kDaysIn100Years;
6951   year += 100 * yd1;
6952 
6953   date++;
6954   int yd2 = date / kDaysIn4Years;
6955   date %= kDaysIn4Years;
6956   year += 4 * yd2;
6957 
6958   date--;
6959   int yd3 = date / 365;
6960   date %= 365;
6961   year += yd3;
6962 
6963   bool is_leap = (!yd1 || yd2) && !yd3;
6964 
6965   ASSERT(date >= -1);
6966   ASSERT(is_leap || (date >= 0));
6967   ASSERT((date < 365) || (is_leap && (date < 366)));
6968   ASSERT(is_leap == ((year % 4 == 0) && (year % 100 || (year % 400 == 0))));
6969   ASSERT(is_leap || ((MakeDay(year, 0, 1) + date) == save_date));
6970   ASSERT(!is_leap || ((MakeDay(year, 0, 1) + date + 1) == save_date));
6971 
6972   if (is_leap) {
6973     day = kDayInYear[2*365 + 1 + date];
6974     month = kMonthInYear[2*365 + 1 + date];
6975   } else {
6976     day = kDayInYear[date];
6977     month = kMonthInYear[date];
6978   }
6979 
6980   ASSERT(MakeDay(year, month, day) == save_date);
6981 }
6982 
6983 
DateYMDFromTime(int date,int & year,int & month,int & day)6984 static inline void DateYMDFromTime(int date,
6985                                    int& year, int& month, int& day) {
6986   if (date >= 0 && date < 32 * kDaysIn4Years) {
6987     DateYMDFromTimeAfter1970(date, year, month, day);
6988   } else {
6989     DateYMDFromTimeSlow(date, year, month, day);
6990   }
6991 }
6992 
6993 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DateYMDFromTime)6994 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateYMDFromTime) {
6995   NoHandleAllocation ha;
6996   ASSERT(args.length() == 2);
6997 
6998   CONVERT_DOUBLE_CHECKED(t, args[0]);
6999   CONVERT_CHECKED(JSArray, res_array, args[1]);
7000 
7001   int year, month, day;
7002   DateYMDFromTime(static_cast<int>(floor(t / 86400000)), year, month, day);
7003 
7004   RUNTIME_ASSERT(res_array->elements()->map() ==
7005                  isolate->heap()->fixed_array_map());
7006   FixedArray* elms = FixedArray::cast(res_array->elements());
7007   RUNTIME_ASSERT(elms->length() == 3);
7008 
7009   elms->set(0, Smi::FromInt(year));
7010   elms->set(1, Smi::FromInt(month));
7011   elms->set(2, Smi::FromInt(day));
7012 
7013   return isolate->heap()->undefined_value();
7014 }
7015 
7016 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewArgumentsFast)7017 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewArgumentsFast) {
7018   NoHandleAllocation ha;
7019   ASSERT(args.length() == 3);
7020 
7021   JSFunction* callee = JSFunction::cast(args[0]);
7022   Object** parameters = reinterpret_cast<Object**>(args[1]);
7023   const int length = Smi::cast(args[2])->value();
7024 
7025   Object* result;
7026   { MaybeObject* maybe_result =
7027         isolate->heap()->AllocateArgumentsObject(callee, length);
7028     if (!maybe_result->ToObject(&result)) return maybe_result;
7029   }
7030   // Allocate the elements if needed.
7031   if (length > 0) {
7032     // Allocate the fixed array.
7033     Object* obj;
7034     { MaybeObject* maybe_obj = isolate->heap()->AllocateRawFixedArray(length);
7035       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7036     }
7037 
7038     AssertNoAllocation no_gc;
7039     FixedArray* array = reinterpret_cast<FixedArray*>(obj);
7040     array->set_map(isolate->heap()->fixed_array_map());
7041     array->set_length(length);
7042 
7043     WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
7044     for (int i = 0; i < length; i++) {
7045       array->set(i, *--parameters, mode);
7046     }
7047     JSObject::cast(result)->set_elements(FixedArray::cast(obj));
7048   }
7049   return result;
7050 }
7051 
7052 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewClosure)7053 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewClosure) {
7054   HandleScope scope(isolate);
7055   ASSERT(args.length() == 3);
7056   CONVERT_ARG_CHECKED(Context, context, 0);
7057   CONVERT_ARG_CHECKED(SharedFunctionInfo, shared, 1);
7058   CONVERT_BOOLEAN_CHECKED(pretenure, args[2]);
7059 
7060   // Allocate global closures in old space and allocate local closures
7061   // in new space. Additionally pretenure closures that are assigned
7062   // directly to properties.
7063   pretenure = pretenure || (context->global_context() == *context);
7064   PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
7065   Handle<JSFunction> result =
7066       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
7067                                                             context,
7068                                                             pretenure_flag);
7069   return *result;
7070 }
7071 
7072 
GetNonBoundArguments(int bound_argc,int * total_argc)7073 static SmartPointer<Object**> GetNonBoundArguments(int bound_argc,
7074                                                    int* total_argc) {
7075   // Find frame containing arguments passed to the caller.
7076   JavaScriptFrameIterator it;
7077   JavaScriptFrame* frame = it.frame();
7078   List<JSFunction*> functions(2);
7079   frame->GetFunctions(&functions);
7080   if (functions.length() > 1) {
7081     int inlined_frame_index = functions.length() - 1;
7082     JSFunction* inlined_function = functions[inlined_frame_index];
7083     int args_count = inlined_function->shared()->formal_parameter_count();
7084     ScopedVector<SlotRef> args_slots(args_count);
7085     SlotRef::ComputeSlotMappingForArguments(frame,
7086                                             inlined_frame_index,
7087                                             &args_slots);
7088 
7089     *total_argc = bound_argc + args_count;
7090     SmartPointer<Object**> param_data(NewArray<Object**>(*total_argc));
7091     for (int i = 0; i < args_count; i++) {
7092       Handle<Object> val = args_slots[i].GetValue();
7093       param_data[bound_argc + i] = val.location();
7094     }
7095     return param_data;
7096   } else {
7097     it.AdvanceToArgumentsFrame();
7098     frame = it.frame();
7099     int args_count = frame->ComputeParametersCount();
7100 
7101     *total_argc = bound_argc + args_count;
7102     SmartPointer<Object**> param_data(NewArray<Object**>(*total_argc));
7103     for (int i = 0; i < args_count; i++) {
7104       Handle<Object> val = Handle<Object>(frame->GetParameter(i));
7105       param_data[bound_argc + i] = val.location();
7106     }
7107     return param_data;
7108   }
7109 }
7110 
7111 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewObjectFromBound)7112 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObjectFromBound) {
7113   HandleScope scope(isolate);
7114   ASSERT(args.length() == 2);
7115   // First argument is a function to use as a constructor.
7116   CONVERT_ARG_CHECKED(JSFunction, function, 0);
7117 
7118   // Second argument is either null or an array of bound arguments.
7119   Handle<FixedArray> bound_args;
7120   int bound_argc = 0;
7121   if (!args[1]->IsNull()) {
7122     CONVERT_ARG_CHECKED(JSArray, params, 1);
7123     RUNTIME_ASSERT(params->HasFastElements());
7124     bound_args = Handle<FixedArray>(FixedArray::cast(params->elements()));
7125     bound_argc = Smi::cast(params->length())->value();
7126   }
7127 
7128   int total_argc = 0;
7129   SmartPointer<Object**> param_data =
7130       GetNonBoundArguments(bound_argc, &total_argc);
7131   for (int i = 0; i < bound_argc; i++) {
7132     Handle<Object> val = Handle<Object>(bound_args->get(i));
7133     param_data[i] = val.location();
7134   }
7135 
7136   bool exception = false;
7137   Handle<Object> result =
7138       Execution::New(function, total_argc, *param_data, &exception);
7139   if (exception) {
7140       return Failure::Exception();
7141   }
7142 
7143   ASSERT(!result.is_null());
7144   return *result;
7145 }
7146 
7147 
TrySettingInlineConstructStub(Isolate * isolate,Handle<JSFunction> function)7148 static void TrySettingInlineConstructStub(Isolate* isolate,
7149                                           Handle<JSFunction> function) {
7150   Handle<Object> prototype = isolate->factory()->null_value();
7151   if (function->has_instance_prototype()) {
7152     prototype = Handle<Object>(function->instance_prototype(), isolate);
7153   }
7154   if (function->shared()->CanGenerateInlineConstructor(*prototype)) {
7155     ConstructStubCompiler compiler;
7156     MaybeObject* code = compiler.CompileConstructStub(*function);
7157     if (!code->IsFailure()) {
7158       function->shared()->set_construct_stub(
7159           Code::cast(code->ToObjectUnchecked()));
7160     }
7161   }
7162 }
7163 
7164 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewObject)7165 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObject) {
7166   HandleScope scope(isolate);
7167   ASSERT(args.length() == 1);
7168 
7169   Handle<Object> constructor = args.at<Object>(0);
7170 
7171   // If the constructor isn't a proper function we throw a type error.
7172   if (!constructor->IsJSFunction()) {
7173     Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
7174     Handle<Object> type_error =
7175         isolate->factory()->NewTypeError("not_constructor", arguments);
7176     return isolate->Throw(*type_error);
7177   }
7178 
7179   Handle<JSFunction> function = Handle<JSFunction>::cast(constructor);
7180 
7181   // If function should not have prototype, construction is not allowed. In this
7182   // case generated code bailouts here, since function has no initial_map.
7183   if (!function->should_have_prototype()) {
7184     Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
7185     Handle<Object> type_error =
7186         isolate->factory()->NewTypeError("not_constructor", arguments);
7187     return isolate->Throw(*type_error);
7188   }
7189 
7190 #ifdef ENABLE_DEBUGGER_SUPPORT
7191   Debug* debug = isolate->debug();
7192   // Handle stepping into constructors if step into is active.
7193   if (debug->StepInActive()) {
7194     debug->HandleStepIn(function, Handle<Object>::null(), 0, true);
7195   }
7196 #endif
7197 
7198   if (function->has_initial_map()) {
7199     if (function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
7200       // The 'Function' function ignores the receiver object when
7201       // called using 'new' and creates a new JSFunction object that
7202       // is returned.  The receiver object is only used for error
7203       // reporting if an error occurs when constructing the new
7204       // JSFunction. FACTORY->NewJSObject() should not be used to
7205       // allocate JSFunctions since it does not properly initialize
7206       // the shared part of the function. Since the receiver is
7207       // ignored anyway, we use the global object as the receiver
7208       // instead of a new JSFunction object. This way, errors are
7209       // reported the same way whether or not 'Function' is called
7210       // using 'new'.
7211       return isolate->context()->global();
7212     }
7213   }
7214 
7215   // The function should be compiled for the optimization hints to be
7216   // available. We cannot use EnsureCompiled because that forces a
7217   // compilation through the shared function info which makes it
7218   // impossible for us to optimize.
7219   Handle<SharedFunctionInfo> shared(function->shared(), isolate);
7220   if (!function->is_compiled()) CompileLazy(function, CLEAR_EXCEPTION);
7221 
7222   if (!function->has_initial_map() &&
7223       shared->IsInobjectSlackTrackingInProgress()) {
7224     // The tracking is already in progress for another function. We can only
7225     // track one initial_map at a time, so we force the completion before the
7226     // function is called as a constructor for the first time.
7227     shared->CompleteInobjectSlackTracking();
7228   }
7229 
7230   bool first_allocation = !shared->live_objects_may_exist();
7231   Handle<JSObject> result = isolate->factory()->NewJSObject(function);
7232   RETURN_IF_EMPTY_HANDLE(isolate, result);
7233   // Delay setting the stub if inobject slack tracking is in progress.
7234   if (first_allocation && !shared->IsInobjectSlackTrackingInProgress()) {
7235     TrySettingInlineConstructStub(isolate, function);
7236   }
7237 
7238   isolate->counters()->constructed_objects()->Increment();
7239   isolate->counters()->constructed_objects_runtime()->Increment();
7240 
7241   return *result;
7242 }
7243 
7244 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FinalizeInstanceSize)7245 RUNTIME_FUNCTION(MaybeObject*, Runtime_FinalizeInstanceSize) {
7246   HandleScope scope(isolate);
7247   ASSERT(args.length() == 1);
7248 
7249   CONVERT_ARG_CHECKED(JSFunction, function, 0);
7250   function->shared()->CompleteInobjectSlackTracking();
7251   TrySettingInlineConstructStub(isolate, function);
7252 
7253   return isolate->heap()->undefined_value();
7254 }
7255 
7256 
RUNTIME_FUNCTION(MaybeObject *,Runtime_LazyCompile)7257 RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyCompile) {
7258   HandleScope scope(isolate);
7259   ASSERT(args.length() == 1);
7260 
7261   Handle<JSFunction> function = args.at<JSFunction>(0);
7262 #ifdef DEBUG
7263   if (FLAG_trace_lazy && !function->shared()->is_compiled()) {
7264     PrintF("[lazy: ");
7265     function->PrintName();
7266     PrintF("]\n");
7267   }
7268 #endif
7269 
7270   // Compile the target function.  Here we compile using CompileLazyInLoop in
7271   // order to get the optimized version.  This helps code like delta-blue
7272   // that calls performance-critical routines through constructors.  A
7273   // constructor call doesn't use a CallIC, it uses a LoadIC followed by a
7274   // direct call.  Since the in-loop tracking takes place through CallICs
7275   // this means that things called through constructors are never known to
7276   // be in loops.  We compile them as if they are in loops here just in case.
7277   ASSERT(!function->is_compiled());
7278   if (!CompileLazyInLoop(function, KEEP_EXCEPTION)) {
7279     return Failure::Exception();
7280   }
7281 
7282   // All done. Return the compiled code.
7283   ASSERT(function->is_compiled());
7284   return function->code();
7285 }
7286 
7287 
RUNTIME_FUNCTION(MaybeObject *,Runtime_LazyRecompile)7288 RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyRecompile) {
7289   HandleScope scope(isolate);
7290   ASSERT(args.length() == 1);
7291   Handle<JSFunction> function = args.at<JSFunction>(0);
7292   // If the function is not optimizable or debugger is active continue using the
7293   // code from the full compiler.
7294   if (!function->shared()->code()->optimizable() ||
7295       isolate->debug()->has_break_points()) {
7296     if (FLAG_trace_opt) {
7297       PrintF("[failed to optimize ");
7298       function->PrintName();
7299       PrintF(": is code optimizable: %s, is debugger enabled: %s]\n",
7300           function->shared()->code()->optimizable() ? "T" : "F",
7301           isolate->debug()->has_break_points() ? "T" : "F");
7302     }
7303     function->ReplaceCode(function->shared()->code());
7304     return function->code();
7305   }
7306   if (CompileOptimized(function, AstNode::kNoNumber, CLEAR_EXCEPTION)) {
7307     return function->code();
7308   }
7309   if (FLAG_trace_opt) {
7310     PrintF("[failed to optimize ");
7311     function->PrintName();
7312     PrintF(": optimized compilation failed]\n");
7313   }
7314   function->ReplaceCode(function->shared()->code());
7315   return function->code();
7316 }
7317 
7318 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NotifyDeoptimized)7319 RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyDeoptimized) {
7320   HandleScope scope(isolate);
7321   ASSERT(args.length() == 1);
7322   RUNTIME_ASSERT(args[0]->IsSmi());
7323   Deoptimizer::BailoutType type =
7324       static_cast<Deoptimizer::BailoutType>(Smi::cast(args[0])->value());
7325   Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
7326   ASSERT(isolate->heap()->IsAllocationAllowed());
7327   int frames = deoptimizer->output_count();
7328 
7329   deoptimizer->MaterializeHeapNumbers();
7330   delete deoptimizer;
7331 
7332   JavaScriptFrameIterator it(isolate);
7333   JavaScriptFrame* frame = NULL;
7334   for (int i = 0; i < frames - 1; i++) it.Advance();
7335   frame = it.frame();
7336 
7337   RUNTIME_ASSERT(frame->function()->IsJSFunction());
7338   Handle<JSFunction> function(JSFunction::cast(frame->function()), isolate);
7339   Handle<Object> arguments;
7340   for (int i = frame->ComputeExpressionsCount() - 1; i >= 0; --i) {
7341     if (frame->GetExpression(i) == isolate->heap()->arguments_marker()) {
7342       if (arguments.is_null()) {
7343         // FunctionGetArguments can't throw an exception, so cast away the
7344         // doubt with an assert.
7345         arguments = Handle<Object>(
7346             Accessors::FunctionGetArguments(*function,
7347                                             NULL)->ToObjectUnchecked());
7348         ASSERT(*arguments != isolate->heap()->null_value());
7349         ASSERT(*arguments != isolate->heap()->undefined_value());
7350       }
7351       frame->SetExpression(i, *arguments);
7352     }
7353   }
7354 
7355   isolate->compilation_cache()->MarkForLazyOptimizing(function);
7356   if (type == Deoptimizer::EAGER) {
7357     RUNTIME_ASSERT(function->IsOptimized());
7358   } else {
7359     RUNTIME_ASSERT(!function->IsOptimized());
7360   }
7361 
7362   // Avoid doing too much work when running with --always-opt and keep
7363   // the optimized code around.
7364   if (FLAG_always_opt || type == Deoptimizer::LAZY) {
7365     return isolate->heap()->undefined_value();
7366   }
7367 
7368   // Count the number of optimized activations of the function.
7369   int activations = 0;
7370   while (!it.done()) {
7371     JavaScriptFrame* frame = it.frame();
7372     if (frame->is_optimized() && frame->function() == *function) {
7373       activations++;
7374     }
7375     it.Advance();
7376   }
7377 
7378   // TODO(kasperl): For now, we cannot support removing the optimized
7379   // code when we have recursive invocations of the same function.
7380   if (activations == 0) {
7381     if (FLAG_trace_deopt) {
7382       PrintF("[removing optimized code for: ");
7383       function->PrintName();
7384       PrintF("]\n");
7385     }
7386     function->ReplaceCode(function->shared()->code());
7387   }
7388   return isolate->heap()->undefined_value();
7389 }
7390 
7391 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NotifyOSR)7392 RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyOSR) {
7393   Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
7394   delete deoptimizer;
7395   return isolate->heap()->undefined_value();
7396 }
7397 
7398 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DeoptimizeFunction)7399 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeoptimizeFunction) {
7400   HandleScope scope(isolate);
7401   ASSERT(args.length() == 1);
7402   CONVERT_ARG_CHECKED(JSFunction, function, 0);
7403   if (!function->IsOptimized()) return isolate->heap()->undefined_value();
7404 
7405   Deoptimizer::DeoptimizeFunction(*function);
7406 
7407   return isolate->heap()->undefined_value();
7408 }
7409 
7410 
RUNTIME_FUNCTION(MaybeObject *,Runtime_OptimizeFunctionOnNextCall)7411 RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) {
7412   HandleScope scope(isolate);
7413   ASSERT(args.length() == 1);
7414   CONVERT_ARG_CHECKED(JSFunction, function, 0);
7415   if (!function->IsOptimizable()) return isolate->heap()->undefined_value();
7416   function->MarkForLazyRecompilation();
7417   return isolate->heap()->undefined_value();
7418 }
7419 
7420 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CompileForOnStackReplacement)7421 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
7422   HandleScope scope(isolate);
7423   ASSERT(args.length() == 1);
7424   CONVERT_ARG_CHECKED(JSFunction, function, 0);
7425 
7426   // We're not prepared to handle a function with arguments object.
7427   ASSERT(!function->shared()->scope_info()->HasArgumentsShadow());
7428 
7429   // We have hit a back edge in an unoptimized frame for a function that was
7430   // selected for on-stack replacement.  Find the unoptimized code object.
7431   Handle<Code> unoptimized(function->shared()->code(), isolate);
7432   // Keep track of whether we've succeeded in optimizing.
7433   bool succeeded = unoptimized->optimizable();
7434   if (succeeded) {
7435     // If we are trying to do OSR when there are already optimized
7436     // activations of the function, it means (a) the function is directly or
7437     // indirectly recursive and (b) an optimized invocation has been
7438     // deoptimized so that we are currently in an unoptimized activation.
7439     // Check for optimized activations of this function.
7440     JavaScriptFrameIterator it(isolate);
7441     while (succeeded && !it.done()) {
7442       JavaScriptFrame* frame = it.frame();
7443       succeeded = !frame->is_optimized() || frame->function() != *function;
7444       it.Advance();
7445     }
7446   }
7447 
7448   int ast_id = AstNode::kNoNumber;
7449   if (succeeded) {
7450     // The top JS function is this one, the PC is somewhere in the
7451     // unoptimized code.
7452     JavaScriptFrameIterator it(isolate);
7453     JavaScriptFrame* frame = it.frame();
7454     ASSERT(frame->function() == *function);
7455     ASSERT(frame->LookupCode() == *unoptimized);
7456     ASSERT(unoptimized->contains(frame->pc()));
7457 
7458     // Use linear search of the unoptimized code's stack check table to find
7459     // the AST id matching the PC.
7460     Address start = unoptimized->instruction_start();
7461     unsigned target_pc_offset = static_cast<unsigned>(frame->pc() - start);
7462     Address table_cursor = start + unoptimized->stack_check_table_offset();
7463     uint32_t table_length = Memory::uint32_at(table_cursor);
7464     table_cursor += kIntSize;
7465     for (unsigned i = 0; i < table_length; ++i) {
7466       // Table entries are (AST id, pc offset) pairs.
7467       uint32_t pc_offset = Memory::uint32_at(table_cursor + kIntSize);
7468       if (pc_offset == target_pc_offset) {
7469         ast_id = static_cast<int>(Memory::uint32_at(table_cursor));
7470         break;
7471       }
7472       table_cursor += 2 * kIntSize;
7473     }
7474     ASSERT(ast_id != AstNode::kNoNumber);
7475     if (FLAG_trace_osr) {
7476       PrintF("[replacing on-stack at AST id %d in ", ast_id);
7477       function->PrintName();
7478       PrintF("]\n");
7479     }
7480 
7481     // Try to compile the optimized code.  A true return value from
7482     // CompileOptimized means that compilation succeeded, not necessarily
7483     // that optimization succeeded.
7484     if (CompileOptimized(function, ast_id, CLEAR_EXCEPTION) &&
7485         function->IsOptimized()) {
7486       DeoptimizationInputData* data = DeoptimizationInputData::cast(
7487           function->code()->deoptimization_data());
7488       if (data->OsrPcOffset()->value() >= 0) {
7489         if (FLAG_trace_osr) {
7490           PrintF("[on-stack replacement offset %d in optimized code]\n",
7491                data->OsrPcOffset()->value());
7492         }
7493         ASSERT(data->OsrAstId()->value() == ast_id);
7494       } else {
7495         // We may never generate the desired OSR entry if we emit an
7496         // early deoptimize.
7497         succeeded = false;
7498       }
7499     } else {
7500       succeeded = false;
7501     }
7502   }
7503 
7504   // Revert to the original stack checks in the original unoptimized code.
7505   if (FLAG_trace_osr) {
7506     PrintF("[restoring original stack checks in ");
7507     function->PrintName();
7508     PrintF("]\n");
7509   }
7510   StackCheckStub check_stub;
7511   Handle<Code> check_code = check_stub.GetCode();
7512   Handle<Code> replacement_code = isolate->builtins()->OnStackReplacement();
7513   Deoptimizer::RevertStackCheckCode(*unoptimized,
7514                                     *check_code,
7515                                     *replacement_code);
7516 
7517   // Allow OSR only at nesting level zero again.
7518   unoptimized->set_allow_osr_at_loop_nesting_level(0);
7519 
7520   // If the optimization attempt succeeded, return the AST id tagged as a
7521   // smi. This tells the builtin that we need to translate the unoptimized
7522   // frame to an optimized one.
7523   if (succeeded) {
7524     ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION);
7525     return Smi::FromInt(ast_id);
7526   } else {
7527     if (function->IsMarkedForLazyRecompilation()) {
7528       function->ReplaceCode(function->shared()->code());
7529     }
7530     return Smi::FromInt(-1);
7531   }
7532 }
7533 
7534 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetFunctionDelegate)7535 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionDelegate) {
7536   HandleScope scope(isolate);
7537   ASSERT(args.length() == 1);
7538   RUNTIME_ASSERT(!args[0]->IsJSFunction());
7539   return *Execution::GetFunctionDelegate(args.at<Object>(0));
7540 }
7541 
7542 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetConstructorDelegate)7543 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) {
7544   HandleScope scope(isolate);
7545   ASSERT(args.length() == 1);
7546   RUNTIME_ASSERT(!args[0]->IsJSFunction());
7547   return *Execution::GetConstructorDelegate(args.at<Object>(0));
7548 }
7549 
7550 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewContext)7551 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewContext) {
7552   NoHandleAllocation ha;
7553   ASSERT(args.length() == 1);
7554 
7555   CONVERT_CHECKED(JSFunction, function, args[0]);
7556   int length = function->shared()->scope_info()->NumberOfContextSlots();
7557   Object* result;
7558   { MaybeObject* maybe_result =
7559         isolate->heap()->AllocateFunctionContext(length, function);
7560     if (!maybe_result->ToObject(&result)) return maybe_result;
7561   }
7562 
7563   isolate->set_context(Context::cast(result));
7564 
7565   return result;  // non-failure
7566 }
7567 
7568 
PushContextHelper(Isolate * isolate,Object * object,bool is_catch_context)7569 MUST_USE_RESULT static MaybeObject* PushContextHelper(Isolate* isolate,
7570                                                       Object* object,
7571                                                       bool is_catch_context) {
7572   // Convert the object to a proper JavaScript object.
7573   Object* js_object = object;
7574   if (!js_object->IsJSObject()) {
7575     MaybeObject* maybe_js_object = js_object->ToObject();
7576     if (!maybe_js_object->ToObject(&js_object)) {
7577       if (!Failure::cast(maybe_js_object)->IsInternalError()) {
7578         return maybe_js_object;
7579       }
7580       HandleScope scope(isolate);
7581       Handle<Object> handle(object, isolate);
7582       Handle<Object> result =
7583           isolate->factory()->NewTypeError("with_expression",
7584                                            HandleVector(&handle, 1));
7585       return isolate->Throw(*result);
7586     }
7587   }
7588 
7589   Object* result;
7590   { MaybeObject* maybe_result = isolate->heap()->AllocateWithContext(
7591       isolate->context(), JSObject::cast(js_object), is_catch_context);
7592     if (!maybe_result->ToObject(&result)) return maybe_result;
7593   }
7594 
7595   Context* context = Context::cast(result);
7596   isolate->set_context(context);
7597 
7598   return result;
7599 }
7600 
7601 
RUNTIME_FUNCTION(MaybeObject *,Runtime_PushContext)7602 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushContext) {
7603   NoHandleAllocation ha;
7604   ASSERT(args.length() == 1);
7605   return PushContextHelper(isolate, args[0], false);
7606 }
7607 
7608 
RUNTIME_FUNCTION(MaybeObject *,Runtime_PushCatchContext)7609 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushCatchContext) {
7610   NoHandleAllocation ha;
7611   ASSERT(args.length() == 1);
7612   return PushContextHelper(isolate, args[0], true);
7613 }
7614 
7615 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DeleteContextSlot)7616 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteContextSlot) {
7617   HandleScope scope(isolate);
7618   ASSERT(args.length() == 2);
7619 
7620   CONVERT_ARG_CHECKED(Context, context, 0);
7621   CONVERT_ARG_CHECKED(String, name, 1);
7622 
7623   int index;
7624   PropertyAttributes attributes;
7625   ContextLookupFlags flags = FOLLOW_CHAINS;
7626   Handle<Object> holder = context->Lookup(name, flags, &index, &attributes);
7627 
7628   // If the slot was not found the result is true.
7629   if (holder.is_null()) {
7630     return isolate->heap()->true_value();
7631   }
7632 
7633   // If the slot was found in a context, it should be DONT_DELETE.
7634   if (holder->IsContext()) {
7635     return isolate->heap()->false_value();
7636   }
7637 
7638   // The slot was found in a JSObject, either a context extension object,
7639   // the global object, or an arguments object.  Try to delete it
7640   // (respecting DONT_DELETE).  For consistency with V8's usual behavior,
7641   // which allows deleting all parameters in functions that mention
7642   // 'arguments', we do this even for the case of slots found on an
7643   // arguments object.  The slot was found on an arguments object if the
7644   // index is non-negative.
7645   Handle<JSObject> object = Handle<JSObject>::cast(holder);
7646   if (index >= 0) {
7647     return object->DeleteElement(index, JSObject::NORMAL_DELETION);
7648   } else {
7649     return object->DeleteProperty(*name, JSObject::NORMAL_DELETION);
7650   }
7651 }
7652 
7653 
7654 // A mechanism to return a pair of Object pointers in registers (if possible).
7655 // How this is achieved is calling convention-dependent.
7656 // All currently supported x86 compiles uses calling conventions that are cdecl
7657 // variants where a 64-bit value is returned in two 32-bit registers
7658 // (edx:eax on ia32, r1:r0 on ARM).
7659 // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax.
7660 // In Win64 calling convention, a struct of two pointers is returned in memory,
7661 // allocated by the caller, and passed as a pointer in a hidden first parameter.
7662 #ifdef V8_HOST_ARCH_64_BIT
7663 struct ObjectPair {
7664   MaybeObject* x;
7665   MaybeObject* y;
7666 };
7667 
MakePair(MaybeObject * x,MaybeObject * y)7668 static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
7669   ObjectPair result = {x, y};
7670   // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
7671   // In Win64 they are assigned to a hidden first argument.
7672   return result;
7673 }
7674 #else
7675 typedef uint64_t ObjectPair;
MakePair(MaybeObject * x,MaybeObject * y)7676 static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
7677   return reinterpret_cast<uint32_t>(x) |
7678       (reinterpret_cast<ObjectPair>(y) << 32);
7679 }
7680 #endif
7681 
7682 
Unhole(Heap * heap,MaybeObject * x,PropertyAttributes attributes)7683 static inline MaybeObject* Unhole(Heap* heap,
7684                                   MaybeObject* x,
7685                                   PropertyAttributes attributes) {
7686   ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
7687   USE(attributes);
7688   return x->IsTheHole() ? heap->undefined_value() : x;
7689 }
7690 
7691 
ComputeReceiverForNonGlobal(Isolate * isolate,JSObject * holder)7692 static JSObject* ComputeReceiverForNonGlobal(Isolate* isolate,
7693                                              JSObject* holder) {
7694   ASSERT(!holder->IsGlobalObject());
7695   Context* top = isolate->context();
7696   // Get the context extension function.
7697   JSFunction* context_extension_function =
7698       top->global_context()->context_extension_function();
7699   // If the holder isn't a context extension object, we just return it
7700   // as the receiver. This allows arguments objects to be used as
7701   // receivers, but only if they are put in the context scope chain
7702   // explicitly via a with-statement.
7703   Object* constructor = holder->map()->constructor();
7704   if (constructor != context_extension_function) return holder;
7705   // Fall back to using the global object as the receiver if the
7706   // property turns out to be a local variable allocated in a context
7707   // extension object - introduced via eval.
7708   return top->global()->global_receiver();
7709 }
7710 
7711 
LoadContextSlotHelper(Arguments args,Isolate * isolate,bool throw_error)7712 static ObjectPair LoadContextSlotHelper(Arguments args,
7713                                         Isolate* isolate,
7714                                         bool throw_error) {
7715   HandleScope scope(isolate);
7716   ASSERT_EQ(2, args.length());
7717 
7718   if (!args[0]->IsContext() || !args[1]->IsString()) {
7719     return MakePair(isolate->ThrowIllegalOperation(), NULL);
7720   }
7721   Handle<Context> context = args.at<Context>(0);
7722   Handle<String> name = args.at<String>(1);
7723 
7724   int index;
7725   PropertyAttributes attributes;
7726   ContextLookupFlags flags = FOLLOW_CHAINS;
7727   Handle<Object> holder = context->Lookup(name, flags, &index, &attributes);
7728 
7729   // If the index is non-negative, the slot has been found in a local
7730   // variable or a parameter. Read it from the context object or the
7731   // arguments object.
7732   if (index >= 0) {
7733     // If the "property" we were looking for is a local variable or an
7734     // argument in a context, the receiver is the global object; see
7735     // ECMA-262, 3rd., 10.1.6 and 10.2.3.
7736     JSObject* receiver =
7737         isolate->context()->global()->global_receiver();
7738     MaybeObject* value = (holder->IsContext())
7739         ? Context::cast(*holder)->get(index)
7740         : JSObject::cast(*holder)->GetElement(index);
7741     return MakePair(Unhole(isolate->heap(), value, attributes), receiver);
7742   }
7743 
7744   // If the holder is found, we read the property from it.
7745   if (!holder.is_null() && holder->IsJSObject()) {
7746     ASSERT(Handle<JSObject>::cast(holder)->HasProperty(*name));
7747     JSObject* object = JSObject::cast(*holder);
7748     JSObject* receiver;
7749     if (object->IsGlobalObject()) {
7750       receiver = GlobalObject::cast(object)->global_receiver();
7751     } else if (context->is_exception_holder(*holder)) {
7752       receiver = isolate->context()->global()->global_receiver();
7753     } else {
7754       receiver = ComputeReceiverForNonGlobal(isolate, object);
7755     }
7756     // No need to unhole the value here. This is taken care of by the
7757     // GetProperty function.
7758     MaybeObject* value = object->GetProperty(*name);
7759     return MakePair(value, receiver);
7760   }
7761 
7762   if (throw_error) {
7763     // The property doesn't exist - throw exception.
7764     Handle<Object> reference_error =
7765         isolate->factory()->NewReferenceError("not_defined",
7766                                               HandleVector(&name, 1));
7767     return MakePair(isolate->Throw(*reference_error), NULL);
7768   } else {
7769     // The property doesn't exist - return undefined
7770     return MakePair(isolate->heap()->undefined_value(),
7771                     isolate->heap()->undefined_value());
7772   }
7773 }
7774 
7775 
RUNTIME_FUNCTION(ObjectPair,Runtime_LoadContextSlot)7776 RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlot) {
7777   return LoadContextSlotHelper(args, isolate, true);
7778 }
7779 
7780 
RUNTIME_FUNCTION(ObjectPair,Runtime_LoadContextSlotNoReferenceError)7781 RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlotNoReferenceError) {
7782   return LoadContextSlotHelper(args, isolate, false);
7783 }
7784 
7785 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StoreContextSlot)7786 RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreContextSlot) {
7787   HandleScope scope(isolate);
7788   ASSERT(args.length() == 4);
7789 
7790   Handle<Object> value(args[0], isolate);
7791   CONVERT_ARG_CHECKED(Context, context, 1);
7792   CONVERT_ARG_CHECKED(String, name, 2);
7793   CONVERT_SMI_CHECKED(strict_unchecked, args[3]);
7794   RUNTIME_ASSERT(strict_unchecked == kStrictMode ||
7795                  strict_unchecked == kNonStrictMode);
7796   StrictModeFlag strict_mode = static_cast<StrictModeFlag>(strict_unchecked);
7797 
7798   int index;
7799   PropertyAttributes attributes;
7800   ContextLookupFlags flags = FOLLOW_CHAINS;
7801   Handle<Object> holder = context->Lookup(name, flags, &index, &attributes);
7802 
7803   if (index >= 0) {
7804     if (holder->IsContext()) {
7805       // Ignore if read_only variable.
7806       if ((attributes & READ_ONLY) == 0) {
7807         // Context is a fixed array and set cannot fail.
7808         Context::cast(*holder)->set(index, *value);
7809       } else if (strict_mode == kStrictMode) {
7810         // Setting read only property in strict mode.
7811         Handle<Object> error =
7812             isolate->factory()->NewTypeError("strict_cannot_assign",
7813                                              HandleVector(&name, 1));
7814         return isolate->Throw(*error);
7815       }
7816     } else {
7817       ASSERT((attributes & READ_ONLY) == 0);
7818       Handle<Object> result =
7819           SetElement(Handle<JSObject>::cast(holder), index, value, strict_mode);
7820       if (result.is_null()) {
7821         ASSERT(isolate->has_pending_exception());
7822         return Failure::Exception();
7823       }
7824     }
7825     return *value;
7826   }
7827 
7828   // Slow case: The property is not in a FixedArray context.
7829   // It is either in an JSObject extension context or it was not found.
7830   Handle<JSObject> context_ext;
7831 
7832   if (!holder.is_null()) {
7833     // The property exists in the extension context.
7834     context_ext = Handle<JSObject>::cast(holder);
7835   } else {
7836     // The property was not found.
7837     ASSERT(attributes == ABSENT);
7838 
7839     if (strict_mode == kStrictMode) {
7840       // Throw in strict mode (assignment to undefined variable).
7841       Handle<Object> error =
7842         isolate->factory()->NewReferenceError(
7843             "not_defined", HandleVector(&name, 1));
7844       return isolate->Throw(*error);
7845     }
7846     // In non-strict mode, the property is stored in the global context.
7847     attributes = NONE;
7848     context_ext = Handle<JSObject>(isolate->context()->global());
7849   }
7850 
7851   // Set the property, but ignore if read_only variable on the context
7852   // extension object itself.
7853   if ((attributes & READ_ONLY) == 0 ||
7854       (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) {
7855     RETURN_IF_EMPTY_HANDLE(
7856         isolate,
7857         SetProperty(context_ext, name, value, NONE, strict_mode));
7858   } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) {
7859     // Setting read only property in strict mode.
7860     Handle<Object> error =
7861       isolate->factory()->NewTypeError(
7862           "strict_cannot_assign", HandleVector(&name, 1));
7863     return isolate->Throw(*error);
7864   }
7865   return *value;
7866 }
7867 
7868 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Throw)7869 RUNTIME_FUNCTION(MaybeObject*, Runtime_Throw) {
7870   HandleScope scope(isolate);
7871   ASSERT(args.length() == 1);
7872 
7873   return isolate->Throw(args[0]);
7874 }
7875 
7876 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ReThrow)7877 RUNTIME_FUNCTION(MaybeObject*, Runtime_ReThrow) {
7878   HandleScope scope(isolate);
7879   ASSERT(args.length() == 1);
7880 
7881   return isolate->ReThrow(args[0]);
7882 }
7883 
7884 
RUNTIME_FUNCTION(MaybeObject *,Runtime_PromoteScheduledException)7885 RUNTIME_FUNCTION(MaybeObject*, Runtime_PromoteScheduledException) {
7886   ASSERT_EQ(0, args.length());
7887   return isolate->PromoteScheduledException();
7888 }
7889 
7890 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ThrowReferenceError)7891 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowReferenceError) {
7892   HandleScope scope(isolate);
7893   ASSERT(args.length() == 1);
7894 
7895   Handle<Object> name(args[0], isolate);
7896   Handle<Object> reference_error =
7897     isolate->factory()->NewReferenceError("not_defined",
7898                                           HandleVector(&name, 1));
7899   return isolate->Throw(*reference_error);
7900 }
7901 
7902 
RUNTIME_FUNCTION(MaybeObject *,Runtime_StackGuard)7903 RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) {
7904   ASSERT(args.length() == 0);
7905 
7906   // First check if this is a real stack overflow.
7907   if (isolate->stack_guard()->IsStackOverflow()) {
7908     NoHandleAllocation na;
7909     return isolate->StackOverflow();
7910   }
7911 
7912   return Execution::HandleStackGuardInterrupt();
7913 }
7914 
7915 
7916 // NOTE: These PrintXXX functions are defined for all builds (not just
7917 // DEBUG builds) because we may want to be able to trace function
7918 // calls in all modes.
PrintString(String * str)7919 static void PrintString(String* str) {
7920   // not uncommon to have empty strings
7921   if (str->length() > 0) {
7922     SmartPointer<char> s =
7923         str->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
7924     PrintF("%s", *s);
7925   }
7926 }
7927 
7928 
PrintObject(Object * obj)7929 static void PrintObject(Object* obj) {
7930   if (obj->IsSmi()) {
7931     PrintF("%d", Smi::cast(obj)->value());
7932   } else if (obj->IsString() || obj->IsSymbol()) {
7933     PrintString(String::cast(obj));
7934   } else if (obj->IsNumber()) {
7935     PrintF("%g", obj->Number());
7936   } else if (obj->IsFailure()) {
7937     PrintF("<failure>");
7938   } else if (obj->IsUndefined()) {
7939     PrintF("<undefined>");
7940   } else if (obj->IsNull()) {
7941     PrintF("<null>");
7942   } else if (obj->IsTrue()) {
7943     PrintF("<true>");
7944   } else if (obj->IsFalse()) {
7945     PrintF("<false>");
7946   } else {
7947     PrintF("%p", reinterpret_cast<void*>(obj));
7948   }
7949 }
7950 
7951 
StackSize()7952 static int StackSize() {
7953   int n = 0;
7954   for (JavaScriptFrameIterator it; !it.done(); it.Advance()) n++;
7955   return n;
7956 }
7957 
7958 
PrintTransition(Object * result)7959 static void PrintTransition(Object* result) {
7960   // indentation
7961   { const int nmax = 80;
7962     int n = StackSize();
7963     if (n <= nmax)
7964       PrintF("%4d:%*s", n, n, "");
7965     else
7966       PrintF("%4d:%*s", n, nmax, "...");
7967   }
7968 
7969   if (result == NULL) {
7970     // constructor calls
7971     JavaScriptFrameIterator it;
7972     JavaScriptFrame* frame = it.frame();
7973     if (frame->IsConstructor()) PrintF("new ");
7974     // function name
7975     Object* fun = frame->function();
7976     if (fun->IsJSFunction()) {
7977       PrintObject(JSFunction::cast(fun)->shared()->name());
7978     } else {
7979       PrintObject(fun);
7980     }
7981     // function arguments
7982     // (we are intentionally only printing the actually
7983     // supplied parameters, not all parameters required)
7984     PrintF("(this=");
7985     PrintObject(frame->receiver());
7986     const int length = frame->ComputeParametersCount();
7987     for (int i = 0; i < length; i++) {
7988       PrintF(", ");
7989       PrintObject(frame->GetParameter(i));
7990     }
7991     PrintF(") {\n");
7992 
7993   } else {
7994     // function result
7995     PrintF("} -> ");
7996     PrintObject(result);
7997     PrintF("\n");
7998   }
7999 }
8000 
8001 
RUNTIME_FUNCTION(MaybeObject *,Runtime_TraceEnter)8002 RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceEnter) {
8003   ASSERT(args.length() == 0);
8004   NoHandleAllocation ha;
8005   PrintTransition(NULL);
8006   return isolate->heap()->undefined_value();
8007 }
8008 
8009 
RUNTIME_FUNCTION(MaybeObject *,Runtime_TraceExit)8010 RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceExit) {
8011   NoHandleAllocation ha;
8012   PrintTransition(args[0]);
8013   return args[0];  // return TOS
8014 }
8015 
8016 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugPrint)8017 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrint) {
8018   NoHandleAllocation ha;
8019   ASSERT(args.length() == 1);
8020 
8021 #ifdef DEBUG
8022   if (args[0]->IsString()) {
8023     // If we have a string, assume it's a code "marker"
8024     // and print some interesting cpu debugging info.
8025     JavaScriptFrameIterator it(isolate);
8026     JavaScriptFrame* frame = it.frame();
8027     PrintF("fp = %p, sp = %p, caller_sp = %p: ",
8028            frame->fp(), frame->sp(), frame->caller_sp());
8029   } else {
8030     PrintF("DebugPrint: ");
8031   }
8032   args[0]->Print();
8033   if (args[0]->IsHeapObject()) {
8034     PrintF("\n");
8035     HeapObject::cast(args[0])->map()->Print();
8036   }
8037 #else
8038   // ShortPrint is available in release mode. Print is not.
8039   args[0]->ShortPrint();
8040 #endif
8041   PrintF("\n");
8042   Flush();
8043 
8044   return args[0];  // return TOS
8045 }
8046 
8047 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugTrace)8048 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugTrace) {
8049   ASSERT(args.length() == 0);
8050   NoHandleAllocation ha;
8051   isolate->PrintStack();
8052   return isolate->heap()->undefined_value();
8053 }
8054 
8055 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DateCurrentTime)8056 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateCurrentTime) {
8057   NoHandleAllocation ha;
8058   ASSERT(args.length() == 0);
8059 
8060   // According to ECMA-262, section 15.9.1, page 117, the precision of
8061   // the number in a Date object representing a particular instant in
8062   // time is milliseconds. Therefore, we floor the result of getting
8063   // the OS time.
8064   double millis = floor(OS::TimeCurrentMillis());
8065   return isolate->heap()->NumberFromDouble(millis);
8066 }
8067 
8068 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DateParseString)8069 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateParseString) {
8070   HandleScope scope(isolate);
8071   ASSERT(args.length() == 2);
8072 
8073   CONVERT_ARG_CHECKED(String, str, 0);
8074   FlattenString(str);
8075 
8076   CONVERT_ARG_CHECKED(JSArray, output, 1);
8077   RUNTIME_ASSERT(output->HasFastElements());
8078 
8079   AssertNoAllocation no_allocation;
8080 
8081   FixedArray* output_array = FixedArray::cast(output->elements());
8082   RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
8083   bool result;
8084   if (str->IsAsciiRepresentation()) {
8085     result = DateParser::Parse(str->ToAsciiVector(),
8086                                output_array,
8087                                isolate->unicode_cache());
8088   } else {
8089     ASSERT(str->IsTwoByteRepresentation());
8090     result = DateParser::Parse(str->ToUC16Vector(),
8091                                output_array,
8092                                isolate->unicode_cache());
8093   }
8094 
8095   if (result) {
8096     return *output;
8097   } else {
8098     return isolate->heap()->null_value();
8099   }
8100 }
8101 
8102 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DateLocalTimezone)8103 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateLocalTimezone) {
8104   NoHandleAllocation ha;
8105   ASSERT(args.length() == 1);
8106 
8107   CONVERT_DOUBLE_CHECKED(x, args[0]);
8108   const char* zone = OS::LocalTimezone(x);
8109   return isolate->heap()->AllocateStringFromUtf8(CStrVector(zone));
8110 }
8111 
8112 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DateLocalTimeOffset)8113 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateLocalTimeOffset) {
8114   NoHandleAllocation ha;
8115   ASSERT(args.length() == 0);
8116 
8117   return isolate->heap()->NumberFromDouble(OS::LocalTimeOffset());
8118 }
8119 
8120 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DateDaylightSavingsOffset)8121 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateDaylightSavingsOffset) {
8122   NoHandleAllocation ha;
8123   ASSERT(args.length() == 1);
8124 
8125   CONVERT_DOUBLE_CHECKED(x, args[0]);
8126   return isolate->heap()->NumberFromDouble(OS::DaylightSavingsOffset(x));
8127 }
8128 
8129 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GlobalReceiver)8130 RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalReceiver) {
8131   ASSERT(args.length() == 1);
8132   Object* global = args[0];
8133   if (!global->IsJSGlobalObject()) return isolate->heap()->null_value();
8134   return JSGlobalObject::cast(global)->global_receiver();
8135 }
8136 
8137 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ParseJson)8138 RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) {
8139   HandleScope scope(isolate);
8140   ASSERT_EQ(1, args.length());
8141   CONVERT_ARG_CHECKED(String, source, 0);
8142 
8143   Handle<Object> result = JsonParser::Parse(source);
8144   if (result.is_null()) {
8145     // Syntax error or stack overflow in scanner.
8146     ASSERT(isolate->has_pending_exception());
8147     return Failure::Exception();
8148   }
8149   return *result;
8150 }
8151 
8152 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CompileString)8153 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
8154   HandleScope scope(isolate);
8155   ASSERT_EQ(1, args.length());
8156   CONVERT_ARG_CHECKED(String, source, 0);
8157 
8158   // Compile source string in the global context.
8159   Handle<Context> context(isolate->context()->global_context());
8160   Handle<SharedFunctionInfo> shared = Compiler::CompileEval(source,
8161                                                             context,
8162                                                             true,
8163                                                             kNonStrictMode);
8164   if (shared.is_null()) return Failure::Exception();
8165   Handle<JSFunction> fun =
8166       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
8167                                                             context,
8168                                                             NOT_TENURED);
8169   return *fun;
8170 }
8171 
8172 
CompileGlobalEval(Isolate * isolate,Handle<String> source,Handle<Object> receiver,StrictModeFlag strict_mode)8173 static ObjectPair CompileGlobalEval(Isolate* isolate,
8174                                     Handle<String> source,
8175                                     Handle<Object> receiver,
8176                                     StrictModeFlag strict_mode) {
8177   // Deal with a normal eval call with a string argument. Compile it
8178   // and return the compiled function bound in the local context.
8179   Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
8180       source,
8181       Handle<Context>(isolate->context()),
8182       isolate->context()->IsGlobalContext(),
8183       strict_mode);
8184   if (shared.is_null()) return MakePair(Failure::Exception(), NULL);
8185   Handle<JSFunction> compiled =
8186       isolate->factory()->NewFunctionFromSharedFunctionInfo(
8187           shared, Handle<Context>(isolate->context()), NOT_TENURED);
8188   return MakePair(*compiled, *receiver);
8189 }
8190 
8191 
RUNTIME_FUNCTION(ObjectPair,Runtime_ResolvePossiblyDirectEval)8192 RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
8193   ASSERT(args.length() == 4);
8194 
8195   HandleScope scope(isolate);
8196   Handle<Object> callee = args.at<Object>(0);
8197   Handle<Object> receiver;  // Will be overwritten.
8198 
8199   // Compute the calling context.
8200   Handle<Context> context = Handle<Context>(isolate->context(), isolate);
8201 #ifdef DEBUG
8202   // Make sure Isolate::context() agrees with the old code that traversed
8203   // the stack frames to compute the context.
8204   StackFrameLocator locator;
8205   JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
8206   ASSERT(Context::cast(frame->context()) == *context);
8207 #endif
8208 
8209   // Find where the 'eval' symbol is bound. It is unaliased only if
8210   // it is bound in the global context.
8211   int index = -1;
8212   PropertyAttributes attributes = ABSENT;
8213   while (true) {
8214     receiver = context->Lookup(isolate->factory()->eval_symbol(),
8215                                FOLLOW_PROTOTYPE_CHAIN,
8216                                &index, &attributes);
8217     // Stop search when eval is found or when the global context is
8218     // reached.
8219     if (attributes != ABSENT || context->IsGlobalContext()) break;
8220     if (context->is_function_context()) {
8221       context = Handle<Context>(Context::cast(context->closure()->context()),
8222                                 isolate);
8223     } else {
8224       context = Handle<Context>(context->previous(), isolate);
8225     }
8226   }
8227 
8228   // If eval could not be resolved, it has been deleted and we need to
8229   // throw a reference error.
8230   if (attributes == ABSENT) {
8231     Handle<Object> name = isolate->factory()->eval_symbol();
8232     Handle<Object> reference_error =
8233         isolate->factory()->NewReferenceError("not_defined",
8234                                               HandleVector(&name, 1));
8235     return MakePair(isolate->Throw(*reference_error), NULL);
8236   }
8237 
8238   if (!context->IsGlobalContext()) {
8239     // 'eval' is not bound in the global context. Just call the function
8240     // with the given arguments. This is not necessarily the global eval.
8241     if (receiver->IsContext()) {
8242       context = Handle<Context>::cast(receiver);
8243       receiver = Handle<Object>(context->get(index), isolate);
8244     } else if (receiver->IsJSContextExtensionObject()) {
8245       receiver = Handle<JSObject>(
8246           isolate->context()->global()->global_receiver(), isolate);
8247     }
8248     return MakePair(*callee, *receiver);
8249   }
8250 
8251   // 'eval' is bound in the global context, but it may have been overwritten.
8252   // Compare it to the builtin 'GlobalEval' function to make sure.
8253   if (*callee != isolate->global_context()->global_eval_fun() ||
8254       !args[1]->IsString()) {
8255     return MakePair(*callee,
8256                     isolate->context()->global()->global_receiver());
8257   }
8258 
8259   ASSERT(args[3]->IsSmi());
8260   return CompileGlobalEval(isolate,
8261                            args.at<String>(1),
8262                            args.at<Object>(2),
8263                            static_cast<StrictModeFlag>(
8264                                 Smi::cast(args[3])->value()));
8265 }
8266 
8267 
RUNTIME_FUNCTION(ObjectPair,Runtime_ResolvePossiblyDirectEvalNoLookup)8268 RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEvalNoLookup) {
8269   ASSERT(args.length() == 4);
8270 
8271   HandleScope scope(isolate);
8272   Handle<Object> callee = args.at<Object>(0);
8273 
8274   // 'eval' is bound in the global context, but it may have been overwritten.
8275   // Compare it to the builtin 'GlobalEval' function to make sure.
8276   if (*callee != isolate->global_context()->global_eval_fun() ||
8277       !args[1]->IsString()) {
8278     return MakePair(*callee,
8279                     isolate->context()->global()->global_receiver());
8280   }
8281 
8282   ASSERT(args[3]->IsSmi());
8283   return CompileGlobalEval(isolate,
8284                            args.at<String>(1),
8285                            args.at<Object>(2),
8286                            static_cast<StrictModeFlag>(
8287                                 Smi::cast(args[3])->value()));
8288 }
8289 
8290 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetNewFunctionAttributes)8291 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNewFunctionAttributes) {
8292   // This utility adjusts the property attributes for newly created Function
8293   // object ("new Function(...)") by changing the map.
8294   // All it does is changing the prototype property to enumerable
8295   // as specified in ECMA262, 15.3.5.2.
8296   HandleScope scope(isolate);
8297   ASSERT(args.length() == 1);
8298   CONVERT_ARG_CHECKED(JSFunction, func, 0);
8299 
8300   Handle<Map> map = func->shared()->strict_mode()
8301                         ? isolate->strict_mode_function_instance_map()
8302                         : isolate->function_instance_map();
8303 
8304   ASSERT(func->map()->instance_type() == map->instance_type());
8305   ASSERT(func->map()->instance_size() == map->instance_size());
8306   func->set_map(*map);
8307   return *func;
8308 }
8309 
8310 
RUNTIME_FUNCTION(MaybeObject *,Runtime_AllocateInNewSpace)8311 RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInNewSpace) {
8312   // Allocate a block of memory in NewSpace (filled with a filler).
8313   // Use as fallback for allocation in generated code when NewSpace
8314   // is full.
8315   ASSERT(args.length() == 1);
8316   CONVERT_ARG_CHECKED(Smi, size_smi, 0);
8317   int size = size_smi->value();
8318   RUNTIME_ASSERT(IsAligned(size, kPointerSize));
8319   RUNTIME_ASSERT(size > 0);
8320   Heap* heap = isolate->heap();
8321   const int kMinFreeNewSpaceAfterGC = heap->InitialSemiSpaceSize() * 3/4;
8322   RUNTIME_ASSERT(size <= kMinFreeNewSpaceAfterGC);
8323   Object* allocation;
8324   { MaybeObject* maybe_allocation = heap->new_space()->AllocateRaw(size);
8325     if (maybe_allocation->ToObject(&allocation)) {
8326       heap->CreateFillerObjectAt(HeapObject::cast(allocation)->address(), size);
8327     }
8328     return maybe_allocation;
8329   }
8330 }
8331 
8332 
8333 // Push an object unto an array of objects if it is not already in the
8334 // array.  Returns true if the element was pushed on the stack and
8335 // false otherwise.
RUNTIME_FUNCTION(MaybeObject *,Runtime_PushIfAbsent)8336 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) {
8337   ASSERT(args.length() == 2);
8338   CONVERT_CHECKED(JSArray, array, args[0]);
8339   CONVERT_CHECKED(JSObject, element, args[1]);
8340   RUNTIME_ASSERT(array->HasFastElements());
8341   int length = Smi::cast(array->length())->value();
8342   FixedArray* elements = FixedArray::cast(array->elements());
8343   for (int i = 0; i < length; i++) {
8344     if (elements->get(i) == element) return isolate->heap()->false_value();
8345   }
8346   Object* obj;
8347   // Strict not needed. Used for cycle detection in Array join implementation.
8348   { MaybeObject* maybe_obj = array->SetFastElement(length, element,
8349                                                    kNonStrictMode);
8350     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
8351   }
8352   return isolate->heap()->true_value();
8353 }
8354 
8355 
8356 /**
8357  * A simple visitor visits every element of Array's.
8358  * The backend storage can be a fixed array for fast elements case,
8359  * or a dictionary for sparse array. Since Dictionary is a subtype
8360  * of FixedArray, the class can be used by both fast and slow cases.
8361  * The second parameter of the constructor, fast_elements, specifies
8362  * whether the storage is a FixedArray or Dictionary.
8363  *
8364  * An index limit is used to deal with the situation that a result array
8365  * length overflows 32-bit non-negative integer.
8366  */
8367 class ArrayConcatVisitor {
8368  public:
ArrayConcatVisitor(Isolate * isolate,Handle<FixedArray> storage,bool fast_elements)8369   ArrayConcatVisitor(Isolate* isolate,
8370                      Handle<FixedArray> storage,
8371                      bool fast_elements) :
8372       isolate_(isolate),
8373       storage_(Handle<FixedArray>::cast(
8374           isolate->global_handles()->Create(*storage))),
8375       index_offset_(0u),
8376       fast_elements_(fast_elements) { }
8377 
~ArrayConcatVisitor()8378   ~ArrayConcatVisitor() {
8379     clear_storage();
8380   }
8381 
visit(uint32_t i,Handle<Object> elm)8382   void visit(uint32_t i, Handle<Object> elm) {
8383     if (i >= JSObject::kMaxElementCount - index_offset_) return;
8384     uint32_t index = index_offset_ + i;
8385 
8386     if (fast_elements_) {
8387       if (index < static_cast<uint32_t>(storage_->length())) {
8388         storage_->set(index, *elm);
8389         return;
8390       }
8391       // Our initial estimate of length was foiled, possibly by
8392       // getters on the arrays increasing the length of later arrays
8393       // during iteration.
8394       // This shouldn't happen in anything but pathological cases.
8395       SetDictionaryMode(index);
8396       // Fall-through to dictionary mode.
8397     }
8398     ASSERT(!fast_elements_);
8399     Handle<NumberDictionary> dict(NumberDictionary::cast(*storage_));
8400     Handle<NumberDictionary> result =
8401         isolate_->factory()->DictionaryAtNumberPut(dict, index, elm);
8402     if (!result.is_identical_to(dict)) {
8403       // Dictionary needed to grow.
8404       clear_storage();
8405       set_storage(*result);
8406     }
8407 }
8408 
increase_index_offset(uint32_t delta)8409   void increase_index_offset(uint32_t delta) {
8410     if (JSObject::kMaxElementCount - index_offset_ < delta) {
8411       index_offset_ = JSObject::kMaxElementCount;
8412     } else {
8413       index_offset_ += delta;
8414     }
8415   }
8416 
ToArray()8417   Handle<JSArray> ToArray() {
8418     Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
8419     Handle<Object> length =
8420         isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
8421     Handle<Map> map;
8422     if (fast_elements_) {
8423       map = isolate_->factory()->GetFastElementsMap(Handle<Map>(array->map()));
8424     } else {
8425       map = isolate_->factory()->GetSlowElementsMap(Handle<Map>(array->map()));
8426     }
8427     array->set_map(*map);
8428     array->set_length(*length);
8429     array->set_elements(*storage_);
8430     return array;
8431   }
8432 
8433  private:
8434   // Convert storage to dictionary mode.
SetDictionaryMode(uint32_t index)8435   void SetDictionaryMode(uint32_t index) {
8436     ASSERT(fast_elements_);
8437     Handle<FixedArray> current_storage(*storage_);
8438     Handle<NumberDictionary> slow_storage(
8439         isolate_->factory()->NewNumberDictionary(current_storage->length()));
8440     uint32_t current_length = static_cast<uint32_t>(current_storage->length());
8441     for (uint32_t i = 0; i < current_length; i++) {
8442       HandleScope loop_scope;
8443       Handle<Object> element(current_storage->get(i));
8444       if (!element->IsTheHole()) {
8445         Handle<NumberDictionary> new_storage =
8446           isolate_->factory()->DictionaryAtNumberPut(slow_storage, i, element);
8447         if (!new_storage.is_identical_to(slow_storage)) {
8448           slow_storage = loop_scope.CloseAndEscape(new_storage);
8449         }
8450       }
8451     }
8452     clear_storage();
8453     set_storage(*slow_storage);
8454     fast_elements_ = false;
8455   }
8456 
clear_storage()8457   inline void clear_storage() {
8458     isolate_->global_handles()->Destroy(
8459         Handle<Object>::cast(storage_).location());
8460   }
8461 
set_storage(FixedArray * storage)8462   inline void set_storage(FixedArray* storage) {
8463     storage_ = Handle<FixedArray>::cast(
8464         isolate_->global_handles()->Create(storage));
8465   }
8466 
8467   Isolate* isolate_;
8468   Handle<FixedArray> storage_;  // Always a global handle.
8469   // Index after last seen index. Always less than or equal to
8470   // JSObject::kMaxElementCount.
8471   uint32_t index_offset_;
8472   bool fast_elements_;
8473 };
8474 
8475 
EstimateElementCount(Handle<JSArray> array)8476 static uint32_t EstimateElementCount(Handle<JSArray> array) {
8477   uint32_t length = static_cast<uint32_t>(array->length()->Number());
8478   int element_count = 0;
8479   switch (array->GetElementsKind()) {
8480     case JSObject::FAST_ELEMENTS: {
8481       // Fast elements can't have lengths that are not representable by
8482       // a 32-bit signed integer.
8483       ASSERT(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
8484       int fast_length = static_cast<int>(length);
8485       Handle<FixedArray> elements(FixedArray::cast(array->elements()));
8486       for (int i = 0; i < fast_length; i++) {
8487         if (!elements->get(i)->IsTheHole()) element_count++;
8488       }
8489       break;
8490     }
8491     case JSObject::DICTIONARY_ELEMENTS: {
8492       Handle<NumberDictionary> dictionary(
8493           NumberDictionary::cast(array->elements()));
8494       int capacity = dictionary->Capacity();
8495       for (int i = 0; i < capacity; i++) {
8496         Handle<Object> key(dictionary->KeyAt(i));
8497         if (dictionary->IsKey(*key)) {
8498           element_count++;
8499         }
8500       }
8501       break;
8502     }
8503     default:
8504       // External arrays are always dense.
8505       return length;
8506   }
8507   // As an estimate, we assume that the prototype doesn't contain any
8508   // inherited elements.
8509   return element_count;
8510 }
8511 
8512 
8513 
8514 template<class ExternalArrayClass, class ElementType>
IterateExternalArrayElements(Isolate * isolate,Handle<JSObject> receiver,bool elements_are_ints,bool elements_are_guaranteed_smis,ArrayConcatVisitor * visitor)8515 static void IterateExternalArrayElements(Isolate* isolate,
8516                                          Handle<JSObject> receiver,
8517                                          bool elements_are_ints,
8518                                          bool elements_are_guaranteed_smis,
8519                                          ArrayConcatVisitor* visitor) {
8520   Handle<ExternalArrayClass> array(
8521       ExternalArrayClass::cast(receiver->elements()));
8522   uint32_t len = static_cast<uint32_t>(array->length());
8523 
8524   ASSERT(visitor != NULL);
8525   if (elements_are_ints) {
8526     if (elements_are_guaranteed_smis) {
8527       for (uint32_t j = 0; j < len; j++) {
8528         HandleScope loop_scope;
8529         Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get(j))));
8530         visitor->visit(j, e);
8531       }
8532     } else {
8533       for (uint32_t j = 0; j < len; j++) {
8534         HandleScope loop_scope;
8535         int64_t val = static_cast<int64_t>(array->get(j));
8536         if (Smi::IsValid(static_cast<intptr_t>(val))) {
8537           Handle<Smi> e(Smi::FromInt(static_cast<int>(val)));
8538           visitor->visit(j, e);
8539         } else {
8540           Handle<Object> e =
8541               isolate->factory()->NewNumber(static_cast<ElementType>(val));
8542           visitor->visit(j, e);
8543         }
8544       }
8545     }
8546   } else {
8547     for (uint32_t j = 0; j < len; j++) {
8548       HandleScope loop_scope(isolate);
8549       Handle<Object> e = isolate->factory()->NewNumber(array->get(j));
8550       visitor->visit(j, e);
8551     }
8552   }
8553 }
8554 
8555 
8556 // Used for sorting indices in a List<uint32_t>.
compareUInt32(const uint32_t * ap,const uint32_t * bp)8557 static int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
8558   uint32_t a = *ap;
8559   uint32_t b = *bp;
8560   return (a == b) ? 0 : (a < b) ? -1 : 1;
8561 }
8562 
8563 
CollectElementIndices(Handle<JSObject> object,uint32_t range,List<uint32_t> * indices)8564 static void CollectElementIndices(Handle<JSObject> object,
8565                                   uint32_t range,
8566                                   List<uint32_t>* indices) {
8567   JSObject::ElementsKind kind = object->GetElementsKind();
8568   switch (kind) {
8569     case JSObject::FAST_ELEMENTS: {
8570       Handle<FixedArray> elements(FixedArray::cast(object->elements()));
8571       uint32_t length = static_cast<uint32_t>(elements->length());
8572       if (range < length) length = range;
8573       for (uint32_t i = 0; i < length; i++) {
8574         if (!elements->get(i)->IsTheHole()) {
8575           indices->Add(i);
8576         }
8577       }
8578       break;
8579     }
8580     case JSObject::DICTIONARY_ELEMENTS: {
8581       Handle<NumberDictionary> dict(NumberDictionary::cast(object->elements()));
8582       uint32_t capacity = dict->Capacity();
8583       for (uint32_t j = 0; j < capacity; j++) {
8584         HandleScope loop_scope;
8585         Handle<Object> k(dict->KeyAt(j));
8586         if (dict->IsKey(*k)) {
8587           ASSERT(k->IsNumber());
8588           uint32_t index = static_cast<uint32_t>(k->Number());
8589           if (index < range) {
8590             indices->Add(index);
8591           }
8592         }
8593       }
8594       break;
8595     }
8596     default: {
8597       int dense_elements_length;
8598       switch (kind) {
8599         case JSObject::EXTERNAL_PIXEL_ELEMENTS: {
8600         dense_elements_length =
8601             ExternalPixelArray::cast(object->elements())->length();
8602           break;
8603         }
8604         case JSObject::EXTERNAL_BYTE_ELEMENTS: {
8605         dense_elements_length =
8606             ExternalByteArray::cast(object->elements())->length();
8607           break;
8608         }
8609         case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
8610         dense_elements_length =
8611             ExternalUnsignedByteArray::cast(object->elements())->length();
8612           break;
8613         }
8614         case JSObject::EXTERNAL_SHORT_ELEMENTS: {
8615         dense_elements_length =
8616             ExternalShortArray::cast(object->elements())->length();
8617           break;
8618         }
8619         case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
8620         dense_elements_length =
8621             ExternalUnsignedShortArray::cast(object->elements())->length();
8622           break;
8623         }
8624         case JSObject::EXTERNAL_INT_ELEMENTS: {
8625         dense_elements_length =
8626             ExternalIntArray::cast(object->elements())->length();
8627           break;
8628         }
8629         case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: {
8630         dense_elements_length =
8631             ExternalUnsignedIntArray::cast(object->elements())->length();
8632           break;
8633         }
8634         case JSObject::EXTERNAL_FLOAT_ELEMENTS: {
8635         dense_elements_length =
8636             ExternalFloatArray::cast(object->elements())->length();
8637           break;
8638         }
8639         default:
8640           UNREACHABLE();
8641           dense_elements_length = 0;
8642           break;
8643       }
8644       uint32_t length = static_cast<uint32_t>(dense_elements_length);
8645       if (range <= length) {
8646         length = range;
8647         // We will add all indices, so we might as well clear it first
8648         // and avoid duplicates.
8649         indices->Clear();
8650       }
8651       for (uint32_t i = 0; i < length; i++) {
8652         indices->Add(i);
8653       }
8654       if (length == range) return;  // All indices accounted for already.
8655       break;
8656     }
8657   }
8658 
8659   Handle<Object> prototype(object->GetPrototype());
8660   if (prototype->IsJSObject()) {
8661     // The prototype will usually have no inherited element indices,
8662     // but we have to check.
8663     CollectElementIndices(Handle<JSObject>::cast(prototype), range, indices);
8664   }
8665 }
8666 
8667 
8668 /**
8669  * A helper function that visits elements of a JSArray in numerical
8670  * order.
8671  *
8672  * The visitor argument called for each existing element in the array
8673  * with the element index and the element's value.
8674  * Afterwards it increments the base-index of the visitor by the array
8675  * length.
8676  * Returns false if any access threw an exception, otherwise true.
8677  */
IterateElements(Isolate * isolate,Handle<JSArray> receiver,ArrayConcatVisitor * visitor)8678 static bool IterateElements(Isolate* isolate,
8679                             Handle<JSArray> receiver,
8680                             ArrayConcatVisitor* visitor) {
8681   uint32_t length = static_cast<uint32_t>(receiver->length()->Number());
8682   switch (receiver->GetElementsKind()) {
8683     case JSObject::FAST_ELEMENTS: {
8684       // Run through the elements FixedArray and use HasElement and GetElement
8685       // to check the prototype for missing elements.
8686       Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
8687       int fast_length = static_cast<int>(length);
8688       ASSERT(fast_length <= elements->length());
8689       for (int j = 0; j < fast_length; j++) {
8690         HandleScope loop_scope(isolate);
8691         Handle<Object> element_value(elements->get(j), isolate);
8692         if (!element_value->IsTheHole()) {
8693           visitor->visit(j, element_value);
8694         } else if (receiver->HasElement(j)) {
8695           // Call GetElement on receiver, not its prototype, or getters won't
8696           // have the correct receiver.
8697           element_value = GetElement(receiver, j);
8698           if (element_value.is_null()) return false;
8699           visitor->visit(j, element_value);
8700         }
8701       }
8702       break;
8703     }
8704     case JSObject::DICTIONARY_ELEMENTS: {
8705       Handle<NumberDictionary> dict(receiver->element_dictionary());
8706       List<uint32_t> indices(dict->Capacity() / 2);
8707       // Collect all indices in the object and the prototypes less
8708       // than length. This might introduce duplicates in the indices list.
8709       CollectElementIndices(receiver, length, &indices);
8710       indices.Sort(&compareUInt32);
8711       int j = 0;
8712       int n = indices.length();
8713       while (j < n) {
8714         HandleScope loop_scope;
8715         uint32_t index = indices[j];
8716         Handle<Object> element = GetElement(receiver, index);
8717         if (element.is_null()) return false;
8718         visitor->visit(index, element);
8719         // Skip to next different index (i.e., omit duplicates).
8720         do {
8721           j++;
8722         } while (j < n && indices[j] == index);
8723       }
8724       break;
8725     }
8726     case JSObject::EXTERNAL_PIXEL_ELEMENTS: {
8727       Handle<ExternalPixelArray> pixels(ExternalPixelArray::cast(
8728           receiver->elements()));
8729       for (uint32_t j = 0; j < length; j++) {
8730         Handle<Smi> e(Smi::FromInt(pixels->get(j)));
8731         visitor->visit(j, e);
8732       }
8733       break;
8734     }
8735     case JSObject::EXTERNAL_BYTE_ELEMENTS: {
8736       IterateExternalArrayElements<ExternalByteArray, int8_t>(
8737           isolate, receiver, true, true, visitor);
8738       break;
8739     }
8740     case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
8741       IterateExternalArrayElements<ExternalUnsignedByteArray, uint8_t>(
8742           isolate, receiver, true, true, visitor);
8743       break;
8744     }
8745     case JSObject::EXTERNAL_SHORT_ELEMENTS: {
8746       IterateExternalArrayElements<ExternalShortArray, int16_t>(
8747           isolate, receiver, true, true, visitor);
8748       break;
8749     }
8750     case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
8751       IterateExternalArrayElements<ExternalUnsignedShortArray, uint16_t>(
8752           isolate, receiver, true, true, visitor);
8753       break;
8754     }
8755     case JSObject::EXTERNAL_INT_ELEMENTS: {
8756       IterateExternalArrayElements<ExternalIntArray, int32_t>(
8757           isolate, receiver, true, false, visitor);
8758       break;
8759     }
8760     case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: {
8761       IterateExternalArrayElements<ExternalUnsignedIntArray, uint32_t>(
8762           isolate, receiver, true, false, visitor);
8763       break;
8764     }
8765     case JSObject::EXTERNAL_FLOAT_ELEMENTS: {
8766       IterateExternalArrayElements<ExternalFloatArray, float>(
8767           isolate, receiver, false, false, visitor);
8768       break;
8769     }
8770     default:
8771       UNREACHABLE();
8772       break;
8773   }
8774   visitor->increase_index_offset(length);
8775   return true;
8776 }
8777 
8778 
8779 /**
8780  * Array::concat implementation.
8781  * See ECMAScript 262, 15.4.4.4.
8782  * TODO(581): Fix non-compliance for very large concatenations and update to
8783  * following the ECMAScript 5 specification.
8784  */
RUNTIME_FUNCTION(MaybeObject *,Runtime_ArrayConcat)8785 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) {
8786   ASSERT(args.length() == 1);
8787   HandleScope handle_scope(isolate);
8788 
8789   CONVERT_ARG_CHECKED(JSArray, arguments, 0);
8790   int argument_count = static_cast<int>(arguments->length()->Number());
8791   RUNTIME_ASSERT(arguments->HasFastElements());
8792   Handle<FixedArray> elements(FixedArray::cast(arguments->elements()));
8793 
8794   // Pass 1: estimate the length and number of elements of the result.
8795   // The actual length can be larger if any of the arguments have getters
8796   // that mutate other arguments (but will otherwise be precise).
8797   // The number of elements is precise if there are no inherited elements.
8798 
8799   uint32_t estimate_result_length = 0;
8800   uint32_t estimate_nof_elements = 0;
8801   {
8802     for (int i = 0; i < argument_count; i++) {
8803       HandleScope loop_scope;
8804       Handle<Object> obj(elements->get(i));
8805       uint32_t length_estimate;
8806       uint32_t element_estimate;
8807       if (obj->IsJSArray()) {
8808         Handle<JSArray> array(Handle<JSArray>::cast(obj));
8809         length_estimate =
8810             static_cast<uint32_t>(array->length()->Number());
8811         element_estimate =
8812             EstimateElementCount(array);
8813       } else {
8814         length_estimate = 1;
8815         element_estimate = 1;
8816       }
8817       // Avoid overflows by capping at kMaxElementCount.
8818       if (JSObject::kMaxElementCount - estimate_result_length <
8819           length_estimate) {
8820         estimate_result_length = JSObject::kMaxElementCount;
8821       } else {
8822         estimate_result_length += length_estimate;
8823       }
8824       if (JSObject::kMaxElementCount - estimate_nof_elements <
8825           element_estimate) {
8826         estimate_nof_elements = JSObject::kMaxElementCount;
8827       } else {
8828         estimate_nof_elements += element_estimate;
8829       }
8830     }
8831   }
8832 
8833   // If estimated number of elements is more than half of length, a
8834   // fixed array (fast case) is more time and space-efficient than a
8835   // dictionary.
8836   bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length;
8837 
8838   Handle<FixedArray> storage;
8839   if (fast_case) {
8840     // The backing storage array must have non-existing elements to
8841     // preserve holes across concat operations.
8842     storage = isolate->factory()->NewFixedArrayWithHoles(
8843         estimate_result_length);
8844   } else {
8845     // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
8846     uint32_t at_least_space_for = estimate_nof_elements +
8847                                   (estimate_nof_elements >> 2);
8848     storage = Handle<FixedArray>::cast(
8849         isolate->factory()->NewNumberDictionary(at_least_space_for));
8850   }
8851 
8852   ArrayConcatVisitor visitor(isolate, storage, fast_case);
8853 
8854   for (int i = 0; i < argument_count; i++) {
8855     Handle<Object> obj(elements->get(i));
8856     if (obj->IsJSArray()) {
8857       Handle<JSArray> array = Handle<JSArray>::cast(obj);
8858       if (!IterateElements(isolate, array, &visitor)) {
8859         return Failure::Exception();
8860       }
8861     } else {
8862       visitor.visit(0, obj);
8863       visitor.increase_index_offset(1);
8864     }
8865   }
8866 
8867   return *visitor.ToArray();
8868 }
8869 
8870 
8871 // This will not allocate (flatten the string), but it may run
8872 // very slowly for very deeply nested ConsStrings.  For debugging use only.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GlobalPrint)8873 RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalPrint) {
8874   NoHandleAllocation ha;
8875   ASSERT(args.length() == 1);
8876 
8877   CONVERT_CHECKED(String, string, args[0]);
8878   StringInputBuffer buffer(string);
8879   while (buffer.has_more()) {
8880     uint16_t character = buffer.GetNext();
8881     PrintF("%c", character);
8882   }
8883   return string;
8884 }
8885 
8886 // Moves all own elements of an object, that are below a limit, to positions
8887 // starting at zero. All undefined values are placed after non-undefined values,
8888 // and are followed by non-existing element. Does not change the length
8889 // property.
8890 // Returns the number of non-undefined elements collected.
RUNTIME_FUNCTION(MaybeObject *,Runtime_RemoveArrayHoles)8891 RUNTIME_FUNCTION(MaybeObject*, Runtime_RemoveArrayHoles) {
8892   ASSERT(args.length() == 2);
8893   CONVERT_CHECKED(JSObject, object, args[0]);
8894   CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
8895   return object->PrepareElementsForSort(limit);
8896 }
8897 
8898 
8899 // Move contents of argument 0 (an array) to argument 1 (an array)
RUNTIME_FUNCTION(MaybeObject *,Runtime_MoveArrayContents)8900 RUNTIME_FUNCTION(MaybeObject*, Runtime_MoveArrayContents) {
8901   ASSERT(args.length() == 2);
8902   CONVERT_CHECKED(JSArray, from, args[0]);
8903   CONVERT_CHECKED(JSArray, to, args[1]);
8904   HeapObject* new_elements = from->elements();
8905   MaybeObject* maybe_new_map;
8906   if (new_elements->map() == isolate->heap()->fixed_array_map() ||
8907       new_elements->map() == isolate->heap()->fixed_cow_array_map()) {
8908     maybe_new_map = to->map()->GetFastElementsMap();
8909   } else {
8910     maybe_new_map = to->map()->GetSlowElementsMap();
8911   }
8912   Object* new_map;
8913   if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
8914   to->set_map(Map::cast(new_map));
8915   to->set_elements(new_elements);
8916   to->set_length(from->length());
8917   Object* obj;
8918   { MaybeObject* maybe_obj = from->ResetElements();
8919     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
8920   }
8921   from->set_length(Smi::FromInt(0));
8922   return to;
8923 }
8924 
8925 
8926 // How many elements does this object/array have?
RUNTIME_FUNCTION(MaybeObject *,Runtime_EstimateNumberOfElements)8927 RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) {
8928   ASSERT(args.length() == 1);
8929   CONVERT_CHECKED(JSObject, object, args[0]);
8930   HeapObject* elements = object->elements();
8931   if (elements->IsDictionary()) {
8932     return Smi::FromInt(NumberDictionary::cast(elements)->NumberOfElements());
8933   } else if (object->IsJSArray()) {
8934     return JSArray::cast(object)->length();
8935   } else {
8936     return Smi::FromInt(FixedArray::cast(elements)->length());
8937   }
8938 }
8939 
8940 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SwapElements)8941 RUNTIME_FUNCTION(MaybeObject*, Runtime_SwapElements) {
8942   HandleScope handle_scope(isolate);
8943 
8944   ASSERT_EQ(3, args.length());
8945 
8946   CONVERT_ARG_CHECKED(JSObject, object, 0);
8947   Handle<Object> key1 = args.at<Object>(1);
8948   Handle<Object> key2 = args.at<Object>(2);
8949 
8950   uint32_t index1, index2;
8951   if (!key1->ToArrayIndex(&index1)
8952       || !key2->ToArrayIndex(&index2)) {
8953     return isolate->ThrowIllegalOperation();
8954   }
8955 
8956   Handle<JSObject> jsobject = Handle<JSObject>::cast(object);
8957   Handle<Object> tmp1 = GetElement(jsobject, index1);
8958   RETURN_IF_EMPTY_HANDLE(isolate, tmp1);
8959   Handle<Object> tmp2 = GetElement(jsobject, index2);
8960   RETURN_IF_EMPTY_HANDLE(isolate, tmp2);
8961 
8962   RETURN_IF_EMPTY_HANDLE(isolate,
8963                          SetElement(jsobject, index1, tmp2, kStrictMode));
8964   RETURN_IF_EMPTY_HANDLE(isolate,
8965                          SetElement(jsobject, index2, tmp1, kStrictMode));
8966 
8967   return isolate->heap()->undefined_value();
8968 }
8969 
8970 
8971 // Returns an array that tells you where in the [0, length) interval an array
8972 // might have elements.  Can either return keys (positive integers) or
8973 // intervals (pair of a negative integer (-start-1) followed by a
8974 // positive (length)) or undefined values.
8975 // Intervals can span over some keys that are not in the object.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetArrayKeys)8976 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
8977   ASSERT(args.length() == 2);
8978   HandleScope scope(isolate);
8979   CONVERT_ARG_CHECKED(JSObject, array, 0);
8980   CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
8981   if (array->elements()->IsDictionary()) {
8982     // Create an array and get all the keys into it, then remove all the
8983     // keys that are not integers in the range 0 to length-1.
8984     Handle<FixedArray> keys = GetKeysInFixedArrayFor(array, INCLUDE_PROTOS);
8985     int keys_length = keys->length();
8986     for (int i = 0; i < keys_length; i++) {
8987       Object* key = keys->get(i);
8988       uint32_t index = 0;
8989       if (!key->ToArrayIndex(&index) || index >= length) {
8990         // Zap invalid keys.
8991         keys->set_undefined(i);
8992       }
8993     }
8994     return *isolate->factory()->NewJSArrayWithElements(keys);
8995   } else {
8996     ASSERT(array->HasFastElements());
8997     Handle<FixedArray> single_interval = isolate->factory()->NewFixedArray(2);
8998     // -1 means start of array.
8999     single_interval->set(0, Smi::FromInt(-1));
9000     uint32_t actual_length =
9001         static_cast<uint32_t>(FixedArray::cast(array->elements())->length());
9002     uint32_t min_length = actual_length < length ? actual_length : length;
9003     Handle<Object> length_object =
9004         isolate->factory()->NewNumber(static_cast<double>(min_length));
9005     single_interval->set(1, *length_object);
9006     return *isolate->factory()->NewJSArrayWithElements(single_interval);
9007   }
9008 }
9009 
9010 
9011 // DefineAccessor takes an optional final argument which is the
9012 // property attributes (eg, DONT_ENUM, DONT_DELETE).  IMPORTANT: due
9013 // to the way accessors are implemented, it is set for both the getter
9014 // and setter on the first call to DefineAccessor and ignored on
9015 // subsequent calls.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DefineAccessor)9016 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineAccessor) {
9017   RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
9018   // Compute attributes.
9019   PropertyAttributes attributes = NONE;
9020   if (args.length() == 5) {
9021     CONVERT_CHECKED(Smi, attrs, args[4]);
9022     int value = attrs->value();
9023     // Only attribute bits should be set.
9024     ASSERT((value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
9025     attributes = static_cast<PropertyAttributes>(value);
9026   }
9027 
9028   CONVERT_CHECKED(JSObject, obj, args[0]);
9029   CONVERT_CHECKED(String, name, args[1]);
9030   CONVERT_CHECKED(Smi, flag, args[2]);
9031   CONVERT_CHECKED(JSFunction, fun, args[3]);
9032   return obj->DefineAccessor(name, flag->value() == 0, fun, attributes);
9033 }
9034 
9035 
RUNTIME_FUNCTION(MaybeObject *,Runtime_LookupAccessor)9036 RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) {
9037   ASSERT(args.length() == 3);
9038   CONVERT_CHECKED(JSObject, obj, args[0]);
9039   CONVERT_CHECKED(String, name, args[1]);
9040   CONVERT_CHECKED(Smi, flag, args[2]);
9041   return obj->LookupAccessor(name, flag->value() == 0);
9042 }
9043 
9044 
9045 #ifdef ENABLE_DEBUGGER_SUPPORT
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugBreak)9046 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugBreak) {
9047   ASSERT(args.length() == 0);
9048   return Execution::DebugBreakHelper();
9049 }
9050 
9051 
9052 // Helper functions for wrapping and unwrapping stack frame ids.
WrapFrameId(StackFrame::Id id)9053 static Smi* WrapFrameId(StackFrame::Id id) {
9054   ASSERT(IsAligned(OffsetFrom(id), static_cast<intptr_t>(4)));
9055   return Smi::FromInt(id >> 2);
9056 }
9057 
9058 
UnwrapFrameId(Smi * wrapped)9059 static StackFrame::Id UnwrapFrameId(Smi* wrapped) {
9060   return static_cast<StackFrame::Id>(wrapped->value() << 2);
9061 }
9062 
9063 
9064 // Adds a JavaScript function as a debug event listener.
9065 // args[0]: debug event listener function to set or null or undefined for
9066 //          clearing the event listener function
9067 // args[1]: object supplied during callback
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetDebugEventListener)9068 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDebugEventListener) {
9069   ASSERT(args.length() == 2);
9070   RUNTIME_ASSERT(args[0]->IsJSFunction() ||
9071                  args[0]->IsUndefined() ||
9072                  args[0]->IsNull());
9073   Handle<Object> callback = args.at<Object>(0);
9074   Handle<Object> data = args.at<Object>(1);
9075   isolate->debugger()->SetEventListener(callback, data);
9076 
9077   return isolate->heap()->undefined_value();
9078 }
9079 
9080 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Break)9081 RUNTIME_FUNCTION(MaybeObject*, Runtime_Break) {
9082   ASSERT(args.length() == 0);
9083   isolate->stack_guard()->DebugBreak();
9084   return isolate->heap()->undefined_value();
9085 }
9086 
9087 
DebugLookupResultValue(Heap * heap,Object * receiver,String * name,LookupResult * result,bool * caught_exception)9088 static MaybeObject* DebugLookupResultValue(Heap* heap,
9089                                            Object* receiver,
9090                                            String* name,
9091                                            LookupResult* result,
9092                                            bool* caught_exception) {
9093   Object* value;
9094   switch (result->type()) {
9095     case NORMAL:
9096       value = result->holder()->GetNormalizedProperty(result);
9097       if (value->IsTheHole()) {
9098         return heap->undefined_value();
9099       }
9100       return value;
9101     case FIELD:
9102       value =
9103           JSObject::cast(
9104               result->holder())->FastPropertyAt(result->GetFieldIndex());
9105       if (value->IsTheHole()) {
9106         return heap->undefined_value();
9107       }
9108       return value;
9109     case CONSTANT_FUNCTION:
9110       return result->GetConstantFunction();
9111     case CALLBACKS: {
9112       Object* structure = result->GetCallbackObject();
9113       if (structure->IsProxy() || structure->IsAccessorInfo()) {
9114         MaybeObject* maybe_value = receiver->GetPropertyWithCallback(
9115             receiver, structure, name, result->holder());
9116         if (!maybe_value->ToObject(&value)) {
9117           if (maybe_value->IsRetryAfterGC()) return maybe_value;
9118           ASSERT(maybe_value->IsException());
9119           maybe_value = heap->isolate()->pending_exception();
9120           heap->isolate()->clear_pending_exception();
9121           if (caught_exception != NULL) {
9122             *caught_exception = true;
9123           }
9124           return maybe_value;
9125         }
9126         return value;
9127       } else {
9128         return heap->undefined_value();
9129       }
9130     }
9131     case INTERCEPTOR:
9132     case MAP_TRANSITION:
9133     case EXTERNAL_ARRAY_TRANSITION:
9134     case CONSTANT_TRANSITION:
9135     case NULL_DESCRIPTOR:
9136       return heap->undefined_value();
9137     default:
9138       UNREACHABLE();
9139   }
9140   UNREACHABLE();
9141   return heap->undefined_value();
9142 }
9143 
9144 
9145 // Get debugger related details for an object property.
9146 // args[0]: object holding property
9147 // args[1]: name of the property
9148 //
9149 // The array returned contains the following information:
9150 // 0: Property value
9151 // 1: Property details
9152 // 2: Property value is exception
9153 // 3: Getter function if defined
9154 // 4: Setter function if defined
9155 // Items 2-4 are only filled if the property has either a getter or a setter
9156 // defined through __defineGetter__ and/or __defineSetter__.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugGetPropertyDetails)9157 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) {
9158   HandleScope scope(isolate);
9159 
9160   ASSERT(args.length() == 2);
9161 
9162   CONVERT_ARG_CHECKED(JSObject, obj, 0);
9163   CONVERT_ARG_CHECKED(String, name, 1);
9164 
9165   // Make sure to set the current context to the context before the debugger was
9166   // entered (if the debugger is entered). The reason for switching context here
9167   // is that for some property lookups (accessors and interceptors) callbacks
9168   // into the embedding application can occour, and the embedding application
9169   // could have the assumption that its own global context is the current
9170   // context and not some internal debugger context.
9171   SaveContext save(isolate);
9172   if (isolate->debug()->InDebugger()) {
9173     isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
9174   }
9175 
9176   // Skip the global proxy as it has no properties and always delegates to the
9177   // real global object.
9178   if (obj->IsJSGlobalProxy()) {
9179     obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
9180   }
9181 
9182 
9183   // Check if the name is trivially convertible to an index and get the element
9184   // if so.
9185   uint32_t index;
9186   if (name->AsArrayIndex(&index)) {
9187     Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
9188     Object* element_or_char;
9189     { MaybeObject* maybe_element_or_char =
9190           Runtime::GetElementOrCharAt(isolate, obj, index);
9191       if (!maybe_element_or_char->ToObject(&element_or_char)) {
9192         return maybe_element_or_char;
9193       }
9194     }
9195     details->set(0, element_or_char);
9196     details->set(1, PropertyDetails(NONE, NORMAL).AsSmi());
9197     return *isolate->factory()->NewJSArrayWithElements(details);
9198   }
9199 
9200   // Find the number of objects making up this.
9201   int length = LocalPrototypeChainLength(*obj);
9202 
9203   // Try local lookup on each of the objects.
9204   Handle<JSObject> jsproto = obj;
9205   for (int i = 0; i < length; i++) {
9206     LookupResult result;
9207     jsproto->LocalLookup(*name, &result);
9208     if (result.IsProperty()) {
9209       // LookupResult is not GC safe as it holds raw object pointers.
9210       // GC can happen later in this code so put the required fields into
9211       // local variables using handles when required for later use.
9212       PropertyType result_type = result.type();
9213       Handle<Object> result_callback_obj;
9214       if (result_type == CALLBACKS) {
9215         result_callback_obj = Handle<Object>(result.GetCallbackObject(),
9216                                              isolate);
9217       }
9218       Smi* property_details = result.GetPropertyDetails().AsSmi();
9219       // DebugLookupResultValue can cause GC so details from LookupResult needs
9220       // to be copied to handles before this.
9221       bool caught_exception = false;
9222       Object* raw_value;
9223       { MaybeObject* maybe_raw_value =
9224             DebugLookupResultValue(isolate->heap(), *obj, *name,
9225                                    &result, &caught_exception);
9226         if (!maybe_raw_value->ToObject(&raw_value)) return maybe_raw_value;
9227       }
9228       Handle<Object> value(raw_value, isolate);
9229 
9230       // If the callback object is a fixed array then it contains JavaScript
9231       // getter and/or setter.
9232       bool hasJavaScriptAccessors = result_type == CALLBACKS &&
9233                                     result_callback_obj->IsFixedArray();
9234       Handle<FixedArray> details =
9235           isolate->factory()->NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
9236       details->set(0, *value);
9237       details->set(1, property_details);
9238       if (hasJavaScriptAccessors) {
9239         details->set(2,
9240                      caught_exception ? isolate->heap()->true_value()
9241                                       : isolate->heap()->false_value());
9242         details->set(3, FixedArray::cast(*result_callback_obj)->get(0));
9243         details->set(4, FixedArray::cast(*result_callback_obj)->get(1));
9244       }
9245 
9246       return *isolate->factory()->NewJSArrayWithElements(details);
9247     }
9248     if (i < length - 1) {
9249       jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
9250     }
9251   }
9252 
9253   return isolate->heap()->undefined_value();
9254 }
9255 
9256 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugGetProperty)9257 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetProperty) {
9258   HandleScope scope(isolate);
9259 
9260   ASSERT(args.length() == 2);
9261 
9262   CONVERT_ARG_CHECKED(JSObject, obj, 0);
9263   CONVERT_ARG_CHECKED(String, name, 1);
9264 
9265   LookupResult result;
9266   obj->Lookup(*name, &result);
9267   if (result.IsProperty()) {
9268     return DebugLookupResultValue(isolate->heap(), *obj, *name, &result, NULL);
9269   }
9270   return isolate->heap()->undefined_value();
9271 }
9272 
9273 
9274 // Return the property type calculated from the property details.
9275 // args[0]: smi with property details.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugPropertyTypeFromDetails)9276 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyTypeFromDetails) {
9277   ASSERT(args.length() == 1);
9278   CONVERT_CHECKED(Smi, details, args[0]);
9279   PropertyType type = PropertyDetails(details).type();
9280   return Smi::FromInt(static_cast<int>(type));
9281 }
9282 
9283 
9284 // Return the property attribute calculated from the property details.
9285 // args[0]: smi with property details.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugPropertyAttributesFromDetails)9286 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyAttributesFromDetails) {
9287   ASSERT(args.length() == 1);
9288   CONVERT_CHECKED(Smi, details, args[0]);
9289   PropertyAttributes attributes = PropertyDetails(details).attributes();
9290   return Smi::FromInt(static_cast<int>(attributes));
9291 }
9292 
9293 
9294 // Return the property insertion index calculated from the property details.
9295 // args[0]: smi with property details.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugPropertyIndexFromDetails)9296 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyIndexFromDetails) {
9297   ASSERT(args.length() == 1);
9298   CONVERT_CHECKED(Smi, details, args[0]);
9299   int index = PropertyDetails(details).index();
9300   return Smi::FromInt(index);
9301 }
9302 
9303 
9304 // Return property value from named interceptor.
9305 // args[0]: object
9306 // args[1]: property name
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugNamedInterceptorPropertyValue)9307 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugNamedInterceptorPropertyValue) {
9308   HandleScope scope(isolate);
9309   ASSERT(args.length() == 2);
9310   CONVERT_ARG_CHECKED(JSObject, obj, 0);
9311   RUNTIME_ASSERT(obj->HasNamedInterceptor());
9312   CONVERT_ARG_CHECKED(String, name, 1);
9313 
9314   PropertyAttributes attributes;
9315   return obj->GetPropertyWithInterceptor(*obj, *name, &attributes);
9316 }
9317 
9318 
9319 // Return element value from indexed interceptor.
9320 // args[0]: object
9321 // args[1]: index
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugIndexedInterceptorElementValue)9322 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugIndexedInterceptorElementValue) {
9323   HandleScope scope(isolate);
9324   ASSERT(args.length() == 2);
9325   CONVERT_ARG_CHECKED(JSObject, obj, 0);
9326   RUNTIME_ASSERT(obj->HasIndexedInterceptor());
9327   CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
9328 
9329   return obj->GetElementWithInterceptor(*obj, index);
9330 }
9331 
9332 
RUNTIME_FUNCTION(MaybeObject *,Runtime_CheckExecutionState)9333 RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckExecutionState) {
9334   ASSERT(args.length() >= 1);
9335   CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
9336   // Check that the break id is valid.
9337   if (isolate->debug()->break_id() == 0 ||
9338       break_id != isolate->debug()->break_id()) {
9339     return isolate->Throw(
9340         isolate->heap()->illegal_execution_state_symbol());
9341   }
9342 
9343   return isolate->heap()->true_value();
9344 }
9345 
9346 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetFrameCount)9347 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) {
9348   HandleScope scope(isolate);
9349   ASSERT(args.length() == 1);
9350 
9351   // Check arguments.
9352   Object* result;
9353   { MaybeObject* maybe_result = Runtime_CheckExecutionState(
9354       RUNTIME_ARGUMENTS(isolate, args));
9355     if (!maybe_result->ToObject(&result)) return maybe_result;
9356   }
9357 
9358   // Count all frames which are relevant to debugging stack trace.
9359   int n = 0;
9360   StackFrame::Id id = isolate->debug()->break_frame_id();
9361   if (id == StackFrame::NO_ID) {
9362     // If there is no JavaScript stack frame count is 0.
9363     return Smi::FromInt(0);
9364   }
9365   for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) n++;
9366   return Smi::FromInt(n);
9367 }
9368 
9369 
9370 static const int kFrameDetailsFrameIdIndex = 0;
9371 static const int kFrameDetailsReceiverIndex = 1;
9372 static const int kFrameDetailsFunctionIndex = 2;
9373 static const int kFrameDetailsArgumentCountIndex = 3;
9374 static const int kFrameDetailsLocalCountIndex = 4;
9375 static const int kFrameDetailsSourcePositionIndex = 5;
9376 static const int kFrameDetailsConstructCallIndex = 6;
9377 static const int kFrameDetailsAtReturnIndex = 7;
9378 static const int kFrameDetailsDebuggerFrameIndex = 8;
9379 static const int kFrameDetailsFirstDynamicIndex = 9;
9380 
9381 // Return an array with frame details
9382 // args[0]: number: break id
9383 // args[1]: number: frame index
9384 //
9385 // The array returned contains the following information:
9386 // 0: Frame id
9387 // 1: Receiver
9388 // 2: Function
9389 // 3: Argument count
9390 // 4: Local count
9391 // 5: Source position
9392 // 6: Constructor call
9393 // 7: Is at return
9394 // 8: Debugger frame
9395 // Arguments name, value
9396 // Locals name, value
9397 // Return value if any
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetFrameDetails)9398 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
9399   HandleScope scope(isolate);
9400   ASSERT(args.length() == 2);
9401 
9402   // Check arguments.
9403   Object* check;
9404   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
9405       RUNTIME_ARGUMENTS(isolate, args));
9406     if (!maybe_check->ToObject(&check)) return maybe_check;
9407   }
9408   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
9409   Heap* heap = isolate->heap();
9410 
9411   // Find the relevant frame with the requested index.
9412   StackFrame::Id id = isolate->debug()->break_frame_id();
9413   if (id == StackFrame::NO_ID) {
9414     // If there are no JavaScript stack frames return undefined.
9415     return heap->undefined_value();
9416   }
9417   int count = 0;
9418   JavaScriptFrameIterator it(isolate, id);
9419   for (; !it.done(); it.Advance()) {
9420     if (count == index) break;
9421     count++;
9422   }
9423   if (it.done()) return heap->undefined_value();
9424 
9425   bool is_optimized_frame =
9426       it.frame()->LookupCode()->kind() == Code::OPTIMIZED_FUNCTION;
9427 
9428   // Traverse the saved contexts chain to find the active context for the
9429   // selected frame.
9430   SaveContext* save = isolate->save_context();
9431   while (save != NULL && !save->below(it.frame())) {
9432     save = save->prev();
9433   }
9434   ASSERT(save != NULL);
9435 
9436   // Get the frame id.
9437   Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate);
9438 
9439   // Find source position.
9440   int position =
9441       it.frame()->LookupCode()->SourcePosition(it.frame()->pc());
9442 
9443   // Check for constructor frame.
9444   bool constructor = it.frame()->IsConstructor();
9445 
9446   // Get scope info and read from it for local variable information.
9447   Handle<JSFunction> function(JSFunction::cast(it.frame()->function()));
9448   Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info());
9449   ScopeInfo<> info(*scope_info);
9450 
9451   // Get the context.
9452   Handle<Context> context(Context::cast(it.frame()->context()));
9453 
9454   // Get the locals names and values into a temporary array.
9455   //
9456   // TODO(1240907): Hide compiler-introduced stack variables
9457   // (e.g. .result)?  For users of the debugger, they will probably be
9458   // confusing.
9459   Handle<FixedArray> locals =
9460       isolate->factory()->NewFixedArray(info.NumberOfLocals() * 2);
9461 
9462   // Fill in the names of the locals.
9463   for (int i = 0; i < info.NumberOfLocals(); i++) {
9464     locals->set(i * 2, *info.LocalName(i));
9465   }
9466 
9467   // Fill in the values of the locals.
9468   for (int i = 0; i < info.NumberOfLocals(); i++) {
9469     if (is_optimized_frame) {
9470       // If we are inspecting an optimized frame use undefined as the
9471       // value for all locals.
9472       //
9473       // TODO(1140): We should be able to get the correct values
9474       // for locals in optimized frames.
9475       locals->set(i * 2 + 1, isolate->heap()->undefined_value());
9476     } else if (i < info.number_of_stack_slots()) {
9477       // Get the value from the stack.
9478       locals->set(i * 2 + 1, it.frame()->GetExpression(i));
9479     } else {
9480       // Traverse the context chain to the function context as all local
9481       // variables stored in the context will be on the function context.
9482       Handle<String> name = info.LocalName(i);
9483       while (!context->is_function_context()) {
9484         context = Handle<Context>(context->previous());
9485       }
9486       ASSERT(context->is_function_context());
9487       locals->set(i * 2 + 1,
9488                   context->get(scope_info->ContextSlotIndex(*name, NULL)));
9489     }
9490   }
9491 
9492   // Check whether this frame is positioned at return. If not top
9493   // frame or if the frame is optimized it cannot be at a return.
9494   bool at_return = false;
9495   if (!is_optimized_frame && index == 0) {
9496     at_return = isolate->debug()->IsBreakAtReturn(it.frame());
9497   }
9498 
9499   // If positioned just before return find the value to be returned and add it
9500   // to the frame information.
9501   Handle<Object> return_value = isolate->factory()->undefined_value();
9502   if (at_return) {
9503     StackFrameIterator it2(isolate);
9504     Address internal_frame_sp = NULL;
9505     while (!it2.done()) {
9506       if (it2.frame()->is_internal()) {
9507         internal_frame_sp = it2.frame()->sp();
9508       } else {
9509         if (it2.frame()->is_java_script()) {
9510           if (it2.frame()->id() == it.frame()->id()) {
9511             // The internal frame just before the JavaScript frame contains the
9512             // value to return on top. A debug break at return will create an
9513             // internal frame to store the return value (eax/rax/r0) before
9514             // entering the debug break exit frame.
9515             if (internal_frame_sp != NULL) {
9516               return_value =
9517                   Handle<Object>(Memory::Object_at(internal_frame_sp),
9518                                  isolate);
9519               break;
9520             }
9521           }
9522         }
9523 
9524         // Indicate that the previous frame was not an internal frame.
9525         internal_frame_sp = NULL;
9526       }
9527       it2.Advance();
9528     }
9529   }
9530 
9531   // Now advance to the arguments adapter frame (if any). It contains all
9532   // the provided parameters whereas the function frame always have the number
9533   // of arguments matching the functions parameters. The rest of the
9534   // information (except for what is collected above) is the same.
9535   it.AdvanceToArgumentsFrame();
9536 
9537   // Find the number of arguments to fill. At least fill the number of
9538   // parameters for the function and fill more if more parameters are provided.
9539   int argument_count = info.number_of_parameters();
9540   if (argument_count < it.frame()->ComputeParametersCount()) {
9541     argument_count = it.frame()->ComputeParametersCount();
9542   }
9543 
9544   // Calculate the size of the result.
9545   int details_size = kFrameDetailsFirstDynamicIndex +
9546                      2 * (argument_count + info.NumberOfLocals()) +
9547                      (at_return ? 1 : 0);
9548   Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
9549 
9550   // Add the frame id.
9551   details->set(kFrameDetailsFrameIdIndex, *frame_id);
9552 
9553   // Add the function (same as in function frame).
9554   details->set(kFrameDetailsFunctionIndex, it.frame()->function());
9555 
9556   // Add the arguments count.
9557   details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
9558 
9559   // Add the locals count
9560   details->set(kFrameDetailsLocalCountIndex,
9561                Smi::FromInt(info.NumberOfLocals()));
9562 
9563   // Add the source position.
9564   if (position != RelocInfo::kNoPosition) {
9565     details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
9566   } else {
9567     details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
9568   }
9569 
9570   // Add the constructor information.
9571   details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
9572 
9573   // Add the at return information.
9574   details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
9575 
9576   // Add information on whether this frame is invoked in the debugger context.
9577   details->set(kFrameDetailsDebuggerFrameIndex,
9578                heap->ToBoolean(*save->context() ==
9579                    *isolate->debug()->debug_context()));
9580 
9581   // Fill the dynamic part.
9582   int details_index = kFrameDetailsFirstDynamicIndex;
9583 
9584   // Add arguments name and value.
9585   for (int i = 0; i < argument_count; i++) {
9586     // Name of the argument.
9587     if (i < info.number_of_parameters()) {
9588       details->set(details_index++, *info.parameter_name(i));
9589     } else {
9590       details->set(details_index++, heap->undefined_value());
9591     }
9592 
9593     // Parameter value. If we are inspecting an optimized frame, use
9594     // undefined as the value.
9595     //
9596     // TODO(3141533): We should be able to get the actual parameter
9597     // value for optimized frames.
9598     if (!is_optimized_frame &&
9599         (i < it.frame()->ComputeParametersCount())) {
9600       details->set(details_index++, it.frame()->GetParameter(i));
9601     } else {
9602       details->set(details_index++, heap->undefined_value());
9603     }
9604   }
9605 
9606   // Add locals name and value from the temporary copy from the function frame.
9607   for (int i = 0; i < info.NumberOfLocals() * 2; i++) {
9608     details->set(details_index++, locals->get(i));
9609   }
9610 
9611   // Add the value being returned.
9612   if (at_return) {
9613     details->set(details_index++, *return_value);
9614   }
9615 
9616   // Add the receiver (same as in function frame).
9617   // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
9618   // THE FRAME ITERATOR TO WRAP THE RECEIVER.
9619   Handle<Object> receiver(it.frame()->receiver(), isolate);
9620   if (!receiver->IsJSObject()) {
9621     // If the receiver is NOT a JSObject we have hit an optimization
9622     // where a value object is not converted into a wrapped JS objects.
9623     // To hide this optimization from the debugger, we wrap the receiver
9624     // by creating correct wrapper object based on the calling frame's
9625     // global context.
9626     it.Advance();
9627     Handle<Context> calling_frames_global_context(
9628         Context::cast(Context::cast(it.frame()->context())->global_context()));
9629     receiver =
9630         isolate->factory()->ToObject(receiver, calling_frames_global_context);
9631   }
9632   details->set(kFrameDetailsReceiverIndex, *receiver);
9633 
9634   ASSERT_EQ(details_size, details_index);
9635   return *isolate->factory()->NewJSArrayWithElements(details);
9636 }
9637 
9638 
9639 // Copy all the context locals into an object used to materialize a scope.
CopyContextLocalsToScopeObject(Isolate * isolate,Handle<SerializedScopeInfo> serialized_scope_info,ScopeInfo<> & scope_info,Handle<Context> context,Handle<JSObject> scope_object)9640 static bool CopyContextLocalsToScopeObject(
9641     Isolate* isolate,
9642     Handle<SerializedScopeInfo> serialized_scope_info,
9643     ScopeInfo<>& scope_info,
9644     Handle<Context> context,
9645     Handle<JSObject> scope_object) {
9646   // Fill all context locals to the context extension.
9647   for (int i = Context::MIN_CONTEXT_SLOTS;
9648        i < scope_info.number_of_context_slots();
9649        i++) {
9650     int context_index = serialized_scope_info->ContextSlotIndex(
9651         *scope_info.context_slot_name(i), NULL);
9652 
9653     // Don't include the arguments shadow (.arguments) context variable.
9654     if (*scope_info.context_slot_name(i) !=
9655         isolate->heap()->arguments_shadow_symbol()) {
9656       RETURN_IF_EMPTY_HANDLE_VALUE(
9657           isolate,
9658           SetProperty(scope_object,
9659                       scope_info.context_slot_name(i),
9660                       Handle<Object>(context->get(context_index), isolate),
9661                       NONE,
9662                       kNonStrictMode),
9663           false);
9664     }
9665   }
9666 
9667   return true;
9668 }
9669 
9670 
9671 // Create a plain JSObject which materializes the local scope for the specified
9672 // frame.
MaterializeLocalScope(Isolate * isolate,JavaScriptFrame * frame)9673 static Handle<JSObject> MaterializeLocalScope(Isolate* isolate,
9674                                               JavaScriptFrame* frame) {
9675   Handle<JSFunction> function(JSFunction::cast(frame->function()));
9676   Handle<SharedFunctionInfo> shared(function->shared());
9677   Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info());
9678   ScopeInfo<> scope_info(*serialized_scope_info);
9679 
9680   // Allocate and initialize a JSObject with all the arguments, stack locals
9681   // heap locals and extension properties of the debugged function.
9682   Handle<JSObject> local_scope =
9683       isolate->factory()->NewJSObject(isolate->object_function());
9684 
9685   // First fill all parameters.
9686   for (int i = 0; i < scope_info.number_of_parameters(); ++i) {
9687     RETURN_IF_EMPTY_HANDLE_VALUE(
9688         isolate,
9689         SetProperty(local_scope,
9690                     scope_info.parameter_name(i),
9691                     Handle<Object>(frame->GetParameter(i), isolate),
9692                     NONE,
9693                     kNonStrictMode),
9694         Handle<JSObject>());
9695   }
9696 
9697   // Second fill all stack locals.
9698   for (int i = 0; i < scope_info.number_of_stack_slots(); i++) {
9699     RETURN_IF_EMPTY_HANDLE_VALUE(
9700         isolate,
9701         SetProperty(local_scope,
9702                     scope_info.stack_slot_name(i),
9703                     Handle<Object>(frame->GetExpression(i), isolate),
9704                     NONE,
9705                     kNonStrictMode),
9706         Handle<JSObject>());
9707   }
9708 
9709   // Third fill all context locals.
9710   Handle<Context> frame_context(Context::cast(frame->context()));
9711   Handle<Context> function_context(frame_context->fcontext());
9712   if (!CopyContextLocalsToScopeObject(isolate,
9713                                       serialized_scope_info, scope_info,
9714                                       function_context, local_scope)) {
9715     return Handle<JSObject>();
9716   }
9717 
9718   // Finally copy any properties from the function context extension. This will
9719   // be variables introduced by eval.
9720   if (function_context->closure() == *function) {
9721     if (function_context->has_extension() &&
9722         !function_context->IsGlobalContext()) {
9723       Handle<JSObject> ext(JSObject::cast(function_context->extension()));
9724       Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS);
9725       for (int i = 0; i < keys->length(); i++) {
9726         // Names of variables introduced by eval are strings.
9727         ASSERT(keys->get(i)->IsString());
9728         Handle<String> key(String::cast(keys->get(i)));
9729         RETURN_IF_EMPTY_HANDLE_VALUE(
9730             isolate,
9731             SetProperty(local_scope,
9732                         key,
9733                         GetProperty(ext, key),
9734                         NONE,
9735                         kNonStrictMode),
9736             Handle<JSObject>());
9737       }
9738     }
9739   }
9740   return local_scope;
9741 }
9742 
9743 
9744 // Create a plain JSObject which materializes the closure content for the
9745 // context.
MaterializeClosure(Isolate * isolate,Handle<Context> context)9746 static Handle<JSObject> MaterializeClosure(Isolate* isolate,
9747                                            Handle<Context> context) {
9748   ASSERT(context->is_function_context());
9749 
9750   Handle<SharedFunctionInfo> shared(context->closure()->shared());
9751   Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info());
9752   ScopeInfo<> scope_info(*serialized_scope_info);
9753 
9754   // Allocate and initialize a JSObject with all the content of theis function
9755   // closure.
9756   Handle<JSObject> closure_scope =
9757       isolate->factory()->NewJSObject(isolate->object_function());
9758 
9759   // Check whether the arguments shadow object exists.
9760   int arguments_shadow_index =
9761       shared->scope_info()->ContextSlotIndex(
9762           isolate->heap()->arguments_shadow_symbol(), NULL);
9763   if (arguments_shadow_index >= 0) {
9764     // In this case all the arguments are available in the arguments shadow
9765     // object.
9766     Handle<JSObject> arguments_shadow(
9767         JSObject::cast(context->get(arguments_shadow_index)));
9768     for (int i = 0; i < scope_info.number_of_parameters(); ++i) {
9769       // We don't expect exception-throwing getters on the arguments shadow.
9770       Object* element = arguments_shadow->GetElement(i)->ToObjectUnchecked();
9771       RETURN_IF_EMPTY_HANDLE_VALUE(
9772           isolate,
9773           SetProperty(closure_scope,
9774                       scope_info.parameter_name(i),
9775                       Handle<Object>(element, isolate),
9776                       NONE,
9777                       kNonStrictMode),
9778           Handle<JSObject>());
9779     }
9780   }
9781 
9782   // Fill all context locals to the context extension.
9783   if (!CopyContextLocalsToScopeObject(isolate,
9784                                       serialized_scope_info, scope_info,
9785                                       context, closure_scope)) {
9786     return Handle<JSObject>();
9787   }
9788 
9789   // Finally copy any properties from the function context extension. This will
9790   // be variables introduced by eval.
9791   if (context->has_extension()) {
9792     Handle<JSObject> ext(JSObject::cast(context->extension()));
9793     Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS);
9794     for (int i = 0; i < keys->length(); i++) {
9795       // Names of variables introduced by eval are strings.
9796       ASSERT(keys->get(i)->IsString());
9797       Handle<String> key(String::cast(keys->get(i)));
9798        RETURN_IF_EMPTY_HANDLE_VALUE(
9799           isolate,
9800           SetProperty(closure_scope,
9801                       key,
9802                       GetProperty(ext, key),
9803                       NONE,
9804                       kNonStrictMode),
9805           Handle<JSObject>());
9806     }
9807   }
9808 
9809   return closure_scope;
9810 }
9811 
9812 
9813 // Iterate over the actual scopes visible from a stack frame. All scopes are
9814 // backed by an actual context except the local scope, which is inserted
9815 // "artifically" in the context chain.
9816 class ScopeIterator {
9817  public:
9818   enum ScopeType {
9819     ScopeTypeGlobal = 0,
9820     ScopeTypeLocal,
9821     ScopeTypeWith,
9822     ScopeTypeClosure,
9823     // Every catch block contains an implicit with block (its parameter is
9824     // a JSContextExtensionObject) that extends current scope with a variable
9825     // holding exception object. Such with blocks are treated as scopes of their
9826     // own type.
9827     ScopeTypeCatch
9828   };
9829 
ScopeIterator(Isolate * isolate,JavaScriptFrame * frame)9830   ScopeIterator(Isolate* isolate, JavaScriptFrame* frame)
9831     : isolate_(isolate),
9832       frame_(frame),
9833       function_(JSFunction::cast(frame->function())),
9834       context_(Context::cast(frame->context())),
9835       local_done_(false),
9836       at_local_(false) {
9837 
9838     // Check whether the first scope is actually a local scope.
9839     if (context_->IsGlobalContext()) {
9840       // If there is a stack slot for .result then this local scope has been
9841       // created for evaluating top level code and it is not a real local scope.
9842       // Checking for the existence of .result seems fragile, but the scope info
9843       // saved with the code object does not otherwise have that information.
9844       int index = function_->shared()->scope_info()->
9845           StackSlotIndex(isolate_->heap()->result_symbol());
9846       at_local_ = index < 0;
9847     } else if (context_->is_function_context()) {
9848       at_local_ = true;
9849     } else if (context_->closure() != *function_) {
9850       // The context_ is a with block from the outer function.
9851       ASSERT(context_->has_extension());
9852       at_local_ = true;
9853     }
9854   }
9855 
9856   // More scopes?
Done()9857   bool Done() { return context_.is_null(); }
9858 
9859   // Move to the next scope.
Next()9860   void Next() {
9861     // If at a local scope mark the local scope as passed.
9862     if (at_local_) {
9863       at_local_ = false;
9864       local_done_ = true;
9865 
9866       // If the current context is not associated with the local scope the
9867       // current context is the next real scope, so don't move to the next
9868       // context in this case.
9869       if (context_->closure() != *function_) {
9870         return;
9871       }
9872     }
9873 
9874     // The global scope is always the last in the chain.
9875     if (context_->IsGlobalContext()) {
9876       context_ = Handle<Context>();
9877       return;
9878     }
9879 
9880     // Move to the next context.
9881     if (context_->is_function_context()) {
9882       context_ = Handle<Context>(Context::cast(context_->closure()->context()));
9883     } else {
9884       context_ = Handle<Context>(context_->previous());
9885     }
9886 
9887     // If passing the local scope indicate that the current scope is now the
9888     // local scope.
9889     if (!local_done_ &&
9890         (context_->IsGlobalContext() || (context_->is_function_context()))) {
9891       at_local_ = true;
9892     }
9893   }
9894 
9895   // Return the type of the current scope.
Type()9896   int Type() {
9897     if (at_local_) {
9898       return ScopeTypeLocal;
9899     }
9900     if (context_->IsGlobalContext()) {
9901       ASSERT(context_->global()->IsGlobalObject());
9902       return ScopeTypeGlobal;
9903     }
9904     if (context_->is_function_context()) {
9905       return ScopeTypeClosure;
9906     }
9907     ASSERT(context_->has_extension());
9908     // Current scope is either an explicit with statement or a with statement
9909     // implicitely generated for a catch block.
9910     // If the extension object here is a JSContextExtensionObject then
9911     // current with statement is one frome a catch block otherwise it's a
9912     // regular with statement.
9913     if (context_->extension()->IsJSContextExtensionObject()) {
9914       return ScopeTypeCatch;
9915     }
9916     return ScopeTypeWith;
9917   }
9918 
9919   // Return the JavaScript object with the content of the current scope.
ScopeObject()9920   Handle<JSObject> ScopeObject() {
9921     switch (Type()) {
9922       case ScopeIterator::ScopeTypeGlobal:
9923         return Handle<JSObject>(CurrentContext()->global());
9924         break;
9925       case ScopeIterator::ScopeTypeLocal:
9926         // Materialize the content of the local scope into a JSObject.
9927         return MaterializeLocalScope(isolate_, frame_);
9928         break;
9929       case ScopeIterator::ScopeTypeWith:
9930       case ScopeIterator::ScopeTypeCatch:
9931         // Return the with object.
9932         return Handle<JSObject>(CurrentContext()->extension());
9933         break;
9934       case ScopeIterator::ScopeTypeClosure:
9935         // Materialize the content of the closure scope into a JSObject.
9936         return MaterializeClosure(isolate_, CurrentContext());
9937         break;
9938     }
9939     UNREACHABLE();
9940     return Handle<JSObject>();
9941   }
9942 
9943   // Return the context for this scope. For the local context there might not
9944   // be an actual context.
CurrentContext()9945   Handle<Context> CurrentContext() {
9946     if (at_local_ && context_->closure() != *function_) {
9947       return Handle<Context>();
9948     }
9949     return context_;
9950   }
9951 
9952 #ifdef DEBUG
9953   // Debug print of the content of the current scope.
DebugPrint()9954   void DebugPrint() {
9955     switch (Type()) {
9956       case ScopeIterator::ScopeTypeGlobal:
9957         PrintF("Global:\n");
9958         CurrentContext()->Print();
9959         break;
9960 
9961       case ScopeIterator::ScopeTypeLocal: {
9962         PrintF("Local:\n");
9963         ScopeInfo<> scope_info(function_->shared()->scope_info());
9964         scope_info.Print();
9965         if (!CurrentContext().is_null()) {
9966           CurrentContext()->Print();
9967           if (CurrentContext()->has_extension()) {
9968             Handle<JSObject> extension =
9969                 Handle<JSObject>(CurrentContext()->extension());
9970             if (extension->IsJSContextExtensionObject()) {
9971               extension->Print();
9972             }
9973           }
9974         }
9975         break;
9976       }
9977 
9978       case ScopeIterator::ScopeTypeWith: {
9979         PrintF("With:\n");
9980         Handle<JSObject> extension =
9981             Handle<JSObject>(CurrentContext()->extension());
9982         extension->Print();
9983         break;
9984       }
9985 
9986       case ScopeIterator::ScopeTypeCatch: {
9987         PrintF("Catch:\n");
9988         Handle<JSObject> extension =
9989             Handle<JSObject>(CurrentContext()->extension());
9990         extension->Print();
9991         break;
9992       }
9993 
9994       case ScopeIterator::ScopeTypeClosure: {
9995         PrintF("Closure:\n");
9996         CurrentContext()->Print();
9997         if (CurrentContext()->has_extension()) {
9998           Handle<JSObject> extension =
9999               Handle<JSObject>(CurrentContext()->extension());
10000           if (extension->IsJSContextExtensionObject()) {
10001             extension->Print();
10002           }
10003         }
10004         break;
10005       }
10006 
10007       default:
10008         UNREACHABLE();
10009     }
10010     PrintF("\n");
10011   }
10012 #endif
10013 
10014  private:
10015   Isolate* isolate_;
10016   JavaScriptFrame* frame_;
10017   Handle<JSFunction> function_;
10018   Handle<Context> context_;
10019   bool local_done_;
10020   bool at_local_;
10021 
10022   DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
10023 };
10024 
10025 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetScopeCount)10026 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
10027   HandleScope scope(isolate);
10028   ASSERT(args.length() == 2);
10029 
10030   // Check arguments.
10031   Object* check;
10032   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
10033       RUNTIME_ARGUMENTS(isolate, args));
10034     if (!maybe_check->ToObject(&check)) return maybe_check;
10035   }
10036   CONVERT_CHECKED(Smi, wrapped_id, args[1]);
10037 
10038   // Get the frame where the debugging is performed.
10039   StackFrame::Id id = UnwrapFrameId(wrapped_id);
10040   JavaScriptFrameIterator it(isolate, id);
10041   JavaScriptFrame* frame = it.frame();
10042 
10043   // Count the visible scopes.
10044   int n = 0;
10045   for (ScopeIterator it(isolate, frame); !it.Done(); it.Next()) {
10046     n++;
10047   }
10048 
10049   return Smi::FromInt(n);
10050 }
10051 
10052 
10053 static const int kScopeDetailsTypeIndex = 0;
10054 static const int kScopeDetailsObjectIndex = 1;
10055 static const int kScopeDetailsSize = 2;
10056 
10057 // Return an array with scope details
10058 // args[0]: number: break id
10059 // args[1]: number: frame index
10060 // args[2]: number: scope index
10061 //
10062 // The array returned contains the following information:
10063 // 0: Scope type
10064 // 1: Scope object
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetScopeDetails)10065 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
10066   HandleScope scope(isolate);
10067   ASSERT(args.length() == 3);
10068 
10069   // Check arguments.
10070   Object* check;
10071   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
10072       RUNTIME_ARGUMENTS(isolate, args));
10073     if (!maybe_check->ToObject(&check)) return maybe_check;
10074   }
10075   CONVERT_CHECKED(Smi, wrapped_id, args[1]);
10076   CONVERT_NUMBER_CHECKED(int, index, Int32, args[2]);
10077 
10078   // Get the frame where the debugging is performed.
10079   StackFrame::Id id = UnwrapFrameId(wrapped_id);
10080   JavaScriptFrameIterator frame_it(isolate, id);
10081   JavaScriptFrame* frame = frame_it.frame();
10082 
10083   // Find the requested scope.
10084   int n = 0;
10085   ScopeIterator it(isolate, frame);
10086   for (; !it.Done() && n < index; it.Next()) {
10087     n++;
10088   }
10089   if (it.Done()) {
10090     return isolate->heap()->undefined_value();
10091   }
10092 
10093   // Calculate the size of the result.
10094   int details_size = kScopeDetailsSize;
10095   Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
10096 
10097   // Fill in scope details.
10098   details->set(kScopeDetailsTypeIndex, Smi::FromInt(it.Type()));
10099   Handle<JSObject> scope_object = it.ScopeObject();
10100   RETURN_IF_EMPTY_HANDLE(isolate, scope_object);
10101   details->set(kScopeDetailsObjectIndex, *scope_object);
10102 
10103   return *isolate->factory()->NewJSArrayWithElements(details);
10104 }
10105 
10106 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugPrintScopes)10107 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) {
10108   HandleScope scope(isolate);
10109   ASSERT(args.length() == 0);
10110 
10111 #ifdef DEBUG
10112   // Print the scopes for the top frame.
10113   StackFrameLocator locator;
10114   JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
10115   for (ScopeIterator it(isolate, frame); !it.Done(); it.Next()) {
10116     it.DebugPrint();
10117   }
10118 #endif
10119   return isolate->heap()->undefined_value();
10120 }
10121 
10122 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetThreadCount)10123 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadCount) {
10124   HandleScope scope(isolate);
10125   ASSERT(args.length() == 1);
10126 
10127   // Check arguments.
10128   Object* result;
10129   { MaybeObject* maybe_result = Runtime_CheckExecutionState(
10130       RUNTIME_ARGUMENTS(isolate, args));
10131     if (!maybe_result->ToObject(&result)) return maybe_result;
10132   }
10133 
10134   // Count all archived V8 threads.
10135   int n = 0;
10136   for (ThreadState* thread =
10137           isolate->thread_manager()->FirstThreadStateInUse();
10138        thread != NULL;
10139        thread = thread->Next()) {
10140     n++;
10141   }
10142 
10143   // Total number of threads is current thread and archived threads.
10144   return Smi::FromInt(n + 1);
10145 }
10146 
10147 
10148 static const int kThreadDetailsCurrentThreadIndex = 0;
10149 static const int kThreadDetailsThreadIdIndex = 1;
10150 static const int kThreadDetailsSize = 2;
10151 
10152 // Return an array with thread details
10153 // args[0]: number: break id
10154 // args[1]: number: thread index
10155 //
10156 // The array returned contains the following information:
10157 // 0: Is current thread?
10158 // 1: Thread id
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetThreadDetails)10159 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadDetails) {
10160   HandleScope scope(isolate);
10161   ASSERT(args.length() == 2);
10162 
10163   // Check arguments.
10164   Object* check;
10165   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
10166       RUNTIME_ARGUMENTS(isolate, args));
10167     if (!maybe_check->ToObject(&check)) return maybe_check;
10168   }
10169   CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
10170 
10171   // Allocate array for result.
10172   Handle<FixedArray> details =
10173       isolate->factory()->NewFixedArray(kThreadDetailsSize);
10174 
10175   // Thread index 0 is current thread.
10176   if (index == 0) {
10177     // Fill the details.
10178     details->set(kThreadDetailsCurrentThreadIndex,
10179                  isolate->heap()->true_value());
10180     details->set(kThreadDetailsThreadIdIndex,
10181                  Smi::FromInt(ThreadId::Current().ToInteger()));
10182   } else {
10183     // Find the thread with the requested index.
10184     int n = 1;
10185     ThreadState* thread =
10186         isolate->thread_manager()->FirstThreadStateInUse();
10187     while (index != n && thread != NULL) {
10188       thread = thread->Next();
10189       n++;
10190     }
10191     if (thread == NULL) {
10192       return isolate->heap()->undefined_value();
10193     }
10194 
10195     // Fill the details.
10196     details->set(kThreadDetailsCurrentThreadIndex,
10197                  isolate->heap()->false_value());
10198     details->set(kThreadDetailsThreadIdIndex,
10199                  Smi::FromInt(thread->id().ToInteger()));
10200   }
10201 
10202   // Convert to JS array and return.
10203   return *isolate->factory()->NewJSArrayWithElements(details);
10204 }
10205 
10206 
10207 // Sets the disable break state
10208 // args[0]: disable break state
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetDisableBreak)10209 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDisableBreak) {
10210   HandleScope scope(isolate);
10211   ASSERT(args.length() == 1);
10212   CONVERT_BOOLEAN_CHECKED(disable_break, args[0]);
10213   isolate->debug()->set_disable_break(disable_break);
10214   return  isolate->heap()->undefined_value();
10215 }
10216 
10217 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetBreakLocations)10218 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetBreakLocations) {
10219   HandleScope scope(isolate);
10220   ASSERT(args.length() == 1);
10221 
10222   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
10223   Handle<SharedFunctionInfo> shared(fun->shared());
10224   // Find the number of break points
10225   Handle<Object> break_locations = Debug::GetSourceBreakLocations(shared);
10226   if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
10227   // Return array as JS array
10228   return *isolate->factory()->NewJSArrayWithElements(
10229       Handle<FixedArray>::cast(break_locations));
10230 }
10231 
10232 
10233 // Set a break point in a function
10234 // args[0]: function
10235 // args[1]: number: break source position (within the function source)
10236 // args[2]: number: break point object
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetFunctionBreakPoint)10237 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFunctionBreakPoint) {
10238   HandleScope scope(isolate);
10239   ASSERT(args.length() == 3);
10240   CONVERT_ARG_CHECKED(JSFunction, fun, 0);
10241   Handle<SharedFunctionInfo> shared(fun->shared());
10242   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
10243   RUNTIME_ASSERT(source_position >= 0);
10244   Handle<Object> break_point_object_arg = args.at<Object>(2);
10245 
10246   // Set break point.
10247   isolate->debug()->SetBreakPoint(shared, break_point_object_arg,
10248                                   &source_position);
10249 
10250   return Smi::FromInt(source_position);
10251 }
10252 
10253 
FindSharedFunctionInfoInScript(Isolate * isolate,Handle<Script> script,int position)10254 Object* Runtime::FindSharedFunctionInfoInScript(Isolate* isolate,
10255                                                 Handle<Script> script,
10256                                                 int position) {
10257   // Iterate the heap looking for SharedFunctionInfo generated from the
10258   // script. The inner most SharedFunctionInfo containing the source position
10259   // for the requested break point is found.
10260   // NOTE: This might require several heap iterations. If the SharedFunctionInfo
10261   // which is found is not compiled it is compiled and the heap is iterated
10262   // again as the compilation might create inner functions from the newly
10263   // compiled function and the actual requested break point might be in one of
10264   // these functions.
10265   bool done = false;
10266   // The current candidate for the source position:
10267   int target_start_position = RelocInfo::kNoPosition;
10268   Handle<SharedFunctionInfo> target;
10269   while (!done) {
10270     HeapIterator iterator;
10271     for (HeapObject* obj = iterator.next();
10272          obj != NULL; obj = iterator.next()) {
10273       if (obj->IsSharedFunctionInfo()) {
10274         Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(obj));
10275         if (shared->script() == *script) {
10276           // If the SharedFunctionInfo found has the requested script data and
10277           // contains the source position it is a candidate.
10278           int start_position = shared->function_token_position();
10279           if (start_position == RelocInfo::kNoPosition) {
10280             start_position = shared->start_position();
10281           }
10282           if (start_position <= position &&
10283               position <= shared->end_position()) {
10284             // If there is no candidate or this function is within the current
10285             // candidate this is the new candidate.
10286             if (target.is_null()) {
10287               target_start_position = start_position;
10288               target = shared;
10289             } else {
10290               if (target_start_position == start_position &&
10291                   shared->end_position() == target->end_position()) {
10292                   // If a top-level function contain only one function
10293                   // declartion the source for the top-level and the function is
10294                   // the same. In that case prefer the non top-level function.
10295                 if (!shared->is_toplevel()) {
10296                   target_start_position = start_position;
10297                   target = shared;
10298                 }
10299               } else if (target_start_position <= start_position &&
10300                          shared->end_position() <= target->end_position()) {
10301                 // This containment check includes equality as a function inside
10302                 // a top-level function can share either start or end position
10303                 // with the top-level function.
10304                 target_start_position = start_position;
10305                 target = shared;
10306               }
10307             }
10308           }
10309         }
10310       }
10311     }
10312 
10313     if (target.is_null()) {
10314       return isolate->heap()->undefined_value();
10315     }
10316 
10317     // If the candidate found is compiled we are done. NOTE: when lazy
10318     // compilation of inner functions is introduced some additional checking
10319     // needs to be done here to compile inner functions.
10320     done = target->is_compiled();
10321     if (!done) {
10322       // If the candidate is not compiled compile it to reveal any inner
10323       // functions which might contain the requested source position.
10324       CompileLazyShared(target, KEEP_EXCEPTION);
10325     }
10326   }
10327 
10328   return *target;
10329 }
10330 
10331 
10332 // Changes the state of a break point in a script and returns source position
10333 // where break point was set. NOTE: Regarding performance see the NOTE for
10334 // GetScriptFromScriptData.
10335 // args[0]: script to set break point in
10336 // args[1]: number: break source position (within the script source)
10337 // args[2]: number: break point object
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetScriptBreakPoint)10338 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScriptBreakPoint) {
10339   HandleScope scope(isolate);
10340   ASSERT(args.length() == 3);
10341   CONVERT_ARG_CHECKED(JSValue, wrapper, 0);
10342   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
10343   RUNTIME_ASSERT(source_position >= 0);
10344   Handle<Object> break_point_object_arg = args.at<Object>(2);
10345 
10346   // Get the script from the script wrapper.
10347   RUNTIME_ASSERT(wrapper->value()->IsScript());
10348   Handle<Script> script(Script::cast(wrapper->value()));
10349 
10350   Object* result = Runtime::FindSharedFunctionInfoInScript(
10351       isolate, script, source_position);
10352   if (!result->IsUndefined()) {
10353     Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
10354     // Find position within function. The script position might be before the
10355     // source position of the first function.
10356     int position;
10357     if (shared->start_position() > source_position) {
10358       position = 0;
10359     } else {
10360       position = source_position - shared->start_position();
10361     }
10362     isolate->debug()->SetBreakPoint(shared, break_point_object_arg, &position);
10363     position += shared->start_position();
10364     return Smi::FromInt(position);
10365   }
10366   return  isolate->heap()->undefined_value();
10367 }
10368 
10369 
10370 // Clear a break point
10371 // args[0]: number: break point object
RUNTIME_FUNCTION(MaybeObject *,Runtime_ClearBreakPoint)10372 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearBreakPoint) {
10373   HandleScope scope(isolate);
10374   ASSERT(args.length() == 1);
10375   Handle<Object> break_point_object_arg = args.at<Object>(0);
10376 
10377   // Clear break point.
10378   isolate->debug()->ClearBreakPoint(break_point_object_arg);
10379 
10380   return isolate->heap()->undefined_value();
10381 }
10382 
10383 
10384 // Change the state of break on exceptions.
10385 // args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
10386 // args[1]: Boolean indicating on/off.
RUNTIME_FUNCTION(MaybeObject *,Runtime_ChangeBreakOnException)10387 RUNTIME_FUNCTION(MaybeObject*, Runtime_ChangeBreakOnException) {
10388   HandleScope scope(isolate);
10389   ASSERT(args.length() == 2);
10390   RUNTIME_ASSERT(args[0]->IsNumber());
10391   CONVERT_BOOLEAN_CHECKED(enable, args[1]);
10392 
10393   // If the number doesn't match an enum value, the ChangeBreakOnException
10394   // function will default to affecting caught exceptions.
10395   ExceptionBreakType type =
10396       static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
10397   // Update break point state.
10398   isolate->debug()->ChangeBreakOnException(type, enable);
10399   return isolate->heap()->undefined_value();
10400 }
10401 
10402 
10403 // Returns the state of break on exceptions
10404 // args[0]: boolean indicating uncaught exceptions
RUNTIME_FUNCTION(MaybeObject *,Runtime_IsBreakOnException)10405 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsBreakOnException) {
10406   HandleScope scope(isolate);
10407   ASSERT(args.length() == 1);
10408   RUNTIME_ASSERT(args[0]->IsNumber());
10409 
10410   ExceptionBreakType type =
10411       static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
10412   bool result = isolate->debug()->IsBreakOnException(type);
10413   return Smi::FromInt(result);
10414 }
10415 
10416 
10417 // Prepare for stepping
10418 // args[0]: break id for checking execution state
10419 // args[1]: step action from the enumeration StepAction
10420 // args[2]: number of times to perform the step, for step out it is the number
10421 //          of frames to step down.
RUNTIME_FUNCTION(MaybeObject *,Runtime_PrepareStep)10422 RUNTIME_FUNCTION(MaybeObject*, Runtime_PrepareStep) {
10423   HandleScope scope(isolate);
10424   ASSERT(args.length() == 3);
10425   // Check arguments.
10426   Object* check;
10427   { MaybeObject* maybe_check = Runtime_CheckExecutionState(
10428       RUNTIME_ARGUMENTS(isolate, args));
10429     if (!maybe_check->ToObject(&check)) return maybe_check;
10430   }
10431   if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
10432     return isolate->Throw(isolate->heap()->illegal_argument_symbol());
10433   }
10434 
10435   // Get the step action and check validity.
10436   StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
10437   if (step_action != StepIn &&
10438       step_action != StepNext &&
10439       step_action != StepOut &&
10440       step_action != StepInMin &&
10441       step_action != StepMin) {
10442     return isolate->Throw(isolate->heap()->illegal_argument_symbol());
10443   }
10444 
10445   // Get the number of steps.
10446   int step_count = NumberToInt32(args[2]);
10447   if (step_count < 1) {
10448     return isolate->Throw(isolate->heap()->illegal_argument_symbol());
10449   }
10450 
10451   // Clear all current stepping setup.
10452   isolate->debug()->ClearStepping();
10453 
10454   // Prepare step.
10455   isolate->debug()->PrepareStep(static_cast<StepAction>(step_action),
10456                                 step_count);
10457   return isolate->heap()->undefined_value();
10458 }
10459 
10460 
10461 // Clear all stepping set by PrepareStep.
RUNTIME_FUNCTION(MaybeObject *,Runtime_ClearStepping)10462 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) {
10463   HandleScope scope(isolate);
10464   ASSERT(args.length() == 0);
10465   isolate->debug()->ClearStepping();
10466   return isolate->heap()->undefined_value();
10467 }
10468 
10469 
10470 // Creates a copy of the with context chain. The copy of the context chain is
10471 // is linked to the function context supplied.
CopyWithContextChain(Handle<Context> context_chain,Handle<Context> function_context)10472 static Handle<Context> CopyWithContextChain(Handle<Context> context_chain,
10473                                             Handle<Context> function_context) {
10474   // At the bottom of the chain. Return the function context to link to.
10475   if (context_chain->is_function_context()) {
10476     return function_context;
10477   }
10478 
10479   // Recursively copy the with contexts.
10480   Handle<Context> previous(context_chain->previous());
10481   Handle<JSObject> extension(JSObject::cast(context_chain->extension()));
10482   Handle<Context> context = CopyWithContextChain(function_context, previous);
10483   return context->GetIsolate()->factory()->NewWithContext(
10484       context, extension, context_chain->IsCatchContext());
10485 }
10486 
10487 
10488 // Helper function to find or create the arguments object for
10489 // Runtime_DebugEvaluate.
GetArgumentsObject(Isolate * isolate,JavaScriptFrame * frame,Handle<JSFunction> function,Handle<SerializedScopeInfo> scope_info,const ScopeInfo<> * sinfo,Handle<Context> function_context)10490 static Handle<Object> GetArgumentsObject(Isolate* isolate,
10491                                          JavaScriptFrame* frame,
10492                                          Handle<JSFunction> function,
10493                                          Handle<SerializedScopeInfo> scope_info,
10494                                          const ScopeInfo<>* sinfo,
10495                                          Handle<Context> function_context) {
10496   // Try to find the value of 'arguments' to pass as parameter. If it is not
10497   // found (that is the debugged function does not reference 'arguments' and
10498   // does not support eval) then create an 'arguments' object.
10499   int index;
10500   if (sinfo->number_of_stack_slots() > 0) {
10501     index = scope_info->StackSlotIndex(isolate->heap()->arguments_symbol());
10502     if (index != -1) {
10503       return Handle<Object>(frame->GetExpression(index), isolate);
10504     }
10505   }
10506 
10507   if (sinfo->number_of_context_slots() > Context::MIN_CONTEXT_SLOTS) {
10508     index = scope_info->ContextSlotIndex(isolate->heap()->arguments_symbol(),
10509                                          NULL);
10510     if (index != -1) {
10511       return Handle<Object>(function_context->get(index), isolate);
10512     }
10513   }
10514 
10515   const int length = frame->ComputeParametersCount();
10516   Handle<JSObject> arguments =
10517       isolate->factory()->NewArgumentsObject(function, length);
10518   Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
10519 
10520   AssertNoAllocation no_gc;
10521   WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
10522   for (int i = 0; i < length; i++) {
10523     array->set(i, frame->GetParameter(i), mode);
10524   }
10525   arguments->set_elements(*array);
10526   return arguments;
10527 }
10528 
10529 
10530 static const char kSourceStr[] =
10531     "(function(arguments,__source__){return eval(__source__);})";
10532 
10533 
10534 // Evaluate a piece of JavaScript in the context of a stack frame for
10535 // debugging. This is accomplished by creating a new context which in its
10536 // extension part has all the parameters and locals of the function on the
10537 // stack frame. A function which calls eval with the code to evaluate is then
10538 // compiled in this context and called in this context. As this context
10539 // replaces the context of the function on the stack frame a new (empty)
10540 // function is created as well to be used as the closure for the context.
10541 // This function and the context acts as replacements for the function on the
10542 // stack frame presenting the same view of the values of parameters and
10543 // local variables as if the piece of JavaScript was evaluated at the point
10544 // where the function on the stack frame is currently stopped.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugEvaluate)10545 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
10546   HandleScope scope(isolate);
10547 
10548   // Check the execution state and decode arguments frame and source to be
10549   // evaluated.
10550   ASSERT(args.length() == 5);
10551   Object* check_result;
10552   { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(
10553       RUNTIME_ARGUMENTS(isolate, args));
10554     if (!maybe_check_result->ToObject(&check_result)) {
10555       return maybe_check_result;
10556     }
10557   }
10558   CONVERT_CHECKED(Smi, wrapped_id, args[1]);
10559   CONVERT_ARG_CHECKED(String, source, 2);
10560   CONVERT_BOOLEAN_CHECKED(disable_break, args[3]);
10561   Handle<Object> additional_context(args[4]);
10562 
10563   // Handle the processing of break.
10564   DisableBreak disable_break_save(disable_break);
10565 
10566   // Get the frame where the debugging is performed.
10567   StackFrame::Id id = UnwrapFrameId(wrapped_id);
10568   JavaScriptFrameIterator it(isolate, id);
10569   JavaScriptFrame* frame = it.frame();
10570   Handle<JSFunction> function(JSFunction::cast(frame->function()));
10571   Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info());
10572   ScopeInfo<> sinfo(*scope_info);
10573 
10574   // Traverse the saved contexts chain to find the active context for the
10575   // selected frame.
10576   SaveContext* save = isolate->save_context();
10577   while (save != NULL && !save->below(frame)) {
10578     save = save->prev();
10579   }
10580   ASSERT(save != NULL);
10581   SaveContext savex(isolate);
10582   isolate->set_context(*(save->context()));
10583 
10584   // Create the (empty) function replacing the function on the stack frame for
10585   // the purpose of evaluating in the context created below. It is important
10586   // that this function does not describe any parameters and local variables
10587   // in the context. If it does then this will cause problems with the lookup
10588   // in Context::Lookup, where context slots for parameters and local variables
10589   // are looked at before the extension object.
10590   Handle<JSFunction> go_between =
10591       isolate->factory()->NewFunction(isolate->factory()->empty_string(),
10592                                       isolate->factory()->undefined_value());
10593   go_between->set_context(function->context());
10594 #ifdef DEBUG
10595   ScopeInfo<> go_between_sinfo(go_between->shared()->scope_info());
10596   ASSERT(go_between_sinfo.number_of_parameters() == 0);
10597   ASSERT(go_between_sinfo.number_of_context_slots() == 0);
10598 #endif
10599 
10600   // Materialize the content of the local scope into a JSObject.
10601   Handle<JSObject> local_scope = MaterializeLocalScope(isolate, frame);
10602   RETURN_IF_EMPTY_HANDLE(isolate, local_scope);
10603 
10604   // Allocate a new context for the debug evaluation and set the extension
10605   // object build.
10606   Handle<Context> context =
10607       isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS,
10608                                              go_between);
10609   context->set_extension(*local_scope);
10610   // Copy any with contexts present and chain them in front of this context.
10611   Handle<Context> frame_context(Context::cast(frame->context()));
10612   Handle<Context> function_context(frame_context->fcontext());
10613   context = CopyWithContextChain(frame_context, context);
10614 
10615   if (additional_context->IsJSObject()) {
10616     context = isolate->factory()->NewWithContext(context,
10617         Handle<JSObject>::cast(additional_context), false);
10618   }
10619 
10620   // Wrap the evaluation statement in a new function compiled in the newly
10621   // created context. The function has one parameter which has to be called
10622   // 'arguments'. This it to have access to what would have been 'arguments' in
10623   // the function being debugged.
10624   // function(arguments,__source__) {return eval(__source__);}
10625 
10626   Handle<String> function_source =
10627       isolate->factory()->NewStringFromAscii(
10628           Vector<const char>(kSourceStr, sizeof(kSourceStr) - 1));
10629 
10630   // Currently, the eval code will be executed in non-strict mode,
10631   // even in the strict code context.
10632   Handle<SharedFunctionInfo> shared =
10633       Compiler::CompileEval(function_source,
10634                             context,
10635                             context->IsGlobalContext(),
10636                             kNonStrictMode);
10637   if (shared.is_null()) return Failure::Exception();
10638   Handle<JSFunction> compiled_function =
10639       isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context);
10640 
10641   // Invoke the result of the compilation to get the evaluation function.
10642   bool has_pending_exception;
10643   Handle<Object> receiver(frame->receiver(), isolate);
10644   Handle<Object> evaluation_function =
10645       Execution::Call(compiled_function, receiver, 0, NULL,
10646                       &has_pending_exception);
10647   if (has_pending_exception) return Failure::Exception();
10648 
10649   Handle<Object> arguments = GetArgumentsObject(isolate, frame,
10650                                                 function, scope_info,
10651                                                 &sinfo, function_context);
10652 
10653   // Invoke the evaluation function and return the result.
10654   const int argc = 2;
10655   Object** argv[argc] = { arguments.location(),
10656                           Handle<Object>::cast(source).location() };
10657   Handle<Object> result =
10658       Execution::Call(Handle<JSFunction>::cast(evaluation_function), receiver,
10659                       argc, argv, &has_pending_exception);
10660   if (has_pending_exception) return Failure::Exception();
10661 
10662   // Skip the global proxy as it has no properties and always delegates to the
10663   // real global object.
10664   if (result->IsJSGlobalProxy()) {
10665     result = Handle<JSObject>(JSObject::cast(result->GetPrototype()));
10666   }
10667 
10668   return *result;
10669 }
10670 
10671 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugEvaluateGlobal)10672 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) {
10673   HandleScope scope(isolate);
10674 
10675   // Check the execution state and decode arguments frame and source to be
10676   // evaluated.
10677   ASSERT(args.length() == 4);
10678   Object* check_result;
10679   { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(
10680       RUNTIME_ARGUMENTS(isolate, args));
10681     if (!maybe_check_result->ToObject(&check_result)) {
10682       return maybe_check_result;
10683     }
10684   }
10685   CONVERT_ARG_CHECKED(String, source, 1);
10686   CONVERT_BOOLEAN_CHECKED(disable_break, args[2]);
10687   Handle<Object> additional_context(args[3]);
10688 
10689   // Handle the processing of break.
10690   DisableBreak disable_break_save(disable_break);
10691 
10692   // Enter the top context from before the debugger was invoked.
10693   SaveContext save(isolate);
10694   SaveContext* top = &save;
10695   while (top != NULL && *top->context() == *isolate->debug()->debug_context()) {
10696     top = top->prev();
10697   }
10698   if (top != NULL) {
10699     isolate->set_context(*top->context());
10700   }
10701 
10702   // Get the global context now set to the top context from before the
10703   // debugger was invoked.
10704   Handle<Context> context = isolate->global_context();
10705 
10706   bool is_global = true;
10707 
10708   if (additional_context->IsJSObject()) {
10709     // Create a function context first, than put 'with' context on top of it.
10710     Handle<JSFunction> go_between = isolate->factory()->NewFunction(
10711         isolate->factory()->empty_string(),
10712         isolate->factory()->undefined_value());
10713     go_between->set_context(*context);
10714     context =
10715         isolate->factory()->NewFunctionContext(
10716             Context::MIN_CONTEXT_SLOTS, go_between);
10717     context->set_extension(JSObject::cast(*additional_context));
10718     is_global = false;
10719   }
10720 
10721   // Compile the source to be evaluated.
10722   // Currently, the eval code will be executed in non-strict mode,
10723   // even in the strict code context.
10724   Handle<SharedFunctionInfo> shared =
10725       Compiler::CompileEval(source, context, is_global, kNonStrictMode);
10726   if (shared.is_null()) return Failure::Exception();
10727   Handle<JSFunction> compiled_function =
10728       Handle<JSFunction>(
10729           isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
10730                                                                 context));
10731 
10732   // Invoke the result of the compilation to get the evaluation function.
10733   bool has_pending_exception;
10734   Handle<Object> receiver = isolate->global();
10735   Handle<Object> result =
10736     Execution::Call(compiled_function, receiver, 0, NULL,
10737                     &has_pending_exception);
10738   if (has_pending_exception) return Failure::Exception();
10739   return *result;
10740 }
10741 
10742 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugGetLoadedScripts)10743 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetLoadedScripts) {
10744   HandleScope scope(isolate);
10745   ASSERT(args.length() == 0);
10746 
10747   // Fill the script objects.
10748   Handle<FixedArray> instances = isolate->debug()->GetLoadedScripts();
10749 
10750   // Convert the script objects to proper JS objects.
10751   for (int i = 0; i < instances->length(); i++) {
10752     Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
10753     // Get the script wrapper in a local handle before calling GetScriptWrapper,
10754     // because using
10755     //   instances->set(i, *GetScriptWrapper(script))
10756     // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
10757     // already have deferenced the instances handle.
10758     Handle<JSValue> wrapper = GetScriptWrapper(script);
10759     instances->set(i, *wrapper);
10760   }
10761 
10762   // Return result as a JS array.
10763   Handle<JSObject> result =
10764       isolate->factory()->NewJSObject(isolate->array_function());
10765   Handle<JSArray>::cast(result)->SetContent(*instances);
10766   return *result;
10767 }
10768 
10769 
10770 // Helper function used by Runtime_DebugReferencedBy below.
DebugReferencedBy(JSObject * target,Object * instance_filter,int max_references,FixedArray * instances,int instances_size,JSFunction * arguments_function)10771 static int DebugReferencedBy(JSObject* target,
10772                              Object* instance_filter, int max_references,
10773                              FixedArray* instances, int instances_size,
10774                              JSFunction* arguments_function) {
10775   NoHandleAllocation ha;
10776   AssertNoAllocation no_alloc;
10777 
10778   // Iterate the heap.
10779   int count = 0;
10780   JSObject* last = NULL;
10781   HeapIterator iterator;
10782   HeapObject* heap_obj = NULL;
10783   while (((heap_obj = iterator.next()) != NULL) &&
10784          (max_references == 0 || count < max_references)) {
10785     // Only look at all JSObjects.
10786     if (heap_obj->IsJSObject()) {
10787       // Skip context extension objects and argument arrays as these are
10788       // checked in the context of functions using them.
10789       JSObject* obj = JSObject::cast(heap_obj);
10790       if (obj->IsJSContextExtensionObject() ||
10791           obj->map()->constructor() == arguments_function) {
10792         continue;
10793       }
10794 
10795       // Check if the JS object has a reference to the object looked for.
10796       if (obj->ReferencesObject(target)) {
10797         // Check instance filter if supplied. This is normally used to avoid
10798         // references from mirror objects (see Runtime_IsInPrototypeChain).
10799         if (!instance_filter->IsUndefined()) {
10800           Object* V = obj;
10801           while (true) {
10802             Object* prototype = V->GetPrototype();
10803             if (prototype->IsNull()) {
10804               break;
10805             }
10806             if (instance_filter == prototype) {
10807               obj = NULL;  // Don't add this object.
10808               break;
10809             }
10810             V = prototype;
10811           }
10812         }
10813 
10814         if (obj != NULL) {
10815           // Valid reference found add to instance array if supplied an update
10816           // count.
10817           if (instances != NULL && count < instances_size) {
10818             instances->set(count, obj);
10819           }
10820           last = obj;
10821           count++;
10822         }
10823       }
10824     }
10825   }
10826 
10827   // Check for circular reference only. This can happen when the object is only
10828   // referenced from mirrors and has a circular reference in which case the
10829   // object is not really alive and would have been garbage collected if not
10830   // referenced from the mirror.
10831   if (count == 1 && last == target) {
10832     count = 0;
10833   }
10834 
10835   // Return the number of referencing objects found.
10836   return count;
10837 }
10838 
10839 
10840 // Scan the heap for objects with direct references to an object
10841 // args[0]: the object to find references to
10842 // args[1]: constructor function for instances to exclude (Mirror)
10843 // args[2]: the the maximum number of objects to return
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugReferencedBy)10844 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugReferencedBy) {
10845   ASSERT(args.length() == 3);
10846 
10847   // First perform a full GC in order to avoid references from dead objects.
10848   isolate->heap()->CollectAllGarbage(false);
10849 
10850   // Check parameters.
10851   CONVERT_CHECKED(JSObject, target, args[0]);
10852   Object* instance_filter = args[1];
10853   RUNTIME_ASSERT(instance_filter->IsUndefined() ||
10854                  instance_filter->IsJSObject());
10855   CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
10856   RUNTIME_ASSERT(max_references >= 0);
10857 
10858   // Get the constructor function for context extension and arguments array.
10859   JSObject* arguments_boilerplate =
10860       isolate->context()->global_context()->arguments_boilerplate();
10861   JSFunction* arguments_function =
10862       JSFunction::cast(arguments_boilerplate->map()->constructor());
10863 
10864   // Get the number of referencing objects.
10865   int count;
10866   count = DebugReferencedBy(target, instance_filter, max_references,
10867                             NULL, 0, arguments_function);
10868 
10869   // Allocate an array to hold the result.
10870   Object* object;
10871   { MaybeObject* maybe_object = isolate->heap()->AllocateFixedArray(count);
10872     if (!maybe_object->ToObject(&object)) return maybe_object;
10873   }
10874   FixedArray* instances = FixedArray::cast(object);
10875 
10876   // Fill the referencing objects.
10877   count = DebugReferencedBy(target, instance_filter, max_references,
10878                             instances, count, arguments_function);
10879 
10880   // Return result as JS array.
10881   Object* result;
10882   { MaybeObject* maybe_result = isolate->heap()->AllocateJSObject(
10883       isolate->context()->global_context()->array_function());
10884     if (!maybe_result->ToObject(&result)) return maybe_result;
10885   }
10886   JSArray::cast(result)->SetContent(instances);
10887   return result;
10888 }
10889 
10890 
10891 // Helper function used by Runtime_DebugConstructedBy below.
DebugConstructedBy(JSFunction * constructor,int max_references,FixedArray * instances,int instances_size)10892 static int DebugConstructedBy(JSFunction* constructor, int max_references,
10893                               FixedArray* instances, int instances_size) {
10894   AssertNoAllocation no_alloc;
10895 
10896   // Iterate the heap.
10897   int count = 0;
10898   HeapIterator iterator;
10899   HeapObject* heap_obj = NULL;
10900   while (((heap_obj = iterator.next()) != NULL) &&
10901          (max_references == 0 || count < max_references)) {
10902     // Only look at all JSObjects.
10903     if (heap_obj->IsJSObject()) {
10904       JSObject* obj = JSObject::cast(heap_obj);
10905       if (obj->map()->constructor() == constructor) {
10906         // Valid reference found add to instance array if supplied an update
10907         // count.
10908         if (instances != NULL && count < instances_size) {
10909           instances->set(count, obj);
10910         }
10911         count++;
10912       }
10913     }
10914   }
10915 
10916   // Return the number of referencing objects found.
10917   return count;
10918 }
10919 
10920 
10921 // Scan the heap for objects constructed by a specific function.
10922 // args[0]: the constructor to find instances of
10923 // args[1]: the the maximum number of objects to return
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugConstructedBy)10924 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugConstructedBy) {
10925   ASSERT(args.length() == 2);
10926 
10927   // First perform a full GC in order to avoid dead objects.
10928   isolate->heap()->CollectAllGarbage(false);
10929 
10930   // Check parameters.
10931   CONVERT_CHECKED(JSFunction, constructor, args[0]);
10932   CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
10933   RUNTIME_ASSERT(max_references >= 0);
10934 
10935   // Get the number of referencing objects.
10936   int count;
10937   count = DebugConstructedBy(constructor, max_references, NULL, 0);
10938 
10939   // Allocate an array to hold the result.
10940   Object* object;
10941   { MaybeObject* maybe_object = isolate->heap()->AllocateFixedArray(count);
10942     if (!maybe_object->ToObject(&object)) return maybe_object;
10943   }
10944   FixedArray* instances = FixedArray::cast(object);
10945 
10946   // Fill the referencing objects.
10947   count = DebugConstructedBy(constructor, max_references, instances, count);
10948 
10949   // Return result as JS array.
10950   Object* result;
10951   { MaybeObject* maybe_result = isolate->heap()->AllocateJSObject(
10952           isolate->context()->global_context()->array_function());
10953     if (!maybe_result->ToObject(&result)) return maybe_result;
10954   }
10955   JSArray::cast(result)->SetContent(instances);
10956   return result;
10957 }
10958 
10959 
10960 // Find the effective prototype object as returned by __proto__.
10961 // args[0]: the object to find the prototype for.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugGetPrototype)10962 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPrototype) {
10963   ASSERT(args.length() == 1);
10964 
10965   CONVERT_CHECKED(JSObject, obj, args[0]);
10966 
10967   // Use the __proto__ accessor.
10968   return Accessors::ObjectPrototype.getter(obj, NULL);
10969 }
10970 
10971 
RUNTIME_FUNCTION(MaybeObject *,Runtime_SystemBreak)10972 RUNTIME_FUNCTION(MaybeObject*, Runtime_SystemBreak) {
10973   ASSERT(args.length() == 0);
10974   CPU::DebugBreak();
10975   return isolate->heap()->undefined_value();
10976 }
10977 
10978 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugDisassembleFunction)10979 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleFunction) {
10980 #ifdef DEBUG
10981   HandleScope scope(isolate);
10982   ASSERT(args.length() == 1);
10983   // Get the function and make sure it is compiled.
10984   CONVERT_ARG_CHECKED(JSFunction, func, 0);
10985   Handle<SharedFunctionInfo> shared(func->shared());
10986   if (!EnsureCompiled(shared, KEEP_EXCEPTION)) {
10987     return Failure::Exception();
10988   }
10989   func->code()->PrintLn();
10990 #endif  // DEBUG
10991   return isolate->heap()->undefined_value();
10992 }
10993 
10994 
RUNTIME_FUNCTION(MaybeObject *,Runtime_DebugDisassembleConstructor)10995 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleConstructor) {
10996 #ifdef DEBUG
10997   HandleScope scope(isolate);
10998   ASSERT(args.length() == 1);
10999   // Get the function and make sure it is compiled.
11000   CONVERT_ARG_CHECKED(JSFunction, func, 0);
11001   Handle<SharedFunctionInfo> shared(func->shared());
11002   if (!EnsureCompiled(shared, KEEP_EXCEPTION)) {
11003     return Failure::Exception();
11004   }
11005   shared->construct_stub()->PrintLn();
11006 #endif  // DEBUG
11007   return isolate->heap()->undefined_value();
11008 }
11009 
11010 
RUNTIME_FUNCTION(MaybeObject *,Runtime_FunctionGetInferredName)11011 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetInferredName) {
11012   NoHandleAllocation ha;
11013   ASSERT(args.length() == 1);
11014 
11015   CONVERT_CHECKED(JSFunction, f, args[0]);
11016   return f->shared()->inferred_name();
11017 }
11018 
11019 
FindSharedFunctionInfosForScript(Script * script,FixedArray * buffer)11020 static int FindSharedFunctionInfosForScript(Script* script,
11021                                             FixedArray* buffer) {
11022   AssertNoAllocation no_allocations;
11023 
11024   int counter = 0;
11025   int buffer_size = buffer->length();
11026   HeapIterator iterator;
11027   for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
11028     ASSERT(obj != NULL);
11029     if (!obj->IsSharedFunctionInfo()) {
11030       continue;
11031     }
11032     SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
11033     if (shared->script() != script) {
11034       continue;
11035     }
11036     if (counter < buffer_size) {
11037       buffer->set(counter, shared);
11038     }
11039     counter++;
11040   }
11041   return counter;
11042 }
11043 
11044 // For a script finds all SharedFunctionInfo's in the heap that points
11045 // to this script. Returns JSArray of SharedFunctionInfo wrapped
11046 // in OpaqueReferences.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditFindSharedFunctionInfosForScript)11047 RUNTIME_FUNCTION(MaybeObject*,
11048                  Runtime_LiveEditFindSharedFunctionInfosForScript) {
11049   ASSERT(args.length() == 1);
11050   HandleScope scope(isolate);
11051   CONVERT_CHECKED(JSValue, script_value, args[0]);
11052 
11053   Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
11054 
11055   const int kBufferSize = 32;
11056 
11057   Handle<FixedArray> array;
11058   array = isolate->factory()->NewFixedArray(kBufferSize);
11059   int number = FindSharedFunctionInfosForScript(*script, *array);
11060   if (number > kBufferSize) {
11061     array = isolate->factory()->NewFixedArray(number);
11062     FindSharedFunctionInfosForScript(*script, *array);
11063   }
11064 
11065   Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array);
11066   result->set_length(Smi::FromInt(number));
11067 
11068   LiveEdit::WrapSharedFunctionInfos(result);
11069 
11070   return *result;
11071 }
11072 
11073 // For a script calculates compilation information about all its functions.
11074 // The script source is explicitly specified by the second argument.
11075 // The source of the actual script is not used, however it is important that
11076 // all generated code keeps references to this particular instance of script.
11077 // Returns a JSArray of compilation infos. The array is ordered so that
11078 // each function with all its descendant is always stored in a continues range
11079 // with the function itself going first. The root function is a script function.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditGatherCompileInfo)11080 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditGatherCompileInfo) {
11081   ASSERT(args.length() == 2);
11082   HandleScope scope(isolate);
11083   CONVERT_CHECKED(JSValue, script, args[0]);
11084   CONVERT_ARG_CHECKED(String, source, 1);
11085   Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
11086 
11087   JSArray* result =  LiveEdit::GatherCompileInfo(script_handle, source);
11088 
11089   if (isolate->has_pending_exception()) {
11090     return Failure::Exception();
11091   }
11092 
11093   return result;
11094 }
11095 
11096 // Changes the source of the script to a new_source.
11097 // If old_script_name is provided (i.e. is a String), also creates a copy of
11098 // the script with its original source and sends notification to debugger.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditReplaceScript)11099 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceScript) {
11100   ASSERT(args.length() == 3);
11101   HandleScope scope(isolate);
11102   CONVERT_CHECKED(JSValue, original_script_value, args[0]);
11103   CONVERT_ARG_CHECKED(String, new_source, 1);
11104   Handle<Object> old_script_name(args[2], isolate);
11105 
11106   CONVERT_CHECKED(Script, original_script_pointer,
11107                   original_script_value->value());
11108   Handle<Script> original_script(original_script_pointer);
11109 
11110   Object* old_script = LiveEdit::ChangeScriptSource(original_script,
11111                                                     new_source,
11112                                                     old_script_name);
11113 
11114   if (old_script->IsScript()) {
11115     Handle<Script> script_handle(Script::cast(old_script));
11116     return *(GetScriptWrapper(script_handle));
11117   } else {
11118     return isolate->heap()->null_value();
11119   }
11120 }
11121 
11122 
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditFunctionSourceUpdated)11123 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSourceUpdated) {
11124   ASSERT(args.length() == 1);
11125   HandleScope scope(isolate);
11126   CONVERT_ARG_CHECKED(JSArray, shared_info, 0);
11127   return LiveEdit::FunctionSourceUpdated(shared_info);
11128 }
11129 
11130 
11131 // Replaces code of SharedFunctionInfo with a new one.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditReplaceFunctionCode)11132 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceFunctionCode) {
11133   ASSERT(args.length() == 2);
11134   HandleScope scope(isolate);
11135   CONVERT_ARG_CHECKED(JSArray, new_compile_info, 0);
11136   CONVERT_ARG_CHECKED(JSArray, shared_info, 1);
11137 
11138   return LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
11139 }
11140 
11141 // Connects SharedFunctionInfo to another script.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditFunctionSetScript)11142 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSetScript) {
11143   ASSERT(args.length() == 2);
11144   HandleScope scope(isolate);
11145   Handle<Object> function_object(args[0], isolate);
11146   Handle<Object> script_object(args[1], isolate);
11147 
11148   if (function_object->IsJSValue()) {
11149     Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
11150     if (script_object->IsJSValue()) {
11151       CONVERT_CHECKED(Script, script, JSValue::cast(*script_object)->value());
11152       script_object = Handle<Object>(script, isolate);
11153     }
11154 
11155     LiveEdit::SetFunctionScript(function_wrapper, script_object);
11156   } else {
11157     // Just ignore this. We may not have a SharedFunctionInfo for some functions
11158     // and we check it in this function.
11159   }
11160 
11161   return isolate->heap()->undefined_value();
11162 }
11163 
11164 
11165 // In a code of a parent function replaces original function as embedded object
11166 // with a substitution one.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditReplaceRefToNestedFunction)11167 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceRefToNestedFunction) {
11168   ASSERT(args.length() == 3);
11169   HandleScope scope(isolate);
11170 
11171   CONVERT_ARG_CHECKED(JSValue, parent_wrapper, 0);
11172   CONVERT_ARG_CHECKED(JSValue, orig_wrapper, 1);
11173   CONVERT_ARG_CHECKED(JSValue, subst_wrapper, 2);
11174 
11175   LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper,
11176                                        subst_wrapper);
11177 
11178   return isolate->heap()->undefined_value();
11179 }
11180 
11181 
11182 // Updates positions of a shared function info (first parameter) according
11183 // to script source change. Text change is described in second parameter as
11184 // array of groups of 3 numbers:
11185 // (change_begin, change_end, change_end_new_position).
11186 // Each group describes a change in text; groups are sorted by change_begin.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditPatchFunctionPositions)11187 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditPatchFunctionPositions) {
11188   ASSERT(args.length() == 2);
11189   HandleScope scope(isolate);
11190   CONVERT_ARG_CHECKED(JSArray, shared_array, 0);
11191   CONVERT_ARG_CHECKED(JSArray, position_change_array, 1);
11192 
11193   return LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
11194 }
11195 
11196 
11197 // For array of SharedFunctionInfo's (each wrapped in JSValue)
11198 // checks that none of them have activations on stacks (of any thread).
11199 // Returns array of the same length with corresponding results of
11200 // LiveEdit::FunctionPatchabilityStatus type.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditCheckAndDropActivations)11201 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCheckAndDropActivations) {
11202   ASSERT(args.length() == 2);
11203   HandleScope scope(isolate);
11204   CONVERT_ARG_CHECKED(JSArray, shared_array, 0);
11205   CONVERT_BOOLEAN_CHECKED(do_drop, args[1]);
11206 
11207   return *LiveEdit::CheckAndDropActivations(shared_array, do_drop);
11208 }
11209 
11210 // Compares 2 strings line-by-line, then token-wise and returns diff in form
11211 // of JSArray of triplets (pos1, pos1_end, pos2_end) describing list
11212 // of diff chunks.
RUNTIME_FUNCTION(MaybeObject *,Runtime_LiveEditCompareStrings)11213 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCompareStrings) {
11214   ASSERT(args.length() == 2);
11215   HandleScope scope(isolate);
11216   CONVERT_ARG_CHECKED(String, s1, 0);
11217   CONVERT_ARG_CHECKED(String, s2, 1);
11218 
11219   return *LiveEdit::CompareStrings(s1, s2);
11220 }
11221 
11222 
11223 // A testing entry. Returns statement position which is the closest to
11224 // source_position.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetFunctionCodePositionFromSource)11225 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionCodePositionFromSource) {
11226   ASSERT(args.length() == 2);
11227   HandleScope scope(isolate);
11228   CONVERT_ARG_CHECKED(JSFunction, function, 0);
11229   CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
11230 
11231   Handle<Code> code(function->code(), isolate);
11232 
11233   if (code->kind() != Code::FUNCTION &&
11234       code->kind() != Code::OPTIMIZED_FUNCTION) {
11235     return isolate->heap()->undefined_value();
11236   }
11237 
11238   RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION));
11239   int closest_pc = 0;
11240   int distance = kMaxInt;
11241   while (!it.done()) {
11242     int statement_position = static_cast<int>(it.rinfo()->data());
11243     // Check if this break point is closer that what was previously found.
11244     if (source_position <= statement_position &&
11245         statement_position - source_position < distance) {
11246       closest_pc =
11247           static_cast<int>(it.rinfo()->pc() - code->instruction_start());
11248       distance = statement_position - source_position;
11249       // Check whether we can't get any closer.
11250       if (distance == 0) break;
11251     }
11252     it.next();
11253   }
11254 
11255   return Smi::FromInt(closest_pc);
11256 }
11257 
11258 
11259 // Calls specified function with or without entering the debugger.
11260 // This is used in unit tests to run code as if debugger is entered or simply
11261 // to have a stack with C++ frame in the middle.
RUNTIME_FUNCTION(MaybeObject *,Runtime_ExecuteInDebugContext)11262 RUNTIME_FUNCTION(MaybeObject*, Runtime_ExecuteInDebugContext) {
11263   ASSERT(args.length() == 2);
11264   HandleScope scope(isolate);
11265   CONVERT_ARG_CHECKED(JSFunction, function, 0);
11266   CONVERT_BOOLEAN_CHECKED(without_debugger, args[1]);
11267 
11268   Handle<Object> result;
11269   bool pending_exception;
11270   {
11271     if (without_debugger) {
11272       result = Execution::Call(function, isolate->global(), 0, NULL,
11273                                &pending_exception);
11274     } else {
11275       EnterDebugger enter_debugger;
11276       result = Execution::Call(function, isolate->global(), 0, NULL,
11277                                &pending_exception);
11278     }
11279   }
11280   if (!pending_exception) {
11281     return *result;
11282   } else {
11283     return Failure::Exception();
11284   }
11285 }
11286 
11287 
11288 // Sets a v8 flag.
RUNTIME_FUNCTION(MaybeObject *,Runtime_SetFlags)11289 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFlags) {
11290   CONVERT_CHECKED(String, arg, args[0]);
11291   SmartPointer<char> flags =
11292       arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
11293   FlagList::SetFlagsFromString(*flags, StrLength(*flags));
11294   return isolate->heap()->undefined_value();
11295 }
11296 
11297 
11298 // Performs a GC.
11299 // Presently, it only does a full GC.
RUNTIME_FUNCTION(MaybeObject *,Runtime_CollectGarbage)11300 RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectGarbage) {
11301   isolate->heap()->CollectAllGarbage(true);
11302   return isolate->heap()->undefined_value();
11303 }
11304 
11305 
11306 // Gets the current heap usage.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetHeapUsage)11307 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHeapUsage) {
11308   int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
11309   if (!Smi::IsValid(usage)) {
11310     return *isolate->factory()->NewNumberFromInt(usage);
11311   }
11312   return Smi::FromInt(usage);
11313 }
11314 
11315 
11316 // Captures a live object list from the present heap.
RUNTIME_FUNCTION(MaybeObject *,Runtime_HasLOLEnabled)11317 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLOLEnabled) {
11318 #ifdef LIVE_OBJECT_LIST
11319   return isolate->heap()->true_value();
11320 #else
11321   return isolate->heap()->false_value();
11322 #endif
11323 }
11324 
11325 
11326 // Captures a live object list from the present heap.
RUNTIME_FUNCTION(MaybeObject *,Runtime_CaptureLOL)11327 RUNTIME_FUNCTION(MaybeObject*, Runtime_CaptureLOL) {
11328 #ifdef LIVE_OBJECT_LIST
11329   return LiveObjectList::Capture();
11330 #else
11331   return isolate->heap()->undefined_value();
11332 #endif
11333 }
11334 
11335 
11336 // Deletes the specified live object list.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DeleteLOL)11337 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteLOL) {
11338 #ifdef LIVE_OBJECT_LIST
11339   CONVERT_SMI_CHECKED(id, args[0]);
11340   bool success = LiveObjectList::Delete(id);
11341   return success ? isolate->heap()->true_value() :
11342                    isolate->heap()->false_value();
11343 #else
11344   return isolate->heap()->undefined_value();
11345 #endif
11346 }
11347 
11348 
11349 // Generates the response to a debugger request for a dump of the objects
11350 // contained in the difference between the captured live object lists
11351 // specified by id1 and id2.
11352 // If id1 is 0 (i.e. not a valid lol), then the whole of lol id2 will be
11353 // dumped.
RUNTIME_FUNCTION(MaybeObject *,Runtime_DumpLOL)11354 RUNTIME_FUNCTION(MaybeObject*, Runtime_DumpLOL) {
11355 #ifdef LIVE_OBJECT_LIST
11356   HandleScope scope;
11357   CONVERT_SMI_CHECKED(id1, args[0]);
11358   CONVERT_SMI_CHECKED(id2, args[1]);
11359   CONVERT_SMI_CHECKED(start, args[2]);
11360   CONVERT_SMI_CHECKED(count, args[3]);
11361   CONVERT_ARG_CHECKED(JSObject, filter_obj, 4);
11362   EnterDebugger enter_debugger;
11363   return LiveObjectList::Dump(id1, id2, start, count, filter_obj);
11364 #else
11365   return isolate->heap()->undefined_value();
11366 #endif
11367 }
11368 
11369 
11370 // Gets the specified object as requested by the debugger.
11371 // This is only used for obj ids shown in live object lists.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetLOLObj)11372 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObj) {
11373 #ifdef LIVE_OBJECT_LIST
11374   CONVERT_SMI_CHECKED(obj_id, args[0]);
11375   Object* result = LiveObjectList::GetObj(obj_id);
11376   return result;
11377 #else
11378   return isolate->heap()->undefined_value();
11379 #endif
11380 }
11381 
11382 
11383 // Gets the obj id for the specified address if valid.
11384 // This is only used for obj ids shown in live object lists.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetLOLObjId)11385 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObjId) {
11386 #ifdef LIVE_OBJECT_LIST
11387   HandleScope scope;
11388   CONVERT_ARG_CHECKED(String, address, 0);
11389   Object* result = LiveObjectList::GetObjId(address);
11390   return result;
11391 #else
11392   return isolate->heap()->undefined_value();
11393 #endif
11394 }
11395 
11396 
11397 // Gets the retainers that references the specified object alive.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetLOLObjRetainers)11398 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObjRetainers) {
11399 #ifdef LIVE_OBJECT_LIST
11400   HandleScope scope;
11401   CONVERT_SMI_CHECKED(obj_id, args[0]);
11402   RUNTIME_ASSERT(args[1]->IsUndefined() || args[1]->IsJSObject());
11403   RUNTIME_ASSERT(args[2]->IsUndefined() || args[2]->IsBoolean());
11404   RUNTIME_ASSERT(args[3]->IsUndefined() || args[3]->IsSmi());
11405   RUNTIME_ASSERT(args[4]->IsUndefined() || args[4]->IsSmi());
11406   CONVERT_ARG_CHECKED(JSObject, filter_obj, 5);
11407 
11408   Handle<JSObject> instance_filter;
11409   if (args[1]->IsJSObject()) {
11410     instance_filter = args.at<JSObject>(1);
11411   }
11412   bool verbose = false;
11413   if (args[2]->IsBoolean()) {
11414     verbose = args[2]->IsTrue();
11415   }
11416   int start = 0;
11417   if (args[3]->IsSmi()) {
11418     start = Smi::cast(args[3])->value();
11419   }
11420   int limit = Smi::kMaxValue;
11421   if (args[4]->IsSmi()) {
11422     limit = Smi::cast(args[4])->value();
11423   }
11424 
11425   return LiveObjectList::GetObjRetainers(obj_id,
11426                                          instance_filter,
11427                                          verbose,
11428                                          start,
11429                                          limit,
11430                                          filter_obj);
11431 #else
11432   return isolate->heap()->undefined_value();
11433 #endif
11434 }
11435 
11436 
11437 // Gets the reference path between 2 objects.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetLOLPath)11438 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLPath) {
11439 #ifdef LIVE_OBJECT_LIST
11440   HandleScope scope;
11441   CONVERT_SMI_CHECKED(obj_id1, args[0]);
11442   CONVERT_SMI_CHECKED(obj_id2, args[1]);
11443   RUNTIME_ASSERT(args[2]->IsUndefined() || args[2]->IsJSObject());
11444 
11445   Handle<JSObject> instance_filter;
11446   if (args[2]->IsJSObject()) {
11447     instance_filter = args.at<JSObject>(2);
11448   }
11449 
11450   Object* result =
11451       LiveObjectList::GetPath(obj_id1, obj_id2, instance_filter);
11452   return result;
11453 #else
11454   return isolate->heap()->undefined_value();
11455 #endif
11456 }
11457 
11458 
11459 // Generates the response to a debugger request for a list of all
11460 // previously captured live object lists.
RUNTIME_FUNCTION(MaybeObject *,Runtime_InfoLOL)11461 RUNTIME_FUNCTION(MaybeObject*, Runtime_InfoLOL) {
11462 #ifdef LIVE_OBJECT_LIST
11463   CONVERT_SMI_CHECKED(start, args[0]);
11464   CONVERT_SMI_CHECKED(count, args[1]);
11465   return LiveObjectList::Info(start, count);
11466 #else
11467   return isolate->heap()->undefined_value();
11468 #endif
11469 }
11470 
11471 
11472 // Gets a dump of the specified object as requested by the debugger.
11473 // This is only used for obj ids shown in live object lists.
RUNTIME_FUNCTION(MaybeObject *,Runtime_PrintLOLObj)11474 RUNTIME_FUNCTION(MaybeObject*, Runtime_PrintLOLObj) {
11475 #ifdef LIVE_OBJECT_LIST
11476   HandleScope scope;
11477   CONVERT_SMI_CHECKED(obj_id, args[0]);
11478   Object* result = LiveObjectList::PrintObj(obj_id);
11479   return result;
11480 #else
11481   return isolate->heap()->undefined_value();
11482 #endif
11483 }
11484 
11485 
11486 // Resets and releases all previously captured live object lists.
RUNTIME_FUNCTION(MaybeObject *,Runtime_ResetLOL)11487 RUNTIME_FUNCTION(MaybeObject*, Runtime_ResetLOL) {
11488 #ifdef LIVE_OBJECT_LIST
11489   LiveObjectList::Reset();
11490   return isolate->heap()->undefined_value();
11491 #else
11492   return isolate->heap()->undefined_value();
11493 #endif
11494 }
11495 
11496 
11497 // Generates the response to a debugger request for a summary of the types
11498 // of objects in the difference between the captured live object lists
11499 // specified by id1 and id2.
11500 // If id1 is 0 (i.e. not a valid lol), then the whole of lol id2 will be
11501 // summarized.
RUNTIME_FUNCTION(MaybeObject *,Runtime_SummarizeLOL)11502 RUNTIME_FUNCTION(MaybeObject*, Runtime_SummarizeLOL) {
11503 #ifdef LIVE_OBJECT_LIST
11504   HandleScope scope;
11505   CONVERT_SMI_CHECKED(id1, args[0]);
11506   CONVERT_SMI_CHECKED(id2, args[1]);
11507   CONVERT_ARG_CHECKED(JSObject, filter_obj, 2);
11508 
11509   EnterDebugger enter_debugger;
11510   return LiveObjectList::Summarize(id1, id2, filter_obj);
11511 #else
11512   return isolate->heap()->undefined_value();
11513 #endif
11514 }
11515 
11516 #endif  // ENABLE_DEBUGGER_SUPPORT
11517 
11518 
11519 #ifdef ENABLE_LOGGING_AND_PROFILING
RUNTIME_FUNCTION(MaybeObject *,Runtime_ProfilerResume)11520 RUNTIME_FUNCTION(MaybeObject*, Runtime_ProfilerResume) {
11521   NoHandleAllocation ha;
11522   ASSERT(args.length() == 2);
11523 
11524   CONVERT_CHECKED(Smi, smi_modules, args[0]);
11525   CONVERT_CHECKED(Smi, smi_tag, args[1]);
11526   v8::V8::ResumeProfilerEx(smi_modules->value(), smi_tag->value());
11527   return isolate->heap()->undefined_value();
11528 }
11529 
11530 
RUNTIME_FUNCTION(MaybeObject *,Runtime_ProfilerPause)11531 RUNTIME_FUNCTION(MaybeObject*, Runtime_ProfilerPause) {
11532   NoHandleAllocation ha;
11533   ASSERT(args.length() == 2);
11534 
11535   CONVERT_CHECKED(Smi, smi_modules, args[0]);
11536   CONVERT_CHECKED(Smi, smi_tag, args[1]);
11537   v8::V8::PauseProfilerEx(smi_modules->value(), smi_tag->value());
11538   return isolate->heap()->undefined_value();
11539 }
11540 
11541 #endif  // ENABLE_LOGGING_AND_PROFILING
11542 
11543 // Finds the script object from the script data. NOTE: This operation uses
11544 // heap traversal to find the function generated for the source position
11545 // for the requested break point. For lazily compiled functions several heap
11546 // traversals might be required rendering this operation as a rather slow
11547 // operation. However for setting break points which is normally done through
11548 // some kind of user interaction the performance is not crucial.
Runtime_GetScriptFromScriptName(Handle<String> script_name)11549 static Handle<Object> Runtime_GetScriptFromScriptName(
11550     Handle<String> script_name) {
11551   // Scan the heap for Script objects to find the script with the requested
11552   // script data.
11553   Handle<Script> script;
11554   HeapIterator iterator;
11555   HeapObject* obj = NULL;
11556   while (script.is_null() && ((obj = iterator.next()) != NULL)) {
11557     // If a script is found check if it has the script data requested.
11558     if (obj->IsScript()) {
11559       if (Script::cast(obj)->name()->IsString()) {
11560         if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) {
11561           script = Handle<Script>(Script::cast(obj));
11562         }
11563       }
11564     }
11565   }
11566 
11567   // If no script with the requested script data is found return undefined.
11568   if (script.is_null()) return FACTORY->undefined_value();
11569 
11570   // Return the script found.
11571   return GetScriptWrapper(script);
11572 }
11573 
11574 
11575 // Get the script object from script data. NOTE: Regarding performance
11576 // see the NOTE for GetScriptFromScriptData.
11577 // args[0]: script data for the script to find the source for
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetScript)11578 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScript) {
11579   HandleScope scope(isolate);
11580 
11581   ASSERT(args.length() == 1);
11582 
11583   CONVERT_CHECKED(String, script_name, args[0]);
11584 
11585   // Find the requested script.
11586   Handle<Object> result =
11587       Runtime_GetScriptFromScriptName(Handle<String>(script_name));
11588   return *result;
11589 }
11590 
11591 
11592 // Determines whether the given stack frame should be displayed in
11593 // a stack trace.  The caller is the error constructor that asked
11594 // for the stack trace to be collected.  The first time a construct
11595 // call to this function is encountered it is skipped.  The seen_caller
11596 // in/out parameter is used to remember if the caller has been seen
11597 // yet.
ShowFrameInStackTrace(StackFrame * raw_frame,Object * caller,bool * seen_caller)11598 static bool ShowFrameInStackTrace(StackFrame* raw_frame, Object* caller,
11599     bool* seen_caller) {
11600   // Only display JS frames.
11601   if (!raw_frame->is_java_script())
11602     return false;
11603   JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
11604   Object* raw_fun = frame->function();
11605   // Not sure when this can happen but skip it just in case.
11606   if (!raw_fun->IsJSFunction())
11607     return false;
11608   if ((raw_fun == caller) && !(*seen_caller)) {
11609     *seen_caller = true;
11610     return false;
11611   }
11612   // Skip all frames until we've seen the caller.  Also, skip the most
11613   // obvious builtin calls.  Some builtin calls (such as Number.ADD
11614   // which is invoked using 'call') are very difficult to recognize
11615   // so we're leaving them in for now.
11616   return *seen_caller && !frame->receiver()->IsJSBuiltinsObject();
11617 }
11618 
11619 
11620 // Collect the raw data for a stack trace.  Returns an array of 4
11621 // element segments each containing a receiver, function, code and
11622 // native code offset.
RUNTIME_FUNCTION(MaybeObject *,Runtime_CollectStackTrace)11623 RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectStackTrace) {
11624   ASSERT_EQ(args.length(), 2);
11625   Handle<Object> caller = args.at<Object>(0);
11626   CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[1]);
11627 
11628   HandleScope scope(isolate);
11629   Factory* factory = isolate->factory();
11630 
11631   limit = Max(limit, 0);  // Ensure that limit is not negative.
11632   int initial_size = Min(limit, 10);
11633   Handle<FixedArray> elements =
11634       factory->NewFixedArrayWithHoles(initial_size * 4);
11635 
11636   StackFrameIterator iter(isolate);
11637   // If the caller parameter is a function we skip frames until we're
11638   // under it before starting to collect.
11639   bool seen_caller = !caller->IsJSFunction();
11640   int cursor = 0;
11641   int frames_seen = 0;
11642   while (!iter.done() && frames_seen < limit) {
11643     StackFrame* raw_frame = iter.frame();
11644     if (ShowFrameInStackTrace(raw_frame, *caller, &seen_caller)) {
11645       frames_seen++;
11646       JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
11647       // Set initial size to the maximum inlining level + 1 for the outermost
11648       // function.
11649       List<FrameSummary> frames(Compiler::kMaxInliningLevels + 1);
11650       frame->Summarize(&frames);
11651       for (int i = frames.length() - 1; i >= 0; i--) {
11652         if (cursor + 4 > elements->length()) {
11653           int new_capacity = JSObject::NewElementsCapacity(elements->length());
11654           Handle<FixedArray> new_elements =
11655               factory->NewFixedArrayWithHoles(new_capacity);
11656           for (int i = 0; i < cursor; i++) {
11657             new_elements->set(i, elements->get(i));
11658           }
11659           elements = new_elements;
11660         }
11661         ASSERT(cursor + 4 <= elements->length());
11662 
11663         Handle<Object> recv = frames[i].receiver();
11664         Handle<JSFunction> fun = frames[i].function();
11665         Handle<Code> code = frames[i].code();
11666         Handle<Smi> offset(Smi::FromInt(frames[i].offset()));
11667         elements->set(cursor++, *recv);
11668         elements->set(cursor++, *fun);
11669         elements->set(cursor++, *code);
11670         elements->set(cursor++, *offset);
11671       }
11672     }
11673     iter.Advance();
11674   }
11675   Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
11676   result->set_length(Smi::FromInt(cursor));
11677   return *result;
11678 }
11679 
11680 
11681 // Returns V8 version as a string.
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetV8Version)11682 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetV8Version) {
11683   ASSERT_EQ(args.length(), 0);
11684 
11685   NoHandleAllocation ha;
11686 
11687   const char* version_string = v8::V8::GetVersion();
11688 
11689   return isolate->heap()->AllocateStringFromAscii(CStrVector(version_string),
11690                                                   NOT_TENURED);
11691 }
11692 
11693 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Abort)11694 RUNTIME_FUNCTION(MaybeObject*, Runtime_Abort) {
11695   ASSERT(args.length() == 2);
11696   OS::PrintError("abort: %s\n", reinterpret_cast<char*>(args[0]) +
11697                                     Smi::cast(args[1])->value());
11698   isolate->PrintStack();
11699   OS::Abort();
11700   UNREACHABLE();
11701   return NULL;
11702 }
11703 
11704 
RUNTIME_FUNCTION(MaybeObject *,Runtime_GetFromCache)11705 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFromCache) {
11706   // This is only called from codegen, so checks might be more lax.
11707   CONVERT_CHECKED(JSFunctionResultCache, cache, args[0]);
11708   Object* key = args[1];
11709 
11710   int finger_index = cache->finger_index();
11711   Object* o = cache->get(finger_index);
11712   if (o == key) {
11713     // The fastest case: hit the same place again.
11714     return cache->get(finger_index + 1);
11715   }
11716 
11717   for (int i = finger_index - 2;
11718        i >= JSFunctionResultCache::kEntriesIndex;
11719        i -= 2) {
11720     o = cache->get(i);
11721     if (o == key) {
11722       cache->set_finger_index(i);
11723       return cache->get(i + 1);
11724     }
11725   }
11726 
11727   int size = cache->size();
11728   ASSERT(size <= cache->length());
11729 
11730   for (int i = size - 2; i > finger_index; i -= 2) {
11731     o = cache->get(i);
11732     if (o == key) {
11733       cache->set_finger_index(i);
11734       return cache->get(i + 1);
11735     }
11736   }
11737 
11738   // There is no value in the cache.  Invoke the function and cache result.
11739   HandleScope scope(isolate);
11740 
11741   Handle<JSFunctionResultCache> cache_handle(cache);
11742   Handle<Object> key_handle(key);
11743   Handle<Object> value;
11744   {
11745     Handle<JSFunction> factory(JSFunction::cast(
11746           cache_handle->get(JSFunctionResultCache::kFactoryIndex)));
11747     // TODO(antonm): consider passing a receiver when constructing a cache.
11748     Handle<Object> receiver(isolate->global_context()->global());
11749     // This handle is nor shared, nor used later, so it's safe.
11750     Object** argv[] = { key_handle.location() };
11751     bool pending_exception = false;
11752     value = Execution::Call(factory,
11753                             receiver,
11754                             1,
11755                             argv,
11756                             &pending_exception);
11757     if (pending_exception) return Failure::Exception();
11758   }
11759 
11760 #ifdef DEBUG
11761   cache_handle->JSFunctionResultCacheVerify();
11762 #endif
11763 
11764   // Function invocation may have cleared the cache.  Reread all the data.
11765   finger_index = cache_handle->finger_index();
11766   size = cache_handle->size();
11767 
11768   // If we have spare room, put new data into it, otherwise evict post finger
11769   // entry which is likely to be the least recently used.
11770   int index = -1;
11771   if (size < cache_handle->length()) {
11772     cache_handle->set_size(size + JSFunctionResultCache::kEntrySize);
11773     index = size;
11774   } else {
11775     index = finger_index + JSFunctionResultCache::kEntrySize;
11776     if (index == cache_handle->length()) {
11777       index = JSFunctionResultCache::kEntriesIndex;
11778     }
11779   }
11780 
11781   ASSERT(index % 2 == 0);
11782   ASSERT(index >= JSFunctionResultCache::kEntriesIndex);
11783   ASSERT(index < cache_handle->length());
11784 
11785   cache_handle->set(index, *key_handle);
11786   cache_handle->set(index + 1, *value);
11787   cache_handle->set_finger_index(index);
11788 
11789 #ifdef DEBUG
11790   cache_handle->JSFunctionResultCacheVerify();
11791 #endif
11792 
11793   return *value;
11794 }
11795 
11796 
RUNTIME_FUNCTION(MaybeObject *,Runtime_NewMessageObject)11797 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewMessageObject) {
11798   HandleScope scope(isolate);
11799   CONVERT_ARG_CHECKED(String, type, 0);
11800   CONVERT_ARG_CHECKED(JSArray, arguments, 1);
11801   return *isolate->factory()->NewJSMessageObject(
11802       type,
11803       arguments,
11804       0,
11805       0,
11806       isolate->factory()->undefined_value(),
11807       isolate->factory()->undefined_value(),
11808       isolate->factory()->undefined_value());
11809 }
11810 
11811 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MessageGetType)11812 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetType) {
11813   CONVERT_CHECKED(JSMessageObject, message, args[0]);
11814   return message->type();
11815 }
11816 
11817 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MessageGetArguments)11818 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetArguments) {
11819   CONVERT_CHECKED(JSMessageObject, message, args[0]);
11820   return message->arguments();
11821 }
11822 
11823 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MessageGetStartPosition)11824 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetStartPosition) {
11825   CONVERT_CHECKED(JSMessageObject, message, args[0]);
11826   return Smi::FromInt(message->start_position());
11827 }
11828 
11829 
RUNTIME_FUNCTION(MaybeObject *,Runtime_MessageGetScript)11830 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetScript) {
11831   CONVERT_CHECKED(JSMessageObject, message, args[0]);
11832   return message->script();
11833 }
11834 
11835 
11836 #ifdef DEBUG
11837 // ListNatives is ONLY used by the fuzz-natives.js in debug mode
11838 // Exclude the code in release mode.
RUNTIME_FUNCTION(MaybeObject *,Runtime_ListNatives)11839 RUNTIME_FUNCTION(MaybeObject*, Runtime_ListNatives) {
11840   ASSERT(args.length() == 0);
11841   HandleScope scope;
11842 #define COUNT_ENTRY(Name, argc, ressize) + 1
11843   int entry_count = 0
11844       RUNTIME_FUNCTION_LIST(COUNT_ENTRY)
11845       INLINE_FUNCTION_LIST(COUNT_ENTRY)
11846       INLINE_RUNTIME_FUNCTION_LIST(COUNT_ENTRY);
11847 #undef COUNT_ENTRY
11848   Factory* factory = isolate->factory();
11849   Handle<FixedArray> elements = factory->NewFixedArray(entry_count);
11850   int index = 0;
11851   bool inline_runtime_functions = false;
11852 #define ADD_ENTRY(Name, argc, ressize)                                       \
11853   {                                                                          \
11854     HandleScope inner;                                                       \
11855     Handle<String> name;                                                     \
11856     /* Inline runtime functions have an underscore in front of the name. */  \
11857     if (inline_runtime_functions) {                                          \
11858       name = factory->NewStringFromAscii(                                    \
11859           Vector<const char>("_" #Name, StrLength("_" #Name)));              \
11860     } else {                                                                 \
11861       name = factory->NewStringFromAscii(                                    \
11862           Vector<const char>(#Name, StrLength(#Name)));                      \
11863     }                                                                        \
11864     Handle<FixedArray> pair_elements = factory->NewFixedArray(2);            \
11865     pair_elements->set(0, *name);                                            \
11866     pair_elements->set(1, Smi::FromInt(argc));                               \
11867     Handle<JSArray> pair = factory->NewJSArrayWithElements(pair_elements);   \
11868     elements->set(index++, *pair);                                           \
11869   }
11870   inline_runtime_functions = false;
11871   RUNTIME_FUNCTION_LIST(ADD_ENTRY)
11872   inline_runtime_functions = true;
11873   INLINE_FUNCTION_LIST(ADD_ENTRY)
11874   INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY)
11875 #undef ADD_ENTRY
11876   ASSERT_EQ(index, entry_count);
11877   Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
11878   return *result;
11879 }
11880 #endif
11881 
11882 
RUNTIME_FUNCTION(MaybeObject *,Runtime_Log)11883 RUNTIME_FUNCTION(MaybeObject*, Runtime_Log) {
11884   ASSERT(args.length() == 2);
11885   CONVERT_CHECKED(String, format, args[0]);
11886   CONVERT_CHECKED(JSArray, elms, args[1]);
11887   Vector<const char> chars = format->ToAsciiVector();
11888   LOGGER->LogRuntime(chars, elms);
11889   return isolate->heap()->undefined_value();
11890 }
11891 
11892 
RUNTIME_FUNCTION(MaybeObject *,Runtime_IS_VAR)11893 RUNTIME_FUNCTION(MaybeObject*, Runtime_IS_VAR) {
11894   UNREACHABLE();  // implemented as macro in the parser
11895   return NULL;
11896 }
11897 
11898 
11899 // ----------------------------------------------------------------------------
11900 // Implementation of Runtime
11901 
11902 #define F(name, number_of_args, result_size)                             \
11903   { Runtime::k##name, Runtime::RUNTIME, #name,   \
11904     FUNCTION_ADDR(Runtime_##name), number_of_args, result_size },
11905 
11906 
11907 #define I(name, number_of_args, result_size)                             \
11908   { Runtime::kInline##name, Runtime::INLINE,     \
11909     "_" #name, NULL, number_of_args, result_size },
11910 
11911 static const Runtime::Function kIntrinsicFunctions[] = {
11912   RUNTIME_FUNCTION_LIST(F)
11913   INLINE_FUNCTION_LIST(I)
11914   INLINE_RUNTIME_FUNCTION_LIST(I)
11915 };
11916 
11917 
InitializeIntrinsicFunctionNames(Heap * heap,Object * dictionary)11918 MaybeObject* Runtime::InitializeIntrinsicFunctionNames(Heap* heap,
11919                                                        Object* dictionary) {
11920   ASSERT(Isolate::Current()->heap() == heap);
11921   ASSERT(dictionary != NULL);
11922   ASSERT(StringDictionary::cast(dictionary)->NumberOfElements() == 0);
11923   for (int i = 0; i < kNumFunctions; ++i) {
11924     Object* name_symbol;
11925     { MaybeObject* maybe_name_symbol =
11926           heap->LookupAsciiSymbol(kIntrinsicFunctions[i].name);
11927       if (!maybe_name_symbol->ToObject(&name_symbol)) return maybe_name_symbol;
11928     }
11929     StringDictionary* string_dictionary = StringDictionary::cast(dictionary);
11930     { MaybeObject* maybe_dictionary = string_dictionary->Add(
11931           String::cast(name_symbol),
11932           Smi::FromInt(i),
11933           PropertyDetails(NONE, NORMAL));
11934       if (!maybe_dictionary->ToObject(&dictionary)) {
11935         // Non-recoverable failure.  Calling code must restart heap
11936         // initialization.
11937         return maybe_dictionary;
11938       }
11939     }
11940   }
11941   return dictionary;
11942 }
11943 
11944 
FunctionForSymbol(Handle<String> name)11945 const Runtime::Function* Runtime::FunctionForSymbol(Handle<String> name) {
11946   Heap* heap = name->GetHeap();
11947   int entry = heap->intrinsic_function_names()->FindEntry(*name);
11948   if (entry != kNotFound) {
11949     Object* smi_index = heap->intrinsic_function_names()->ValueAt(entry);
11950     int function_index = Smi::cast(smi_index)->value();
11951     return &(kIntrinsicFunctions[function_index]);
11952   }
11953   return NULL;
11954 }
11955 
11956 
FunctionForId(Runtime::FunctionId id)11957 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
11958   return &(kIntrinsicFunctions[static_cast<int>(id)]);
11959 }
11960 
11961 
PerformGC(Object * result)11962 void Runtime::PerformGC(Object* result) {
11963   Isolate* isolate = Isolate::Current();
11964   Failure* failure = Failure::cast(result);
11965   if (failure->IsRetryAfterGC()) {
11966     // Try to do a garbage collection; ignore it if it fails. The C
11967     // entry stub will throw an out-of-memory exception in that case.
11968     isolate->heap()->CollectGarbage(failure->allocation_space());
11969   } else {
11970     // Handle last resort GC and make sure to allow future allocations
11971     // to grow the heap without causing GCs (if possible).
11972     isolate->counters()->gc_last_resort_from_js()->Increment();
11973     isolate->heap()->CollectAllGarbage(false);
11974   }
11975 }
11976 
11977 
11978 } }  // namespace v8::internal
11979