v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
runtime.cc
Go to the documentation of this file.
1 // Copyright 2012 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 "bootstrapper.h"
36 #include "codegen.h"
37 #include "compilation-cache.h"
38 #include "compiler.h"
39 #include "cpu.h"
40 #include "dateparser-inl.h"
41 #include "debug.h"
42 #include "deoptimizer.h"
43 #include "date.h"
44 #include "execution.h"
45 #include "global-handles.h"
46 #include "isolate-inl.h"
47 #include "jsregexp.h"
48 #include "json-parser.h"
49 #include "liveedit.h"
50 #include "liveobjectlist-inl.h"
51 #include "misc-intrinsics.h"
52 #include "parser.h"
53 #include "platform.h"
54 #include "runtime-profiler.h"
55 #include "runtime.h"
56 #include "scopeinfo.h"
57 #include "smart-pointers.h"
58 #include "string-search.h"
59 #include "stub-cache.h"
60 #include "v8threads.h"
61 #include "vm-state-inl.h"
62 
63 namespace v8 {
64 namespace internal {
65 
66 
67 #define RUNTIME_ASSERT(value) \
68  if (!(value)) return isolate->ThrowIllegalOperation();
69 
70 // Cast the given object to a value of the specified type and store
71 // it in a variable with the given name. If the object is not of the
72 // expected type call IllegalOperation and return.
73 #define CONVERT_ARG_CHECKED(Type, name, index) \
74  RUNTIME_ASSERT(args[index]->Is##Type()); \
75  Type* name = Type::cast(args[index]);
76 
77 #define CONVERT_ARG_HANDLE_CHECKED(Type, name, index) \
78  RUNTIME_ASSERT(args[index]->Is##Type()); \
79  Handle<Type> name = args.at<Type>(index);
80 
81 // Cast the given object to a boolean and store it in a variable with
82 // the given name. If the object is not a boolean call IllegalOperation
83 // and return.
84 #define CONVERT_BOOLEAN_ARG_CHECKED(name, index) \
85  RUNTIME_ASSERT(args[index]->IsBoolean()); \
86  bool name = args[index]->IsTrue();
87 
88 // Cast the given argument to a Smi and store its value in an int variable
89 // with the given name. If the argument is not a Smi call IllegalOperation
90 // and return.
91 #define CONVERT_SMI_ARG_CHECKED(name, index) \
92  RUNTIME_ASSERT(args[index]->IsSmi()); \
93  int name = args.smi_at(index);
94 
95 // Cast the given argument to a double and store it in a variable with
96 // the given name. If the argument is not a number (as opposed to
97 // the number not-a-number) call IllegalOperation and return.
98 #define CONVERT_DOUBLE_ARG_CHECKED(name, index) \
99  RUNTIME_ASSERT(args[index]->IsNumber()); \
100  double name = args.number_at(index);
101 
102 // Call the specified converter on the object *comand store the result in
103 // a variable of the specified type with the given name. If the
104 // object is not a Number call IllegalOperation and return.
105 #define CONVERT_NUMBER_CHECKED(type, name, Type, obj) \
106  RUNTIME_ASSERT(obj->IsNumber()); \
107  type name = NumberTo##Type(obj);
108 
109 
110 // Cast the given argument to PropertyDetails and store its value in a
111 // variable with the given name. If the argument is not a Smi call
112 // IllegalOperation and return.
113 #define CONVERT_PROPERTY_DETAILS_CHECKED(name, index) \
114  RUNTIME_ASSERT(args[index]->IsSmi()); \
115  PropertyDetails name = PropertyDetails(Smi::cast(args[index]));
116 
117 
118 // Assert that the given argument has a valid value for a StrictModeFlag
119 // and store it in a StrictModeFlag variable with the given name.
120 #define CONVERT_STRICT_MODE_ARG_CHECKED(name, index) \
121  RUNTIME_ASSERT(args[index]->IsSmi()); \
122  RUNTIME_ASSERT(args.smi_at(index) == kStrictMode || \
123  args.smi_at(index) == kNonStrictMode); \
124  StrictModeFlag name = \
125  static_cast<StrictModeFlag>(args.smi_at(index));
126 
127 
128 // Assert that the given argument has a valid value for a LanguageMode
129 // and store it in a LanguageMode variable with the given name.
130 #define CONVERT_LANGUAGE_MODE_ARG(name, index) \
131  ASSERT(args[index]->IsSmi()); \
132  ASSERT(args.smi_at(index) == CLASSIC_MODE || \
133  args.smi_at(index) == STRICT_MODE || \
134  args.smi_at(index) == EXTENDED_MODE); \
135  LanguageMode name = \
136  static_cast<LanguageMode>(args.smi_at(index));
137 
138 
139 MUST_USE_RESULT static MaybeObject* DeepCopyBoilerplate(Isolate* isolate,
140  JSObject* boilerplate) {
141  StackLimitCheck check(isolate);
142  if (check.HasOverflowed()) return isolate->StackOverflow();
143 
144  Heap* heap = isolate->heap();
145  Object* result;
146  { MaybeObject* maybe_result = heap->CopyJSObject(boilerplate);
147  if (!maybe_result->ToObject(&result)) return maybe_result;
148  }
149  JSObject* copy = JSObject::cast(result);
150 
151  // Deep copy local properties.
152  if (copy->HasFastProperties()) {
153  FixedArray* properties = copy->properties();
154  for (int i = 0; i < properties->length(); i++) {
155  Object* value = properties->get(i);
156  if (value->IsJSObject()) {
157  JSObject* js_object = JSObject::cast(value);
158  { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
159  if (!maybe_result->ToObject(&result)) return maybe_result;
160  }
161  properties->set(i, result);
162  }
163  }
164  int nof = copy->map()->inobject_properties();
165  for (int i = 0; i < nof; i++) {
166  Object* value = copy->InObjectPropertyAt(i);
167  if (value->IsJSObject()) {
168  JSObject* js_object = JSObject::cast(value);
169  { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
170  if (!maybe_result->ToObject(&result)) return maybe_result;
171  }
172  copy->InObjectPropertyAtPut(i, result);
173  }
174  }
175  } else {
176  { MaybeObject* maybe_result =
177  heap->AllocateFixedArray(copy->NumberOfLocalProperties());
178  if (!maybe_result->ToObject(&result)) return maybe_result;
179  }
180  FixedArray* names = FixedArray::cast(result);
181  copy->GetLocalPropertyNames(names, 0);
182  for (int i = 0; i < names->length(); i++) {
183  ASSERT(names->get(i)->IsString());
184  String* key_string = String::cast(names->get(i));
185  PropertyAttributes attributes =
186  copy->GetLocalPropertyAttribute(key_string);
187  // Only deep copy fields from the object literal expression.
188  // In particular, don't try to copy the length attribute of
189  // an array.
190  if (attributes != NONE) continue;
191  Object* value =
192  copy->GetProperty(key_string, &attributes)->ToObjectUnchecked();
193  if (value->IsJSObject()) {
194  JSObject* js_object = JSObject::cast(value);
195  { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
196  if (!maybe_result->ToObject(&result)) return maybe_result;
197  }
198  { MaybeObject* maybe_result =
199  // Creating object copy for literals. No strict mode needed.
200  copy->SetProperty(key_string, result, NONE, kNonStrictMode);
201  if (!maybe_result->ToObject(&result)) return maybe_result;
202  }
203  }
204  }
205  }
206 
207  // Deep copy local elements.
208  // Pixel elements cannot be created using an object literal.
209  ASSERT(!copy->HasExternalArrayElements());
210  switch (copy->GetElementsKind()) {
211  case FAST_SMI_ELEMENTS:
212  case FAST_ELEMENTS:
214  case FAST_HOLEY_ELEMENTS: {
215  FixedArray* elements = FixedArray::cast(copy->elements());
216  if (elements->map() == heap->fixed_cow_array_map()) {
217  isolate->counters()->cow_arrays_created_runtime()->Increment();
218 #ifdef DEBUG
219  for (int i = 0; i < elements->length(); i++) {
220  ASSERT(!elements->get(i)->IsJSObject());
221  }
222 #endif
223  } else {
224  for (int i = 0; i < elements->length(); i++) {
225  Object* value = elements->get(i);
226  ASSERT(value->IsSmi() ||
227  value->IsTheHole() ||
228  (IsFastObjectElementsKind(copy->GetElementsKind())));
229  if (value->IsJSObject()) {
230  JSObject* js_object = JSObject::cast(value);
231  { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate,
232  js_object);
233  if (!maybe_result->ToObject(&result)) return maybe_result;
234  }
235  elements->set(i, result);
236  }
237  }
238  }
239  break;
240  }
241  case DICTIONARY_ELEMENTS: {
242  SeededNumberDictionary* element_dictionary = copy->element_dictionary();
243  int capacity = element_dictionary->Capacity();
244  for (int i = 0; i < capacity; i++) {
245  Object* k = element_dictionary->KeyAt(i);
246  if (element_dictionary->IsKey(k)) {
247  Object* value = element_dictionary->ValueAt(i);
248  if (value->IsJSObject()) {
249  JSObject* js_object = JSObject::cast(value);
250  { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate,
251  js_object);
252  if (!maybe_result->ToObject(&result)) return maybe_result;
253  }
254  element_dictionary->ValueAtPut(i, result);
255  }
256  }
257  }
258  break;
259  }
261  UNIMPLEMENTED();
262  break;
274  // No contained objects, nothing to do.
275  break;
276  }
277  return copy;
278 }
279 
280 
281 static Handle<Map> ComputeObjectLiteralMap(
282  Handle<Context> context,
283  Handle<FixedArray> constant_properties,
284  bool* is_result_from_cache) {
285  Isolate* isolate = context->GetIsolate();
286  int properties_length = constant_properties->length();
287  int number_of_properties = properties_length / 2;
288  // Check that there are only symbols and array indices among keys.
289  int number_of_symbol_keys = 0;
290  for (int p = 0; p != properties_length; p += 2) {
291  Object* key = constant_properties->get(p);
292  uint32_t element_index = 0;
293  if (key->IsSymbol()) {
294  number_of_symbol_keys++;
295  } else if (key->ToArrayIndex(&element_index)) {
296  // An index key does not require space in the property backing store.
297  number_of_properties--;
298  } else {
299  // Bail out as a non-symbol non-index key makes caching impossible.
300  // ASSERT to make sure that the if condition after the loop is false.
301  ASSERT(number_of_symbol_keys != number_of_properties);
302  break;
303  }
304  }
305  // If we only have symbols and array indices among keys then we can
306  // use the map cache in the native context.
307  const int kMaxKeys = 10;
308  if ((number_of_symbol_keys == number_of_properties) &&
309  (number_of_symbol_keys < kMaxKeys)) {
310  // Create the fixed array with the key.
311  Handle<FixedArray> keys =
312  isolate->factory()->NewFixedArray(number_of_symbol_keys);
313  if (number_of_symbol_keys > 0) {
314  int index = 0;
315  for (int p = 0; p < properties_length; p += 2) {
316  Object* key = constant_properties->get(p);
317  if (key->IsSymbol()) {
318  keys->set(index++, key);
319  }
320  }
321  ASSERT(index == number_of_symbol_keys);
322  }
323  *is_result_from_cache = true;
324  return isolate->factory()->ObjectLiteralMapFromCache(context, keys);
325  }
326  *is_result_from_cache = false;
327  return isolate->factory()->CopyMap(
328  Handle<Map>(context->object_function()->initial_map()),
329  number_of_properties);
330 }
331 
332 
333 static Handle<Object> CreateLiteralBoilerplate(
334  Isolate* isolate,
335  Handle<FixedArray> literals,
336  Handle<FixedArray> constant_properties);
337 
338 
339 static Handle<Object> CreateObjectLiteralBoilerplate(
340  Isolate* isolate,
341  Handle<FixedArray> literals,
342  Handle<FixedArray> constant_properties,
343  bool should_have_fast_elements,
344  bool has_function_literal) {
345  // Get the native context from the literals array. This is the
346  // context in which the function was created and we use the object
347  // function from this context to create the object literal. We do
348  // not use the object function from the current native context
349  // because this might be the object function from another context
350  // which we should not have access to.
351  Handle<Context> context =
352  Handle<Context>(JSFunction::NativeContextFromLiterals(*literals));
353 
354  // In case we have function literals, we want the object to be in
355  // slow properties mode for now. We don't go in the map cache because
356  // maps with constant functions can't be shared if the functions are
357  // not the same (which is the common case).
358  bool is_result_from_cache = false;
359  Handle<Map> map = has_function_literal
360  ? Handle<Map>(context->object_function()->initial_map())
361  : ComputeObjectLiteralMap(context,
362  constant_properties,
363  &is_result_from_cache);
364 
365  Handle<JSObject> boilerplate = isolate->factory()->NewJSObjectFromMap(map);
366 
367  // Normalize the elements of the boilerplate to save space if needed.
368  if (!should_have_fast_elements) JSObject::NormalizeElements(boilerplate);
369 
370  // Add the constant properties to the boilerplate.
371  int length = constant_properties->length();
372  bool should_transform =
373  !is_result_from_cache && boilerplate->HasFastProperties();
374  if (should_transform || has_function_literal) {
375  // Normalize the properties of object to avoid n^2 behavior
376  // when extending the object multiple properties. Indicate the number of
377  // properties to be added.
379  boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2);
380  }
381 
382  for (int index = 0; index < length; index +=2) {
383  Handle<Object> key(constant_properties->get(index+0), isolate);
384  Handle<Object> value(constant_properties->get(index+1), isolate);
385  if (value->IsFixedArray()) {
386  // The value contains the constant_properties of a
387  // simple object or array literal.
388  Handle<FixedArray> array = Handle<FixedArray>::cast(value);
389  value = CreateLiteralBoilerplate(isolate, literals, array);
390  if (value.is_null()) return value;
391  }
392  Handle<Object> result;
393  uint32_t element_index = 0;
394  if (key->IsSymbol()) {
395  if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
396  // Array index as string (uint32).
397  result = JSObject::SetOwnElement(
398  boilerplate, element_index, value, kNonStrictMode);
399  } else {
400  Handle<String> name(String::cast(*key));
401  ASSERT(!name->AsArrayIndex(&element_index));
403  boilerplate, name, value, NONE);
404  }
405  } else if (key->ToArrayIndex(&element_index)) {
406  // Array index (uint32).
407  result = JSObject::SetOwnElement(
408  boilerplate, element_index, value, kNonStrictMode);
409  } else {
410  // Non-uint32 number.
411  ASSERT(key->IsNumber());
412  double num = key->Number();
413  char arr[100];
414  Vector<char> buffer(arr, ARRAY_SIZE(arr));
415  const char* str = DoubleToCString(num, buffer);
416  Handle<String> name =
417  isolate->factory()->NewStringFromAscii(CStrVector(str));
419  boilerplate, name, value, NONE);
420  }
421  // If setting the property on the boilerplate throws an
422  // exception, the exception is converted to an empty handle in
423  // the handle based operations. In that case, we need to
424  // convert back to an exception.
425  if (result.is_null()) return result;
426  }
427 
428  // Transform to fast properties if necessary. For object literals with
429  // containing function literals we defer this operation until after all
430  // computed properties have been assigned so that we can generate
431  // constant function properties.
432  if (should_transform && !has_function_literal) {
434  boilerplate, boilerplate->map()->unused_property_fields());
435  }
436 
437  return boilerplate;
438 }
439 
440 
441 MaybeObject* TransitionElements(Handle<Object> object,
442  ElementsKind to_kind,
443  Isolate* isolate) {
444  HandleScope scope(isolate);
445  if (!object->IsJSObject()) return isolate->ThrowIllegalOperation();
446  ElementsKind from_kind =
447  Handle<JSObject>::cast(object)->map()->elements_kind();
448  if (Map::IsValidElementsTransition(from_kind, to_kind)) {
450  Handle<JSObject>::cast(object), to_kind);
451  if (result.is_null()) return isolate->ThrowIllegalOperation();
452  return *result;
453  }
454  return isolate->ThrowIllegalOperation();
455 }
456 
457 
458 static const int kSmiLiteralMinimumLength = 1024;
459 
460 
462  Isolate* isolate,
463  Handle<FixedArray> literals,
464  Handle<FixedArray> elements) {
465  // Create the JSArray.
466  Handle<JSFunction> constructor(
467  JSFunction::NativeContextFromLiterals(*literals)->array_function());
468  Handle<JSArray> object =
469  Handle<JSArray>::cast(isolate->factory()->NewJSObject(constructor));
470 
471  ElementsKind constant_elements_kind =
472  static_cast<ElementsKind>(Smi::cast(elements->get(0))->value());
473  Handle<FixedArrayBase> constant_elements_values(
474  FixedArrayBase::cast(elements->get(1)));
475 
476  ASSERT(IsFastElementsKind(constant_elements_kind));
477  Context* native_context = isolate->context()->native_context();
478  Object* maybe_maps_array = native_context->js_array_maps();
479  ASSERT(!maybe_maps_array->IsUndefined());
480  Object* maybe_map = FixedArray::cast(maybe_maps_array)->get(
481  constant_elements_kind);
482  ASSERT(maybe_map->IsMap());
483  object->set_map(Map::cast(maybe_map));
484 
485  Handle<FixedArrayBase> copied_elements_values;
486  if (IsFastDoubleElementsKind(constant_elements_kind)) {
487  ASSERT(FLAG_smi_only_arrays);
488  copied_elements_values = isolate->factory()->CopyFixedDoubleArray(
489  Handle<FixedDoubleArray>::cast(constant_elements_values));
490  } else {
491  ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind));
492  const bool is_cow =
493  (constant_elements_values->map() ==
494  isolate->heap()->fixed_cow_array_map());
495  if (is_cow) {
496  copied_elements_values = constant_elements_values;
497 #if DEBUG
498  Handle<FixedArray> fixed_array_values =
499  Handle<FixedArray>::cast(copied_elements_values);
500  for (int i = 0; i < fixed_array_values->length(); i++) {
501  ASSERT(!fixed_array_values->get(i)->IsFixedArray());
502  }
503 #endif
504  } else {
505  Handle<FixedArray> fixed_array_values =
506  Handle<FixedArray>::cast(constant_elements_values);
507  Handle<FixedArray> fixed_array_values_copy =
508  isolate->factory()->CopyFixedArray(fixed_array_values);
509  copied_elements_values = fixed_array_values_copy;
510  for (int i = 0; i < fixed_array_values->length(); i++) {
511  Object* current = fixed_array_values->get(i);
512  if (current->IsFixedArray()) {
513  // The value contains the constant_properties of a
514  // simple object or array literal.
515  Handle<FixedArray> fa(FixedArray::cast(fixed_array_values->get(i)));
516  Handle<Object> result =
517  CreateLiteralBoilerplate(isolate, literals, fa);
518  if (result.is_null()) return result;
519  fixed_array_values_copy->set(i, *result);
520  }
521  }
522  }
523  }
524  object->set_elements(*copied_elements_values);
525  object->set_length(Smi::FromInt(copied_elements_values->length()));
526 
527  // Ensure that the boilerplate object has FAST_*_ELEMENTS, unless the flag is
528  // on or the object is larger than the threshold.
529  if (!FLAG_smi_only_arrays &&
530  constant_elements_values->length() < kSmiLiteralMinimumLength) {
531  ElementsKind elements_kind = object->GetElementsKind();
532  if (!IsFastObjectElementsKind(elements_kind)) {
533  if (IsFastHoleyElementsKind(elements_kind)) {
535  isolate)->IsFailure());
536  } else {
537  CHECK(!TransitionElements(object, FAST_ELEMENTS, isolate)->IsFailure());
538  }
539  }
540  }
541 
542  object->ValidateElements();
543  return object;
544 }
545 
546 
547 static Handle<Object> CreateLiteralBoilerplate(
548  Isolate* isolate,
549  Handle<FixedArray> literals,
550  Handle<FixedArray> array) {
552  const bool kHasNoFunctionLiteral = false;
553  switch (CompileTimeValue::GetType(array)) {
555  return CreateObjectLiteralBoilerplate(isolate,
556  literals,
557  elements,
558  true,
559  kHasNoFunctionLiteral);
561  return CreateObjectLiteralBoilerplate(isolate,
562  literals,
563  elements,
564  false,
565  kHasNoFunctionLiteral);
568  isolate, literals, elements);
569  default:
570  UNREACHABLE();
571  return Handle<Object>::null();
572  }
573 }
574 
575 
576 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteral) {
577  HandleScope scope(isolate);
578  ASSERT(args.length() == 4);
580  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
581  CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2);
583  bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
584  bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
585 
586  // Check if boilerplate exists. If not, create it first.
587  Handle<Object> boilerplate(literals->get(literals_index), isolate);
588  if (*boilerplate == isolate->heap()->undefined_value()) {
589  boilerplate = CreateObjectLiteralBoilerplate(isolate,
590  literals,
591  constant_properties,
592  should_have_fast_elements,
593  has_function_literal);
594  if (boilerplate.is_null()) return Failure::Exception();
595  // Update the functions literal and return the boilerplate.
596  literals->set(literals_index, *boilerplate);
597  }
598  return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate));
599 }
600 
601 
602 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteralShallow) {
603  HandleScope scope(isolate);
604  ASSERT(args.length() == 4);
606  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
607  CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2);
609  bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
610  bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
611 
612  // Check if boilerplate exists. If not, create it first.
613  Handle<Object> boilerplate(literals->get(literals_index), isolate);
614  if (*boilerplate == isolate->heap()->undefined_value()) {
615  boilerplate = CreateObjectLiteralBoilerplate(isolate,
616  literals,
617  constant_properties,
618  should_have_fast_elements,
619  has_function_literal);
620  if (boilerplate.is_null()) return Failure::Exception();
621  // Update the functions literal and return the boilerplate.
622  literals->set(literals_index, *boilerplate);
623  }
624  return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate));
625 }
626 
627 
628 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteral) {
629  HandleScope scope(isolate);
630  ASSERT(args.length() == 3);
632  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
634 
635  // Check if boilerplate exists. If not, create it first.
636  Handle<Object> boilerplate(literals->get(literals_index), isolate);
637  if (*boilerplate == isolate->heap()->undefined_value()) {
638  ASSERT(*elements != isolate->heap()->empty_fixed_array());
639  boilerplate =
640  Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
641  if (boilerplate.is_null()) return Failure::Exception();
642  // Update the functions literal and return the boilerplate.
643  literals->set(literals_index, *boilerplate);
644  }
645  return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate));
646 }
647 
648 
649 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralShallow) {
650  HandleScope scope(isolate);
651  ASSERT(args.length() == 3);
653  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
655 
656  // Check if boilerplate exists. If not, create it first.
657  Handle<Object> boilerplate(literals->get(literals_index), isolate);
658  if (*boilerplate == isolate->heap()->undefined_value()) {
659  ASSERT(*elements != isolate->heap()->empty_fixed_array());
660  boilerplate =
661  Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
662  if (boilerplate.is_null()) return Failure::Exception();
663  // Update the functions literal and return the boilerplate.
664  literals->set(literals_index, *boilerplate);
665  }
666  if (JSObject::cast(*boilerplate)->elements()->map() ==
667  isolate->heap()->fixed_cow_array_map()) {
668  isolate->counters()->cow_arrays_created_runtime()->Increment();
669  }
670  return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate));
671 }
672 
673 
674 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSProxy) {
675  ASSERT(args.length() == 2);
676  CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
677  Object* prototype = args[1];
678  Object* used_prototype =
679  prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
680  return isolate->heap()->AllocateJSProxy(handler, used_prototype);
681 }
682 
683 
684 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSFunctionProxy) {
685  ASSERT(args.length() == 4);
686  CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
687  Object* call_trap = args[1];
688  RUNTIME_ASSERT(call_trap->IsJSFunction() || call_trap->IsJSFunctionProxy());
689  CONVERT_ARG_CHECKED(JSFunction, construct_trap, 2);
690  Object* prototype = args[3];
691  Object* used_prototype =
692  prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
693  return isolate->heap()->AllocateJSFunctionProxy(
694  handler, call_trap, construct_trap, used_prototype);
695 }
696 
697 
698 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSProxy) {
699  ASSERT(args.length() == 1);
700  Object* obj = args[0];
701  return isolate->heap()->ToBoolean(obj->IsJSProxy());
702 }
703 
704 
705 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSFunctionProxy) {
706  ASSERT(args.length() == 1);
707  Object* obj = args[0];
708  return isolate->heap()->ToBoolean(obj->IsJSFunctionProxy());
709 }
710 
711 
712 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHandler) {
713  ASSERT(args.length() == 1);
714  CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
715  return proxy->handler();
716 }
717 
718 
719 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetCallTrap) {
720  ASSERT(args.length() == 1);
722  return proxy->call_trap();
723 }
724 
725 
726 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructTrap) {
727  ASSERT(args.length() == 1);
729  return proxy->construct_trap();
730 }
731 
732 
733 RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) {
734  ASSERT(args.length() == 1);
735  CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
736  proxy->Fix();
737  return isolate->heap()->undefined_value();
738 }
739 
740 
741 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInitialize) {
742  HandleScope scope(isolate);
743  ASSERT(args.length() == 1);
744  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
745  Handle<ObjectHashSet> table = isolate->factory()->NewObjectHashSet(0);
746  holder->set_table(*table);
747  return *holder;
748 }
749 
750 
751 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAdd) {
752  HandleScope scope(isolate);
753  ASSERT(args.length() == 2);
754  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
755  Handle<Object> key(args[1]);
756  Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
757  table = ObjectHashSetAdd(table, key);
758  holder->set_table(*table);
759  return isolate->heap()->undefined_value();
760 }
761 
762 
763 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetHas) {
764  HandleScope scope(isolate);
765  ASSERT(args.length() == 2);
766  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
767  Handle<Object> key(args[1]);
768  Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
769  return isolate->heap()->ToBoolean(table->Contains(*key));
770 }
771 
772 
773 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDelete) {
774  HandleScope scope(isolate);
775  ASSERT(args.length() == 2);
776  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
777  Handle<Object> key(args[1]);
778  Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
779  table = ObjectHashSetRemove(table, key);
780  holder->set_table(*table);
781  return isolate->heap()->undefined_value();
782 }
783 
784 
785 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapInitialize) {
786  HandleScope scope(isolate);
787  ASSERT(args.length() == 1);
788  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
789  Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
790  holder->set_table(*table);
791  return *holder;
792 }
793 
794 
795 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGet) {
796  HandleScope scope(isolate);
797  ASSERT(args.length() == 2);
798  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
800  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
801  Handle<Object> lookup(table->Lookup(*key));
802  return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
803 }
804 
805 
806 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapHas) {
807  HandleScope scope(isolate);
808  ASSERT(args.length() == 2);
809  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
811  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
812  Handle<Object> lookup(table->Lookup(*key));
813  return isolate->heap()->ToBoolean(!lookup->IsTheHole());
814 }
815 
816 
817 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapDelete) {
818  HandleScope scope(isolate);
819  ASSERT(args.length() == 2);
820  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
822  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
823  Handle<Object> lookup(table->Lookup(*key));
824  Handle<ObjectHashTable> new_table =
825  PutIntoObjectHashTable(table, key, isolate->factory()->the_hole_value());
826  holder->set_table(*new_table);
827  return isolate->heap()->ToBoolean(!lookup->IsTheHole());
828 }
829 
830 
831 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapSet) {
832  HandleScope scope(isolate);
833  ASSERT(args.length() == 3);
834  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
837  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
838  Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
839  holder->set_table(*new_table);
840  return isolate->heap()->undefined_value();
841 }
842 
843 
844 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapInitialize) {
845  HandleScope scope(isolate);
846  ASSERT(args.length() == 1);
848  ASSERT(weakmap->map()->inobject_properties() == 0);
849  Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
850  weakmap->set_table(*table);
851  weakmap->set_next(Smi::FromInt(0));
852  return *weakmap;
853 }
854 
855 
856 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapGet) {
857  HandleScope scope(isolate);
858  ASSERT(args.length() == 2);
861  Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table()));
862  Handle<Object> lookup(table->Lookup(*key));
863  return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
864 }
865 
866 
867 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapHas) {
868  HandleScope scope(isolate);
869  ASSERT(args.length() == 2);
872  Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table()));
873  Handle<Object> lookup(table->Lookup(*key));
874  return isolate->heap()->ToBoolean(!lookup->IsTheHole());
875 }
876 
877 
878 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapDelete) {
879  HandleScope scope(isolate);
880  ASSERT(args.length() == 2);
883  Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table()));
884  Handle<Object> lookup(table->Lookup(*key));
885  Handle<ObjectHashTable> new_table =
886  PutIntoObjectHashTable(table, key, isolate->factory()->the_hole_value());
887  weakmap->set_table(*new_table);
888  return isolate->heap()->ToBoolean(!lookup->IsTheHole());
889 }
890 
891 
892 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapSet) {
893  HandleScope scope(isolate);
894  ASSERT(args.length() == 3);
897  Handle<Object> value(args[2]);
898  Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table()));
899  Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
900  weakmap->set_table(*new_table);
901  return isolate->heap()->undefined_value();
902 }
903 
904 
905 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) {
906  NoHandleAllocation ha;
907  ASSERT(args.length() == 1);
908  Object* obj = args[0];
909  if (!obj->IsJSObject()) return isolate->heap()->null_value();
910  return JSObject::cast(obj)->class_name();
911 }
912 
913 
914 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) {
915  NoHandleAllocation ha;
916  ASSERT(args.length() == 1);
917  CONVERT_ARG_CHECKED(JSReceiver, input_obj, 0);
918  Object* obj = input_obj;
919  // We don't expect access checks to be needed on JSProxy objects.
920  ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
921  do {
922  if (obj->IsAccessCheckNeeded() &&
923  !isolate->MayNamedAccess(JSObject::cast(obj),
924  isolate->heap()->Proto_symbol(),
925  v8::ACCESS_GET)) {
927  return isolate->heap()->undefined_value();
928  }
929  obj = obj->GetPrototype();
930  } while (obj->IsJSObject() &&
932  return obj;
933 }
934 
935 
936 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) {
937  NoHandleAllocation ha;
938  ASSERT(args.length() == 2);
939  // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
940  Object* O = args[0];
941  Object* V = args[1];
942  while (true) {
943  Object* prototype = V->GetPrototype();
944  if (prototype->IsNull()) return isolate->heap()->false_value();
945  if (O == prototype) return isolate->heap()->true_value();
946  V = prototype;
947  }
948 }
949 
950 
951 // Recursively traverses hidden prototypes if property is not found
952 static void GetOwnPropertyImplementation(JSObject* obj,
953  String* name,
954  LookupResult* result) {
955  obj->LocalLookupRealNamedProperty(name, result);
956 
957  if (result->IsFound()) return;
958 
959  Object* proto = obj->GetPrototype();
960  if (proto->IsJSObject() &&
962  GetOwnPropertyImplementation(JSObject::cast(proto),
963  name, result);
964 }
965 
966 
967 static bool CheckAccessException(LookupResult* result,
968  v8::AccessType access_type) {
969  if (result->type() == CALLBACKS) {
970  Object* callback = result->GetCallbackObject();
971  if (callback->IsAccessorInfo()) {
972  AccessorInfo* info = AccessorInfo::cast(callback);
973  bool can_access =
974  (access_type == v8::ACCESS_HAS &&
975  (info->all_can_read() || info->all_can_write())) ||
976  (access_type == v8::ACCESS_GET && info->all_can_read()) ||
977  (access_type == v8::ACCESS_SET && info->all_can_write());
978  return can_access;
979  }
980  }
981 
982  return false;
983 }
984 
985 
986 static bool CheckAccess(JSObject* obj,
987  String* name,
988  LookupResult* result,
989  v8::AccessType access_type) {
990  ASSERT(result->IsProperty());
991 
992  JSObject* holder = result->holder();
993  JSObject* current = obj;
994  Isolate* isolate = obj->GetIsolate();
995  while (true) {
996  if (current->IsAccessCheckNeeded() &&
997  !isolate->MayNamedAccess(current, name, access_type)) {
998  // Access check callback denied the access, but some properties
999  // can have a special permissions which override callbacks descision
1000  // (currently see v8::AccessControl).
1001  break;
1002  }
1003 
1004  if (current == holder) {
1005  return true;
1006  }
1007 
1008  current = JSObject::cast(current->GetPrototype());
1009  }
1010 
1011  // API callbacks can have per callback access exceptions.
1012  switch (result->type()) {
1013  case CALLBACKS: {
1014  if (CheckAccessException(result, access_type)) {
1015  return true;
1016  }
1017  break;
1018  }
1019  case INTERCEPTOR: {
1020  // If the object has an interceptor, try real named properties.
1021  // Overwrite the result to fetch the correct property later.
1022  holder->LookupRealNamedProperty(name, result);
1023  if (result->IsProperty()) {
1024  if (CheckAccessException(result, access_type)) {
1025  return true;
1026  }
1027  }
1028  break;
1029  }
1030  default:
1031  break;
1032  }
1033 
1034  isolate->ReportFailedAccessCheck(current, access_type);
1035  return false;
1036 }
1037 
1038 
1039 // TODO(1095): we should traverse hidden prototype hierachy as well.
1040 static bool CheckElementAccess(JSObject* obj,
1041  uint32_t index,
1042  v8::AccessType access_type) {
1043  if (obj->IsAccessCheckNeeded() &&
1044  !obj->GetIsolate()->MayIndexedAccess(obj, index, access_type)) {
1045  return false;
1046  }
1047 
1048  return true;
1049 }
1050 
1051 
1052 // Enumerator used as indices into the array returned from GetOwnProperty
1062 };
1063 
1064 
1065 static MaybeObject* GetOwnProperty(Isolate* isolate,
1066  Handle<JSObject> obj,
1067  Handle<String> name) {
1068  Heap* heap = isolate->heap();
1069  Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
1070  Handle<JSArray> desc = isolate->factory()->NewJSArrayWithElements(elms);
1071  LookupResult result(isolate);
1072  // This could be an element.
1073  uint32_t index;
1074  if (name->AsArrayIndex(&index)) {
1075  switch (obj->HasLocalElement(index)) {
1077  return heap->undefined_value();
1078 
1080  // Special handling of string objects according to ECMAScript 5
1081  // 15.5.5.2. Note that this might be a string object with elements
1082  // other than the actual string value. This is covered by the
1083  // subsequent cases.
1084  Handle<JSValue> js_value = Handle<JSValue>::cast(obj);
1085  Handle<String> str(String::cast(js_value->value()));
1086  Handle<String> substr = SubString(str, index, index + 1, NOT_TENURED);
1087 
1088  elms->set(IS_ACCESSOR_INDEX, heap->false_value());
1089  elms->set(VALUE_INDEX, *substr);
1090  elms->set(WRITABLE_INDEX, heap->false_value());
1091  elms->set(ENUMERABLE_INDEX, heap->true_value());
1092  elms->set(CONFIGURABLE_INDEX, heap->false_value());
1093  return *desc;
1094  }
1095 
1097  case JSObject::FAST_ELEMENT: {
1098  elms->set(IS_ACCESSOR_INDEX, heap->false_value());
1099  Handle<Object> value = Object::GetElement(obj, index);
1100  RETURN_IF_EMPTY_HANDLE(isolate, value);
1101  elms->set(VALUE_INDEX, *value);
1102  elms->set(WRITABLE_INDEX, heap->true_value());
1103  elms->set(ENUMERABLE_INDEX, heap->true_value());
1104  elms->set(CONFIGURABLE_INDEX, heap->true_value());
1105  return *desc;
1106  }
1107 
1109  Handle<JSObject> holder = obj;
1110  if (obj->IsJSGlobalProxy()) {
1111  Object* proto = obj->GetPrototype();
1112  if (proto->IsNull()) return heap->undefined_value();
1113  ASSERT(proto->IsJSGlobalObject());
1114  holder = Handle<JSObject>(JSObject::cast(proto));
1115  }
1116  FixedArray* elements = FixedArray::cast(holder->elements());
1117  SeededNumberDictionary* dictionary = NULL;
1118  if (elements->map() == heap->non_strict_arguments_elements_map()) {
1119  dictionary = SeededNumberDictionary::cast(elements->get(1));
1120  } else {
1121  dictionary = SeededNumberDictionary::cast(elements);
1122  }
1123  int entry = dictionary->FindEntry(index);
1125  PropertyDetails details = dictionary->DetailsAt(entry);
1126  switch (details.type()) {
1127  case CALLBACKS: {
1128  // This is an accessor property with getter and/or setter.
1129  AccessorPair* accessors =
1130  AccessorPair::cast(dictionary->ValueAt(entry));
1131  elms->set(IS_ACCESSOR_INDEX, heap->true_value());
1132  if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) {
1133  elms->set(GETTER_INDEX, accessors->GetComponent(ACCESSOR_GETTER));
1134  }
1135  if (CheckElementAccess(*obj, index, v8::ACCESS_SET)) {
1136  elms->set(SETTER_INDEX, accessors->GetComponent(ACCESSOR_SETTER));
1137  }
1138  break;
1139  }
1140  case NORMAL: {
1141  // This is a data property.
1142  elms->set(IS_ACCESSOR_INDEX, heap->false_value());
1143  Handle<Object> value = Object::GetElement(obj, index);
1144  ASSERT(!value.is_null());
1145  elms->set(VALUE_INDEX, *value);
1146  elms->set(WRITABLE_INDEX, heap->ToBoolean(!details.IsReadOnly()));
1147  break;
1148  }
1149  default:
1150  UNREACHABLE();
1151  break;
1152  }
1153  elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!details.IsDontEnum()));
1154  elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!details.IsDontDelete()));
1155  return *desc;
1156  }
1157  }
1158  }
1159 
1160  // Use recursive implementation to also traverse hidden prototypes
1161  GetOwnPropertyImplementation(*obj, *name, &result);
1162 
1163  if (!result.IsProperty()) {
1164  return heap->undefined_value();
1165  }
1166 
1167  if (!CheckAccess(*obj, *name, &result, v8::ACCESS_HAS)) {
1168  return heap->false_value();
1169  }
1170 
1171  elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!result.IsDontEnum()));
1172  elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!result.IsDontDelete()));
1173 
1174  bool is_js_accessor = result.IsPropertyCallbacks() &&
1175  (result.GetCallbackObject()->IsAccessorPair());
1176 
1177  if (is_js_accessor) {
1178  // __defineGetter__/__defineSetter__ callback.
1179  elms->set(IS_ACCESSOR_INDEX, heap->true_value());
1180 
1181  AccessorPair* accessors = AccessorPair::cast(result.GetCallbackObject());
1182  Object* getter = accessors->GetComponent(ACCESSOR_GETTER);
1183  if (!getter->IsMap() && CheckAccess(*obj, *name, &result, v8::ACCESS_GET)) {
1184  elms->set(GETTER_INDEX, getter);
1185  }
1186  Object* setter = accessors->GetComponent(ACCESSOR_SETTER);
1187  if (!setter->IsMap() && CheckAccess(*obj, *name, &result, v8::ACCESS_SET)) {
1188  elms->set(SETTER_INDEX, setter);
1189  }
1190  } else {
1191  elms->set(IS_ACCESSOR_INDEX, heap->false_value());
1192  elms->set(WRITABLE_INDEX, heap->ToBoolean(!result.IsReadOnly()));
1193 
1194  PropertyAttributes attrs;
1195  Object* value;
1196  // GetProperty will check access and report any violations.
1197  { MaybeObject* maybe_value = obj->GetProperty(*obj, &result, *name, &attrs);
1198  if (!maybe_value->ToObject(&value)) return maybe_value;
1199  }
1200  elms->set(VALUE_INDEX, value);
1201  }
1202 
1203  return *desc;
1204 }
1205 
1206 
1207 // Returns an array with the property description:
1208 // if args[1] is not a property on args[0]
1209 // returns undefined
1210 // if args[1] is a data property on args[0]
1211 // [false, value, Writeable, Enumerable, Configurable]
1212 // if args[1] is an accessor on args[0]
1213 // [true, GetFunction, SetFunction, Enumerable, Configurable]
1214 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) {
1215  ASSERT(args.length() == 2);
1216  HandleScope scope(isolate);
1219  return GetOwnProperty(isolate, obj, name);
1220 }
1221 
1222 
1223 RUNTIME_FUNCTION(MaybeObject*, Runtime_PreventExtensions) {
1224  ASSERT(args.length() == 1);
1225  CONVERT_ARG_CHECKED(JSObject, obj, 0);
1226  return obj->PreventExtensions();
1227 }
1228 
1229 
1230 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsExtensible) {
1231  ASSERT(args.length() == 1);
1232  CONVERT_ARG_CHECKED(JSObject, obj, 0);
1233  if (obj->IsJSGlobalProxy()) {
1234  Object* proto = obj->GetPrototype();
1235  if (proto->IsNull()) return isolate->heap()->false_value();
1236  ASSERT(proto->IsJSGlobalObject());
1237  obj = JSObject::cast(proto);
1238  }
1239  return isolate->heap()->ToBoolean(obj->map()->is_extensible());
1240 }
1241 
1242 
1243 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpCompile) {
1244  HandleScope scope(isolate);
1245  ASSERT(args.length() == 3);
1247  CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
1249  Handle<Object> result =
1250  RegExpImpl::Compile(re, pattern, flags, isolate->runtime_zone());
1251  if (result.is_null()) return Failure::Exception();
1252  return *result;
1253 }
1254 
1255 
1256 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateApiFunction) {
1257  HandleScope scope(isolate);
1258  ASSERT(args.length() == 1);
1260  return *isolate->factory()->CreateApiFunction(data);
1261 }
1262 
1263 
1264 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsTemplate) {
1265  ASSERT(args.length() == 1);
1266  Object* arg = args[0];
1267  bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
1268  return isolate->heap()->ToBoolean(result);
1269 }
1270 
1271 
1272 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetTemplateField) {
1273  ASSERT(args.length() == 2);
1274  CONVERT_ARG_CHECKED(HeapObject, templ, 0);
1275  CONVERT_SMI_ARG_CHECKED(index, 1)
1276  int offset = index * kPointerSize + HeapObject::kHeaderSize;
1277  InstanceType type = templ->map()->instance_type();
1279  type == OBJECT_TEMPLATE_INFO_TYPE);
1280  RUNTIME_ASSERT(offset > 0);
1281  if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
1283  } else {
1285  }
1286  return *HeapObject::RawField(templ, offset);
1287 }
1288 
1289 
1290 RUNTIME_FUNCTION(MaybeObject*, Runtime_DisableAccessChecks) {
1291  ASSERT(args.length() == 1);
1292  CONVERT_ARG_CHECKED(HeapObject, object, 0);
1293  Map* old_map = object->map();
1294  bool needs_access_checks = old_map->is_access_check_needed();
1295  if (needs_access_checks) {
1296  // Copy map so it won't interfere constructor's initial map.
1297  Map* new_map;
1298  MaybeObject* maybe_new_map = old_map->Copy();
1299  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
1300 
1301  new_map->set_is_access_check_needed(false);
1302  object->set_map(new_map);
1303  }
1304  return isolate->heap()->ToBoolean(needs_access_checks);
1305 }
1306 
1307 
1308 RUNTIME_FUNCTION(MaybeObject*, Runtime_EnableAccessChecks) {
1309  ASSERT(args.length() == 1);
1310  CONVERT_ARG_CHECKED(HeapObject, object, 0);
1311  Map* old_map = object->map();
1312  if (!old_map->is_access_check_needed()) {
1313  // Copy map so it won't interfere constructor's initial map.
1314  Map* new_map;
1315  MaybeObject* maybe_new_map = old_map->Copy();
1316  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
1317 
1318  new_map->set_is_access_check_needed(true);
1319  object->set_map(new_map);
1320  }
1321  return isolate->heap()->undefined_value();
1322 }
1323 
1324 
1325 static Failure* ThrowRedeclarationError(Isolate* isolate,
1326  const char* type,
1327  Handle<String> name) {
1328  HandleScope scope(isolate);
1329  Handle<Object> type_handle =
1330  isolate->factory()->NewStringFromAscii(CStrVector(type));
1331  Handle<Object> args[2] = { type_handle, name };
1332  Handle<Object> error =
1333  isolate->factory()->NewTypeError("redeclaration", HandleVector(args, 2));
1334  return isolate->Throw(*error);
1335 }
1336 
1337 
1338 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
1339  ASSERT(args.length() == 3);
1340  HandleScope scope(isolate);
1342  isolate->context()->global_object());
1343 
1344  Handle<Context> context = args.at<Context>(0);
1347 
1348  // Traverse the name/value pairs and set the properties.
1349  int length = pairs->length();
1350  for (int i = 0; i < length; i += 2) {
1351  HandleScope scope(isolate);
1352  Handle<String> name(String::cast(pairs->get(i)));
1353  Handle<Object> value(pairs->get(i + 1), isolate);
1354 
1355  // We have to declare a global const property. To capture we only
1356  // assign to it when evaluating the assignment for "const x =
1357  // <expr>" the initial value is the hole.
1358  bool is_var = value->IsUndefined();
1359  bool is_const = value->IsTheHole();
1360  bool is_function = value->IsSharedFunctionInfo();
1361  bool is_module = value->IsJSModule();
1362  ASSERT(is_var + is_const + is_function + is_module == 1);
1363 
1364  if (is_var || is_const) {
1365  // Lookup the property in the global object, and don't set the
1366  // value of the variable if the property is already there.
1367  // Do the lookup locally only, see ES5 erratum.
1368  LookupResult lookup(isolate);
1369  if (FLAG_es52_globals) {
1370  Object* obj = *global;
1371  do {
1372  JSObject::cast(obj)->LocalLookup(*name, &lookup);
1373  if (lookup.IsFound()) break;
1374  obj = obj->GetPrototype();
1375  } while (obj->IsJSObject() &&
1377  } else {
1378  global->Lookup(*name, &lookup);
1379  }
1380  if (lookup.IsFound()) {
1381  // We found an existing property. Unless it was an interceptor
1382  // that claims the property is absent, skip this declaration.
1383  if (!lookup.IsInterceptor()) continue;
1384  PropertyAttributes attributes = global->GetPropertyAttribute(*name);
1385  if (attributes != ABSENT) continue;
1386  // Fall-through and introduce the absent property by using
1387  // SetProperty.
1388  }
1389  } else if (is_function) {
1390  // Copy the function and update its context. Use it as value.
1393  Handle<JSFunction> function =
1394  isolate->factory()->NewFunctionFromSharedFunctionInfo(
1395  shared, context, TENURED);
1396  value = function;
1397  }
1398 
1399  LookupResult lookup(isolate);
1400  global->LocalLookup(*name, &lookup);
1401 
1402  // Compute the property attributes. According to ECMA-262,
1403  // the property must be non-configurable except in eval.
1404  int attr = NONE;
1405  bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
1406  if (!is_eval || is_module) {
1407  attr |= DONT_DELETE;
1408  }
1409  bool is_native = DeclareGlobalsNativeFlag::decode(flags);
1410  if (is_const || is_module || (is_native && is_function)) {
1411  attr |= READ_ONLY;
1412  }
1413 
1415 
1416  if (!lookup.IsFound() || is_function || is_module) {
1417  // If the local property exists, check that we can reconfigure it
1418  // as required for function declarations.
1419  if (lookup.IsFound() && lookup.IsDontDelete()) {
1420  if (lookup.IsReadOnly() || lookup.IsDontEnum() ||
1421  lookup.IsPropertyCallbacks()) {
1422  return ThrowRedeclarationError(
1423  isolate, is_function ? "function" : "module", name);
1424  }
1425  // If the existing property is not configurable, keep its attributes.
1426  attr = lookup.GetAttributes();
1427  }
1428  // Define or redefine own property.
1429  RETURN_IF_EMPTY_HANDLE(isolate,
1431  global, name, value, static_cast<PropertyAttributes>(attr)));
1432  } else {
1433  // Do a [[Put]] on the existing (own) property.
1434  RETURN_IF_EMPTY_HANDLE(isolate,
1436  global, name, value, static_cast<PropertyAttributes>(attr),
1437  language_mode == CLASSIC_MODE ? kNonStrictMode : kStrictMode));
1438  }
1439  }
1440 
1441  ASSERT(!isolate->has_pending_exception());
1442  return isolate->heap()->undefined_value();
1443 }
1444 
1445 
1446 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
1447  HandleScope scope(isolate);
1448  ASSERT(args.length() == 4);
1449 
1450  // Declarations are always made in a function or native context. In the
1451  // case of eval code, the context passed is the context of the caller,
1452  // which may be some nested context and not the declaration context.
1453  RUNTIME_ASSERT(args[0]->IsContext());
1454  Handle<Context> context(Context::cast(args[0])->declaration_context());
1455 
1456  Handle<String> name(String::cast(args[1]));
1457  PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2));
1458  RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE);
1459  Handle<Object> initial_value(args[3], isolate);
1460 
1461  int index;
1462  PropertyAttributes attributes;
1464  BindingFlags binding_flags;
1465  Handle<Object> holder =
1466  context->Lookup(name, flags, &index, &attributes, &binding_flags);
1467 
1468  if (attributes != ABSENT) {
1469  // The name was declared before; check for conflicting re-declarations.
1470  // Note: this is actually inconsistent with what happens for globals (where
1471  // we silently ignore such declarations).
1472  if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
1473  // Functions are not read-only.
1474  ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
1475  const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
1476  return ThrowRedeclarationError(isolate, type, name);
1477  }
1478 
1479  // Initialize it if necessary.
1480  if (*initial_value != NULL) {
1481  if (index >= 0) {
1482  ASSERT(holder.is_identical_to(context));
1483  if (((attributes & READ_ONLY) == 0) ||
1484  context->get(index)->IsTheHole()) {
1485  context->set(index, *initial_value);
1486  }
1487  } else {
1488  // Slow case: The property is in the context extension object of a
1489  // function context or the global object of a native context.
1490  Handle<JSObject> object = Handle<JSObject>::cast(holder);
1492  isolate,
1493  JSReceiver::SetProperty(object, name, initial_value, mode,
1494  kNonStrictMode));
1495  }
1496  }
1497 
1498  } else {
1499  // The property is not in the function context. It needs to be
1500  // "declared" in the function context's extension context or as a
1501  // property of the the global object.
1502  Handle<JSObject> object;
1503  if (context->has_extension()) {
1504  object = Handle<JSObject>(JSObject::cast(context->extension()));
1505  } else {
1506  // Context extension objects are allocated lazily.
1507  ASSERT(context->IsFunctionContext());
1508  object = isolate->factory()->NewJSObject(
1509  isolate->context_extension_function());
1510  context->set_extension(*object);
1511  }
1512  ASSERT(*object != NULL);
1513 
1514  // Declare the property by setting it to the initial value if provided,
1515  // or undefined, and use the correct mode (e.g. READ_ONLY attribute for
1516  // constant declarations).
1517  ASSERT(!object->HasLocalProperty(*name));
1518  Handle<Object> value(isolate->heap()->undefined_value(), isolate);
1519  if (*initial_value != NULL) value = initial_value;
1520  // Declaring a const context slot is a conflicting declaration if
1521  // there is a callback with that name in a prototype. It is
1522  // allowed to introduce const variables in
1523  // JSContextExtensionObjects. They are treated specially in
1524  // SetProperty and no setters are invoked for those since they are
1525  // not real JSObjects.
1526  if (initial_value->IsTheHole() &&
1527  !object->IsJSContextExtensionObject()) {
1528  LookupResult lookup(isolate);
1529  object->Lookup(*name, &lookup);
1530  if (lookup.IsPropertyCallbacks()) {
1531  return ThrowRedeclarationError(isolate, "const", name);
1532  }
1533  }
1534  if (object->IsJSGlobalObject()) {
1535  // Define own property on the global object.
1536  RETURN_IF_EMPTY_HANDLE(isolate,
1537  JSObject::SetLocalPropertyIgnoreAttributes(object, name, value, mode));
1538  } else {
1539  RETURN_IF_EMPTY_HANDLE(isolate,
1540  JSReceiver::SetProperty(object, name, value, mode, kNonStrictMode));
1541  }
1542  }
1543 
1544  return isolate->heap()->undefined_value();
1545 }
1546 
1547 
1548 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
1549  NoHandleAllocation nha;
1550  // args[0] == name
1551  // args[1] == language_mode
1552  // args[2] == value (optional)
1553 
1554  // Determine if we need to assign to the variable if it already
1555  // exists (based on the number of arguments).
1556  RUNTIME_ASSERT(args.length() == 2 || args.length() == 3);
1557  bool assign = args.length() == 3;
1558 
1560  GlobalObject* global = isolate->context()->global_object();
1561  RUNTIME_ASSERT(args[1]->IsSmi());
1562  CONVERT_LANGUAGE_MODE_ARG(language_mode, 1);
1563  StrictModeFlag strict_mode_flag = (language_mode == CLASSIC_MODE)
1565 
1566  // According to ECMA-262, section 12.2, page 62, the property must
1567  // not be deletable.
1568  PropertyAttributes attributes = DONT_DELETE;
1569 
1570  // Lookup the property locally in the global object. If it isn't
1571  // there, there is a property with this name in the prototype chain.
1572  // We follow Safari and Firefox behavior and only set the property
1573  // locally if there is an explicit initialization value that we have
1574  // to assign to the property.
1575  // Note that objects can have hidden prototypes, so we need to traverse
1576  // the whole chain of hidden prototypes to do a 'local' lookup.
1577  Object* object = global;
1578  LookupResult lookup(isolate);
1579  while (object->IsJSObject() &&
1580  JSObject::cast(object)->map()->is_hidden_prototype()) {
1581  JSObject* raw_holder = JSObject::cast(object);
1582  raw_holder->LocalLookup(*name, &lookup);
1583  if (lookup.IsInterceptor()) {
1584  HandleScope handle_scope(isolate);
1585  Handle<JSObject> holder(raw_holder);
1586  PropertyAttributes intercepted = holder->GetPropertyAttribute(*name);
1587  // Update the raw pointer in case it's changed due to GC.
1588  raw_holder = *holder;
1589  if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
1590  // Found an interceptor that's not read only.
1591  if (assign) {
1592  return raw_holder->SetProperty(
1593  &lookup, *name, args[2], attributes, strict_mode_flag);
1594  } else {
1595  return isolate->heap()->undefined_value();
1596  }
1597  }
1598  }
1599  object = raw_holder->GetPrototype();
1600  }
1601 
1602  // Reload global in case the loop above performed a GC.
1603  global = isolate->context()->global_object();
1604  if (assign) {
1605  return global->SetProperty(*name, args[2], attributes, strict_mode_flag);
1606  }
1607  return isolate->heap()->undefined_value();
1608 }
1609 
1610 
1611 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
1612  // All constants are declared with an initial value. The name
1613  // of the constant is the first argument and the initial value
1614  // is the second.
1615  RUNTIME_ASSERT(args.length() == 2);
1617  Handle<Object> value = args.at<Object>(1);
1618 
1619  // Get the current global object from top.
1620  GlobalObject* global = isolate->context()->global_object();
1621 
1622  // According to ECMA-262, section 12.2, page 62, the property must
1623  // not be deletable. Since it's a const, it must be READ_ONLY too.
1624  PropertyAttributes attributes =
1625  static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
1626 
1627  // Lookup the property locally in the global object. If it isn't
1628  // there, we add the property and take special precautions to always
1629  // add it as a local property even in case of callbacks in the
1630  // prototype chain (this rules out using SetProperty).
1631  // We use SetLocalPropertyIgnoreAttributes instead
1632  LookupResult lookup(isolate);
1633  global->LocalLookup(*name, &lookup);
1634  if (!lookup.IsFound()) {
1635  return global->SetLocalPropertyIgnoreAttributes(*name,
1636  *value,
1637  attributes);
1638  }
1639 
1640  if (!lookup.IsReadOnly()) {
1641  // Restore global object from context (in case of GC) and continue
1642  // with setting the value.
1643  HandleScope handle_scope(isolate);
1644  Handle<GlobalObject> global(isolate->context()->global_object());
1645 
1646  // BUG 1213575: Handle the case where we have to set a read-only
1647  // property through an interceptor and only do it if it's
1648  // uninitialized, e.g. the hole. Nirk...
1649  // Passing non-strict mode because the property is writable.
1651  isolate,
1652  JSReceiver::SetProperty(global, name, value, attributes,
1653  kNonStrictMode));
1654  return *value;
1655  }
1656 
1657  // Set the value, but only if we're assigning the initial value to a
1658  // constant. For now, we determine this by checking if the
1659  // current value is the hole.
1660  // Strict mode handling not needed (const is disallowed in strict mode).
1661  if (lookup.IsField()) {
1662  FixedArray* properties = global->properties();
1663  int index = lookup.GetFieldIndex();
1664  if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) {
1665  properties->set(index, *value);
1666  }
1667  } else if (lookup.IsNormal()) {
1668  if (global->GetNormalizedProperty(&lookup)->IsTheHole() ||
1669  !lookup.IsReadOnly()) {
1670  global->SetNormalizedProperty(&lookup, *value);
1671  }
1672  } else {
1673  // Ignore re-initialization of constants that have already been
1674  // assigned a function value.
1675  ASSERT(lookup.IsReadOnly() && lookup.IsConstantFunction());
1676  }
1677 
1678  // Use the set value as the result of the operation.
1679  return *value;
1680 }
1681 
1682 
1683 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) {
1684  HandleScope scope(isolate);
1685  ASSERT(args.length() == 3);
1686 
1687  Handle<Object> value(args[0], isolate);
1688  ASSERT(!value->IsTheHole());
1689 
1690  // Initializations are always done in a function or native context.
1691  RUNTIME_ASSERT(args[1]->IsContext());
1692  Handle<Context> context(Context::cast(args[1])->declaration_context());
1693 
1694  Handle<String> name(String::cast(args[2]));
1695 
1696  int index;
1697  PropertyAttributes attributes;
1699  BindingFlags binding_flags;
1700  Handle<Object> holder =
1701  context->Lookup(name, flags, &index, &attributes, &binding_flags);
1702 
1703  if (index >= 0) {
1704  ASSERT(holder->IsContext());
1705  // Property was found in a context. Perform the assignment if we
1706  // found some non-constant or an uninitialized constant.
1707  Handle<Context> context = Handle<Context>::cast(holder);
1708  if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) {
1709  context->set(index, *value);
1710  }
1711  return *value;
1712  }
1713 
1714  // The property could not be found, we introduce it as a property of the
1715  // global object.
1716  if (attributes == ABSENT) {
1718  isolate->context()->global_object());
1719  // Strict mode not needed (const disallowed in strict mode).
1721  isolate,
1722  JSReceiver::SetProperty(global, name, value, NONE, kNonStrictMode));
1723  return *value;
1724  }
1725 
1726  // The property was present in some function's context extension object,
1727  // as a property on the subject of a with, or as a property of the global
1728  // object.
1729  //
1730  // In most situations, eval-introduced consts should still be present in
1731  // the context extension object. However, because declaration and
1732  // initialization are separate, the property might have been deleted
1733  // before we reach the initialization point.
1734  //
1735  // Example:
1736  //
1737  // function f() { eval("delete x; const x;"); }
1738  //
1739  // In that case, the initialization behaves like a normal assignment.
1740  Handle<JSObject> object = Handle<JSObject>::cast(holder);
1741 
1742  if (*object == context->extension()) {
1743  // This is the property that was introduced by the const declaration.
1744  // Set it if it hasn't been set before. NOTE: We cannot use
1745  // GetProperty() to get the current value as it 'unholes' the value.
1746  LookupResult lookup(isolate);
1747  object->LocalLookupRealNamedProperty(*name, &lookup);
1748  ASSERT(lookup.IsFound()); // the property was declared
1749  ASSERT(lookup.IsReadOnly()); // and it was declared as read-only
1750 
1751  if (lookup.IsField()) {
1752  FixedArray* properties = object->properties();
1753  int index = lookup.GetFieldIndex();
1754  if (properties->get(index)->IsTheHole()) {
1755  properties->set(index, *value);
1756  }
1757  } else if (lookup.IsNormal()) {
1758  if (object->GetNormalizedProperty(&lookup)->IsTheHole()) {
1759  object->SetNormalizedProperty(&lookup, *value);
1760  }
1761  } else {
1762  // We should not reach here. Any real, named property should be
1763  // either a field or a dictionary slot.
1764  UNREACHABLE();
1765  }
1766  } else {
1767  // The property was found on some other object. Set it if it is not a
1768  // read-only property.
1769  if ((attributes & READ_ONLY) == 0) {
1770  // Strict mode not needed (const disallowed in strict mode).
1772  isolate,
1773  JSReceiver::SetProperty(object, name, value, attributes,
1774  kNonStrictMode));
1775  }
1776  }
1777 
1778  return *value;
1779 }
1780 
1781 
1782 RUNTIME_FUNCTION(MaybeObject*,
1783  Runtime_OptimizeObjectForAddingMultipleProperties) {
1784  HandleScope scope(isolate);
1785  ASSERT(args.length() == 2);
1787  CONVERT_SMI_ARG_CHECKED(properties, 1);
1788  if (object->HasFastProperties()) {
1790  }
1791  return *object;
1792 }
1793 
1794 
1795 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) {
1796  HandleScope scope(isolate);
1797  ASSERT(args.length() == 4);
1799  CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
1800  // Due to the way the JS calls are constructed this must be less than the
1801  // length of a string, i.e. it is always a Smi. We check anyway for security.
1802  CONVERT_SMI_ARG_CHECKED(index, 2);
1803  CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
1804  RUNTIME_ASSERT(last_match_info->HasFastObjectElements());
1805  RUNTIME_ASSERT(index >= 0);
1806  RUNTIME_ASSERT(index <= subject->length());
1807  isolate->counters()->regexp_entry_runtime()->Increment();
1808  Handle<Object> result = RegExpImpl::Exec(regexp,
1809  subject,
1810  index,
1811  last_match_info);
1812  if (result.is_null()) return Failure::Exception();
1813  return *result;
1814 }
1815 
1816 
1817 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpConstructResult) {
1818  ASSERT(args.length() == 3);
1819  CONVERT_SMI_ARG_CHECKED(elements_count, 0);
1820  if (elements_count < 0 ||
1821  elements_count > FixedArray::kMaxLength ||
1822  !Smi::IsValid(elements_count)) {
1823  return isolate->ThrowIllegalOperation();
1824  }
1825  Object* new_object;
1826  { MaybeObject* maybe_new_object =
1827  isolate->heap()->AllocateFixedArrayWithHoles(elements_count);
1828  if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
1829  }
1830  FixedArray* elements = FixedArray::cast(new_object);
1831  { MaybeObject* maybe_new_object = isolate->heap()->AllocateRaw(
1833  if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
1834  }
1835  {
1836  AssertNoAllocation no_gc;
1837  HandleScope scope(isolate);
1838  reinterpret_cast<HeapObject*>(new_object)->
1839  set_map(isolate->native_context()->regexp_result_map());
1840  }
1841  JSArray* array = JSArray::cast(new_object);
1842  array->set_properties(isolate->heap()->empty_fixed_array());
1843  array->set_elements(elements);
1844  array->set_length(Smi::FromInt(elements_count));
1845  // Write in-object properties after the length of the array.
1848  return array;
1849 }
1850 
1851 
1852 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) {
1853  AssertNoAllocation no_alloc;
1854  ASSERT(args.length() == 5);
1855  CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
1856  CONVERT_ARG_CHECKED(String, source, 1);
1857  // If source is the empty string we set it to "(?:)" instead as
1858  // suggested by ECMA-262, 5th, section 15.10.4.1.
1859  if (source->length() == 0) source = isolate->heap()->query_colon_symbol();
1860 
1861  Object* global = args[2];
1862  if (!global->IsTrue()) global = isolate->heap()->false_value();
1863 
1864  Object* ignoreCase = args[3];
1865  if (!ignoreCase->IsTrue()) ignoreCase = isolate->heap()->false_value();
1866 
1867  Object* multiline = args[4];
1868  if (!multiline->IsTrue()) multiline = isolate->heap()->false_value();
1869 
1870  Map* map = regexp->map();
1871  Object* constructor = map->constructor();
1872  if (constructor->IsJSFunction() &&
1873  JSFunction::cast(constructor)->initial_map() == map) {
1874  // If we still have the original map, set in-object properties directly.
1875  regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, source);
1876  // Both true and false are immovable immortal objects so no need for write
1877  // barrier.
1878  regexp->InObjectPropertyAtPut(
1880  regexp->InObjectPropertyAtPut(
1882  regexp->InObjectPropertyAtPut(
1884  regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex,
1885  Smi::FromInt(0),
1886  SKIP_WRITE_BARRIER); // It's a Smi.
1887  return regexp;
1888  }
1889 
1890  // Map has changed, so use generic, but slower, method.
1891  PropertyAttributes final =
1893  PropertyAttributes writable =
1894  static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
1895  Heap* heap = isolate->heap();
1896  MaybeObject* result;
1897  result = regexp->SetLocalPropertyIgnoreAttributes(heap->source_symbol(),
1898  source,
1899  final);
1900  ASSERT(!result->IsFailure());
1901  result = regexp->SetLocalPropertyIgnoreAttributes(heap->global_symbol(),
1902  global,
1903  final);
1904  ASSERT(!result->IsFailure());
1905  result =
1906  regexp->SetLocalPropertyIgnoreAttributes(heap->ignore_case_symbol(),
1907  ignoreCase,
1908  final);
1909  ASSERT(!result->IsFailure());
1910  result = regexp->SetLocalPropertyIgnoreAttributes(heap->multiline_symbol(),
1911  multiline,
1912  final);
1913  ASSERT(!result->IsFailure());
1914  result =
1915  regexp->SetLocalPropertyIgnoreAttributes(heap->last_index_symbol(),
1916  Smi::FromInt(0),
1917  writable);
1918  ASSERT(!result->IsFailure());
1919  USE(result);
1920  return regexp;
1921 }
1922 
1923 
1924 RUNTIME_FUNCTION(MaybeObject*, Runtime_FinishArrayPrototypeSetup) {
1925  HandleScope scope(isolate);
1926  ASSERT(args.length() == 1);
1927  CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0);
1928  // This is necessary to enable fast checks for absence of elements
1929  // on Array.prototype and below.
1930  prototype->set_elements(isolate->heap()->empty_fixed_array());
1931  return Smi::FromInt(0);
1932 }
1933 
1934 
1935 static Handle<JSFunction> InstallBuiltin(Isolate* isolate,
1936  Handle<JSObject> holder,
1937  const char* name,
1938  Builtins::Name builtin_name) {
1939  Handle<String> key = isolate->factory()->LookupAsciiSymbol(name);
1940  Handle<Code> code(isolate->builtins()->builtin(builtin_name));
1941  Handle<JSFunction> optimized =
1942  isolate->factory()->NewFunction(key,
1945  code,
1946  false);
1947  optimized->shared()->DontAdaptArguments();
1948  JSReceiver::SetProperty(holder, key, optimized, NONE, kStrictMode);
1949  return optimized;
1950 }
1951 
1952 
1953 RUNTIME_FUNCTION(MaybeObject*, Runtime_SpecialArrayFunctions) {
1954  HandleScope scope(isolate);
1955  ASSERT(args.length() == 1);
1957 
1958  InstallBuiltin(isolate, holder, "pop", Builtins::kArrayPop);
1959  InstallBuiltin(isolate, holder, "push", Builtins::kArrayPush);
1960  InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift);
1961  InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift);
1962  InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice);
1963  InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
1964  InstallBuiltin(isolate, holder, "concat", Builtins::kArrayConcat);
1965 
1966  return *holder;
1967 }
1968 
1969 
1970 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultReceiver) {
1971  ASSERT(args.length() == 1);
1972  CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
1973 
1974  if (!callable->IsJSFunction()) {
1975  HandleScope scope(isolate);
1976  bool threw = false;
1977  Handle<Object> delegate =
1979  if (threw) return Failure::Exception();
1980  callable = JSFunction::cast(*delegate);
1981  }
1982  JSFunction* function = JSFunction::cast(callable);
1983 
1984  SharedFunctionInfo* shared = function->shared();
1985  if (shared->native() || !shared->is_classic_mode()) {
1986  return isolate->heap()->undefined_value();
1987  }
1988  // Returns undefined for strict or native functions, or
1989  // the associated global receiver for "normal" functions.
1990 
1991  Context* native_context =
1992  function->context()->global_object()->native_context();
1993  return native_context->global_object()->global_receiver();
1994 }
1995 
1996 
1997 RUNTIME_FUNCTION(MaybeObject*, Runtime_MaterializeRegExpLiteral) {
1998  HandleScope scope(isolate);
1999  ASSERT(args.length() == 4);
2000  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
2001  int index = args.smi_at(1);
2002  Handle<String> pattern = args.at<String>(2);
2003  Handle<String> flags = args.at<String>(3);
2004 
2005  // Get the RegExp function from the context in the literals array.
2006  // This is the RegExp function from the context in which the
2007  // function was created. We do not use the RegExp function from the
2008  // current native context because this might be the RegExp function
2009  // from another context which we should not have access to.
2010  Handle<JSFunction> constructor =
2012  JSFunction::NativeContextFromLiterals(*literals)->regexp_function());
2013  // Compute the regular expression literal.
2014  bool has_pending_exception;
2015  Handle<Object> regexp =
2016  RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
2017  &has_pending_exception);
2018  if (has_pending_exception) {
2019  ASSERT(isolate->has_pending_exception());
2020  return Failure::Exception();
2021  }
2022  literals->set(index, *regexp);
2023  return *regexp;
2024 }
2025 
2026 
2027 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetName) {
2028  NoHandleAllocation ha;
2029  ASSERT(args.length() == 1);
2030 
2032  return f->shared()->name();
2033 }
2034 
2035 
2036 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetName) {
2037  NoHandleAllocation ha;
2038  ASSERT(args.length() == 2);
2039 
2041  CONVERT_ARG_CHECKED(String, name, 1);
2042  f->shared()->set_name(name);
2043  return isolate->heap()->undefined_value();
2044 }
2045 
2046 
2047 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionNameShouldPrintAsAnonymous) {
2048  NoHandleAllocation ha;
2049  ASSERT(args.length() == 1);
2051  return isolate->heap()->ToBoolean(
2052  f->shared()->name_should_print_as_anonymous());
2053 }
2054 
2055 
2056 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) {
2057  NoHandleAllocation ha;
2058  ASSERT(args.length() == 1);
2060  f->shared()->set_name_should_print_as_anonymous(true);
2061  return isolate->heap()->undefined_value();
2062 }
2063 
2064 
2065 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) {
2066  NoHandleAllocation ha;
2067  ASSERT(args.length() == 1);
2068 
2070  f->RemovePrototype();
2071 
2072  return isolate->heap()->undefined_value();
2073 }
2074 
2075 
2076 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScript) {
2077  HandleScope scope(isolate);
2078  ASSERT(args.length() == 1);
2079 
2081  Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate);
2082  if (!script->IsScript()) return isolate->heap()->undefined_value();
2083 
2084  return *GetScriptWrapper(Handle<Script>::cast(script));
2085 }
2086 
2087 
2088 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetSourceCode) {
2089  HandleScope scope(isolate);
2090  ASSERT(args.length() == 1);
2091 
2093  Handle<SharedFunctionInfo> shared(f->shared());
2094  return *shared->GetSourceCode();
2095 }
2096 
2097 
2098 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScriptSourcePosition) {
2099  NoHandleAllocation ha;
2100  ASSERT(args.length() == 1);
2101 
2103  int pos = fun->shared()->start_position();
2104  return Smi::FromInt(pos);
2105 }
2106 
2107 
2108 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetPositionForOffset) {
2109  ASSERT(args.length() == 2);
2110 
2112  CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]);
2113 
2114  RUNTIME_ASSERT(0 <= offset && offset < code->Size());
2115 
2116  Address pc = code->address() + offset;
2117  return Smi::FromInt(code->SourcePosition(pc));
2118 }
2119 
2120 
2121 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetInstanceClassName) {
2122  NoHandleAllocation ha;
2123  ASSERT(args.length() == 2);
2124 
2126  CONVERT_ARG_CHECKED(String, name, 1);
2127  fun->SetInstanceClassName(name);
2128  return isolate->heap()->undefined_value();
2129 }
2130 
2131 
2132 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetLength) {
2133  NoHandleAllocation ha;
2134  ASSERT(args.length() == 2);
2135 
2137  CONVERT_SMI_ARG_CHECKED(length, 1);
2138  fun->shared()->set_length(length);
2139  return isolate->heap()->undefined_value();
2140 }
2141 
2142 
2143 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) {
2144  NoHandleAllocation ha;
2145  ASSERT(args.length() == 2);
2146 
2148  ASSERT(fun->should_have_prototype());
2149  Object* obj;
2150  { MaybeObject* maybe_obj =
2151  Accessors::FunctionSetPrototype(fun, args[1], NULL);
2152  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2153  }
2154  return args[0]; // return TOS
2155 }
2156 
2157 
2158 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) {
2159  NoHandleAllocation ha;
2160  RUNTIME_ASSERT(args.length() == 1);
2161  CONVERT_ARG_CHECKED(JSFunction, function, 0);
2162 
2163  String* name = isolate->heap()->prototype_symbol();
2164 
2165  if (function->HasFastProperties()) {
2166  // Construct a new field descriptor with updated attributes.
2167  DescriptorArray* instance_desc = function->map()->instance_descriptors();
2168 
2169  int index = instance_desc->SearchWithCache(name, function->map());
2171  PropertyDetails details = instance_desc->GetDetails(index);
2172 
2173  CallbacksDescriptor new_desc(name,
2174  instance_desc->GetValue(index),
2175  static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
2176  details.descriptor_index());
2177 
2178  // Create a new map featuring the new field descriptors array.
2179  Map* new_map;
2180  MaybeObject* maybe_map =
2181  function->map()->CopyReplaceDescriptor(
2182  instance_desc, &new_desc, index, OMIT_TRANSITION);
2183  if (!maybe_map->To(&new_map)) return maybe_map;
2184 
2185  function->set_map(new_map);
2186  } else { // Dictionary properties.
2187  // Directly manipulate the property details.
2188  int entry = function->property_dictionary()->FindEntry(name);
2190  PropertyDetails details = function->property_dictionary()->DetailsAt(entry);
2191  PropertyDetails new_details(
2192  static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
2193  details.type(),
2194  details.dictionary_index());
2195  function->property_dictionary()->DetailsAtPut(entry, new_details);
2196  }
2197  return function;
2198 }
2199 
2200 
2201 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) {
2202  NoHandleAllocation ha;
2203  ASSERT(args.length() == 1);
2204 
2206  return isolate->heap()->ToBoolean(f->shared()->IsApiFunction());
2207 }
2208 
2209 
2210 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) {
2211  NoHandleAllocation ha;
2212  ASSERT(args.length() == 1);
2213 
2215  return isolate->heap()->ToBoolean(f->IsBuiltin());
2216 }
2217 
2218 
2219 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
2220  HandleScope scope(isolate);
2221  ASSERT(args.length() == 2);
2222 
2224  Handle<Object> code = args.at<Object>(1);
2225 
2226  if (code->IsNull()) return *target;
2227  RUNTIME_ASSERT(code->IsJSFunction());
2229  Handle<SharedFunctionInfo> target_shared(target->shared());
2230  Handle<SharedFunctionInfo> source_shared(source->shared());
2231 
2233  return Failure::Exception();
2234  }
2235 
2236  // Set the code, scope info, formal parameter count, and the length
2237  // of the target shared function info. Set the source code of the
2238  // target function to undefined. SetCode is only used for built-in
2239  // constructors like String, Array, and Object, and some web code
2240  // doesn't like seeing source code for constructors.
2241  target_shared->set_code(source_shared->code());
2242  target_shared->set_scope_info(source_shared->scope_info());
2243  target_shared->set_length(source_shared->length());
2244  target_shared->set_formal_parameter_count(
2245  source_shared->formal_parameter_count());
2246  target_shared->set_script(isolate->heap()->undefined_value());
2247 
2248  // Since we don't store the source we should never optimize this.
2249  target_shared->code()->set_optimizable(false);
2250 
2251  // Clear the optimization hints related to the compiled code as these
2252  // are no longer valid when the code is overwritten.
2253  target_shared->ClearThisPropertyAssignmentsInfo();
2254 
2255  // Set the code of the target function.
2256  target->ReplaceCode(source_shared->code());
2257  ASSERT(target->next_function_link()->IsUndefined());
2258 
2259  // Make sure we get a fresh copy of the literal vector to avoid cross
2260  // context contamination.
2261  Handle<Context> context(source->context());
2262  int number_of_literals = source->NumberOfLiterals();
2263  Handle<FixedArray> literals =
2264  isolate->factory()->NewFixedArray(number_of_literals, TENURED);
2265  if (number_of_literals > 0) {
2267  context->native_context());
2268  }
2269  target->set_context(*context);
2270  target->set_literals(*literals);
2271 
2272  if (isolate->logger()->is_logging_code_events() ||
2273  CpuProfiler::is_profiling(isolate)) {
2274  isolate->logger()->LogExistingFunction(
2275  source_shared, Handle<Code>(source_shared->code()));
2276  }
2277 
2278  return *target;
2279 }
2280 
2281 
2282 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetExpectedNumberOfProperties) {
2283  HandleScope scope(isolate);
2284  ASSERT(args.length() == 2);
2285  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
2286  CONVERT_SMI_ARG_CHECKED(num, 1);
2287  RUNTIME_ASSERT(num >= 0);
2288  SetExpectedNofProperties(function, num);
2289  return isolate->heap()->undefined_value();
2290 }
2291 
2292 
2293 MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate,
2294  Object* char_code) {
2295  uint32_t code;
2296  if (char_code->ToArrayIndex(&code)) {
2297  if (code <= 0xffff) {
2298  return isolate->heap()->LookupSingleCharacterStringFromCode(code);
2299  }
2300  }
2301  return isolate->heap()->empty_string();
2302 }
2303 
2304 
2305 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCharCodeAt) {
2306  NoHandleAllocation ha;
2307  ASSERT(args.length() == 2);
2308 
2309  CONVERT_ARG_CHECKED(String, subject, 0);
2310  CONVERT_NUMBER_CHECKED(uint32_t, i, Uint32, args[1]);
2311 
2312  // Flatten the string. If someone wants to get a char at an index
2313  // in a cons string, it is likely that more indices will be
2314  // accessed.
2315  Object* flat;
2316  { MaybeObject* maybe_flat = subject->TryFlatten();
2317  if (!maybe_flat->ToObject(&flat)) return maybe_flat;
2318  }
2319  subject = String::cast(flat);
2320 
2321  if (i >= static_cast<uint32_t>(subject->length())) {
2322  return isolate->heap()->nan_value();
2323  }
2324 
2325  return Smi::FromInt(subject->Get(i));
2326 }
2327 
2328 
2329 RUNTIME_FUNCTION(MaybeObject*, Runtime_CharFromCode) {
2330  NoHandleAllocation ha;
2331  ASSERT(args.length() == 1);
2332  return CharFromCode(isolate, args[0]);
2333 }
2334 
2335 
2337  public:
2338  explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity)
2339  : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)),
2340  length_(0),
2341  has_non_smi_elements_(false) {
2342  // Require a non-zero initial size. Ensures that doubling the size to
2343  // extend the array will work.
2344  ASSERT(initial_capacity > 0);
2345  }
2346 
2347  explicit FixedArrayBuilder(Handle<FixedArray> backing_store)
2348  : array_(backing_store),
2349  length_(0),
2350  has_non_smi_elements_(false) {
2351  // Require a non-zero initial size. Ensures that doubling the size to
2352  // extend the array will work.
2353  ASSERT(backing_store->length() > 0);
2354  }
2355 
2356  bool HasCapacity(int elements) {
2357  int length = array_->length();
2358  int required_length = length_ + elements;
2359  return (length >= required_length);
2360  }
2361 
2362  void EnsureCapacity(int elements) {
2363  int length = array_->length();
2364  int required_length = length_ + elements;
2365  if (length < required_length) {
2366  int new_length = length;
2367  do {
2368  new_length *= 2;
2369  } while (new_length < required_length);
2370  Handle<FixedArray> extended_array =
2371  array_->GetIsolate()->factory()->NewFixedArrayWithHoles(new_length);
2372  array_->CopyTo(0, *extended_array, 0, length_);
2373  array_ = extended_array;
2374  }
2375  }
2376 
2377  void Add(Object* value) {
2378  ASSERT(!value->IsSmi());
2379  ASSERT(length_ < capacity());
2380  array_->set(length_, value);
2381  length_++;
2382  has_non_smi_elements_ = true;
2383  }
2384 
2385  void Add(Smi* value) {
2386  ASSERT(value->IsSmi());
2387  ASSERT(length_ < capacity());
2388  array_->set(length_, value);
2389  length_++;
2390  }
2391 
2393  return array_;
2394  }
2395 
2396  int length() {
2397  return length_;
2398  }
2399 
2400  int capacity() {
2401  return array_->length();
2402  }
2403 
2405  FACTORY->SetContent(target_array, array_);
2406  target_array->set_length(Smi::FromInt(length_));
2407  return target_array;
2408  }
2409 
2410 
2411  private:
2412  Handle<FixedArray> array_;
2413  int length_;
2414  bool has_non_smi_elements_;
2415 };
2416 
2417 
2418 // Forward declarations.
2421 
2422 template <typename schar>
2423 static inline void StringBuilderConcatHelper(String*,
2424  schar*,
2425  FixedArray*,
2426  int);
2427 
2430 typedef BitField<int,
2434 
2435 
2437  public:
2439  Handle<String> subject,
2440  int estimated_part_count)
2441  : heap_(heap),
2442  array_builder_(heap->isolate(), estimated_part_count),
2443  subject_(subject),
2444  character_count_(0),
2445  is_ascii_(subject->IsAsciiRepresentation()) {
2446  // Require a non-zero initial size. Ensures that doubling the size to
2447  // extend the array will work.
2448  ASSERT(estimated_part_count > 0);
2449  }
2450 
2451  static inline void AddSubjectSlice(FixedArrayBuilder* builder,
2452  int from,
2453  int to) {
2454  ASSERT(from >= 0);
2455  int length = to - from;
2456  ASSERT(length > 0);
2459  int encoded_slice = StringBuilderSubstringLength::encode(length) |
2461  builder->Add(Smi::FromInt(encoded_slice));
2462  } else {
2463  // Otherwise encode as two smis.
2464  builder->Add(Smi::FromInt(-length));
2465  builder->Add(Smi::FromInt(from));
2466  }
2467  }
2468 
2469 
2470  void EnsureCapacity(int elements) {
2471  array_builder_.EnsureCapacity(elements);
2472  }
2473 
2474 
2475  void AddSubjectSlice(int from, int to) {
2476  AddSubjectSlice(&array_builder_, from, to);
2477  IncrementCharacterCount(to - from);
2478  }
2479 
2480 
2481  void AddString(Handle<String> string) {
2482  int length = string->length();
2483  ASSERT(length > 0);
2484  AddElement(*string);
2485  if (!string->IsAsciiRepresentation()) {
2486  is_ascii_ = false;
2487  }
2488  IncrementCharacterCount(length);
2489  }
2490 
2491 
2493  if (array_builder_.length() == 0) {
2494  return heap_->isolate()->factory()->empty_string();
2495  }
2496 
2497  Handle<String> joined_string;
2498  if (is_ascii_) {
2499  Handle<SeqAsciiString> seq = NewRawAsciiString(character_count_);
2500  AssertNoAllocation no_alloc;
2501  char* char_buffer = seq->GetChars();
2502  StringBuilderConcatHelper(*subject_,
2503  char_buffer,
2504  *array_builder_.array(),
2505  array_builder_.length());
2506  joined_string = Handle<String>::cast(seq);
2507  } else {
2508  // Non-ASCII.
2509  Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_);
2510  AssertNoAllocation no_alloc;
2511  uc16* char_buffer = seq->GetChars();
2512  StringBuilderConcatHelper(*subject_,
2513  char_buffer,
2514  *array_builder_.array(),
2515  array_builder_.length());
2516  joined_string = Handle<String>::cast(seq);
2517  }
2518  return joined_string;
2519  }
2520 
2521 
2523  if (character_count_ > String::kMaxLength - by) {
2524  V8::FatalProcessOutOfMemory("String.replace result too large.");
2525  }
2526  character_count_ += by;
2527  }
2528 
2529  private:
2530  Handle<SeqAsciiString> NewRawAsciiString(int length) {
2531  return heap_->isolate()->factory()->NewRawAsciiString(length);
2532  }
2533 
2534 
2535  Handle<SeqTwoByteString> NewRawTwoByteString(int length) {
2536  return heap_->isolate()->factory()->NewRawTwoByteString(length);
2537  }
2538 
2539 
2540  void AddElement(Object* element) {
2541  ASSERT(element->IsSmi() || element->IsString());
2542  ASSERT(array_builder_.capacity() > array_builder_.length());
2543  array_builder_.Add(element);
2544  }
2545 
2546  Heap* heap_;
2547  FixedArrayBuilder array_builder_;
2548  Handle<String> subject_;
2549  int character_count_;
2550  bool is_ascii_;
2551 };
2552 
2553 
2555  public:
2557  : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {}
2558 
2559  // Return whether the replacement is simple.
2560  bool Compile(Handle<String> replacement,
2561  int capture_count,
2562  int subject_length);
2563 
2564  // Use Apply only if Compile returned false.
2565  void Apply(ReplacementStringBuilder* builder,
2566  int match_from,
2567  int match_to,
2568  int32_t* match);
2569 
2570  // Number of distinct parts of the replacement pattern.
2571  int parts() {
2572  return parts_.length();
2573  }
2574 
2575  Zone* zone() const { return zone_; }
2576 
2577  private:
2578  enum PartType {
2579  SUBJECT_PREFIX = 1,
2580  SUBJECT_SUFFIX,
2581  SUBJECT_CAPTURE,
2582  REPLACEMENT_SUBSTRING,
2583  REPLACEMENT_STRING,
2584 
2585  NUMBER_OF_PART_TYPES
2586  };
2587 
2588  struct ReplacementPart {
2589  static inline ReplacementPart SubjectMatch() {
2590  return ReplacementPart(SUBJECT_CAPTURE, 0);
2591  }
2592  static inline ReplacementPart SubjectCapture(int capture_index) {
2593  return ReplacementPart(SUBJECT_CAPTURE, capture_index);
2594  }
2595  static inline ReplacementPart SubjectPrefix() {
2596  return ReplacementPart(SUBJECT_PREFIX, 0);
2597  }
2598  static inline ReplacementPart SubjectSuffix(int subject_length) {
2599  return ReplacementPart(SUBJECT_SUFFIX, subject_length);
2600  }
2601  static inline ReplacementPart ReplacementString() {
2602  return ReplacementPart(REPLACEMENT_STRING, 0);
2603  }
2604  static inline ReplacementPart ReplacementSubString(int from, int to) {
2605  ASSERT(from >= 0);
2606  ASSERT(to > from);
2607  return ReplacementPart(-from, to);
2608  }
2609 
2610  // If tag <= 0 then it is the negation of a start index of a substring of
2611  // the replacement pattern, otherwise it's a value from PartType.
2612  ReplacementPart(int tag, int data)
2613  : tag(tag), data(data) {
2614  // Must be non-positive or a PartType value.
2615  ASSERT(tag < NUMBER_OF_PART_TYPES);
2616  }
2617  // Either a value of PartType or a non-positive number that is
2618  // the negation of an index into the replacement string.
2619  int tag;
2620  // The data value's interpretation depends on the value of tag:
2621  // tag == SUBJECT_PREFIX ||
2622  // tag == SUBJECT_SUFFIX: data is unused.
2623  // tag == SUBJECT_CAPTURE: data is the number of the capture.
2624  // tag == REPLACEMENT_SUBSTRING ||
2625  // tag == REPLACEMENT_STRING: data is index into array of substrings
2626  // of the replacement string.
2627  // tag <= 0: Temporary representation of the substring of the replacement
2628  // string ranging over -tag .. data.
2629  // Is replaced by REPLACEMENT_{SUB,}STRING when we create the
2630  // substring objects.
2631  int data;
2632  };
2633 
2634  template<typename Char>
2635  bool ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
2636  Vector<Char> characters,
2637  int capture_count,
2638  int subject_length,
2639  Zone* zone) {
2640  int length = characters.length();
2641  int last = 0;
2642  for (int i = 0; i < length; i++) {
2643  Char c = characters[i];
2644  if (c == '$') {
2645  int next_index = i + 1;
2646  if (next_index == length) { // No next character!
2647  break;
2648  }
2649  Char c2 = characters[next_index];
2650  switch (c2) {
2651  case '$':
2652  if (i > last) {
2653  // There is a substring before. Include the first "$".
2654  parts->Add(ReplacementPart::ReplacementSubString(last, next_index),
2655  zone);
2656  last = next_index + 1; // Continue after the second "$".
2657  } else {
2658  // Let the next substring start with the second "$".
2659  last = next_index;
2660  }
2661  i = next_index;
2662  break;
2663  case '`':
2664  if (i > last) {
2665  parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
2666  }
2667  parts->Add(ReplacementPart::SubjectPrefix(), zone);
2668  i = next_index;
2669  last = i + 1;
2670  break;
2671  case '\'':
2672  if (i > last) {
2673  parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
2674  }
2675  parts->Add(ReplacementPart::SubjectSuffix(subject_length), zone);
2676  i = next_index;
2677  last = i + 1;
2678  break;
2679  case '&':
2680  if (i > last) {
2681  parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
2682  }
2683  parts->Add(ReplacementPart::SubjectMatch(), zone);
2684  i = next_index;
2685  last = i + 1;
2686  break;
2687  case '0':
2688  case '1':
2689  case '2':
2690  case '3':
2691  case '4':
2692  case '5':
2693  case '6':
2694  case '7':
2695  case '8':
2696  case '9': {
2697  int capture_ref = c2 - '0';
2698  if (capture_ref > capture_count) {
2699  i = next_index;
2700  continue;
2701  }
2702  int second_digit_index = next_index + 1;
2703  if (second_digit_index < length) {
2704  // Peek ahead to see if we have two digits.
2705  Char c3 = characters[second_digit_index];
2706  if ('0' <= c3 && c3 <= '9') { // Double digits.
2707  int double_digit_ref = capture_ref * 10 + c3 - '0';
2708  if (double_digit_ref <= capture_count) {
2709  next_index = second_digit_index;
2710  capture_ref = double_digit_ref;
2711  }
2712  }
2713  }
2714  if (capture_ref > 0) {
2715  if (i > last) {
2716  parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
2717  }
2718  ASSERT(capture_ref <= capture_count);
2719  parts->Add(ReplacementPart::SubjectCapture(capture_ref), zone);
2720  last = next_index + 1;
2721  }
2722  i = next_index;
2723  break;
2724  }
2725  default:
2726  i = next_index;
2727  break;
2728  }
2729  }
2730  }
2731  if (length > last) {
2732  if (last == 0) {
2733  // Replacement is simple. Do not use Apply to do the replacement.
2734  return true;
2735  } else {
2736  parts->Add(ReplacementPart::ReplacementSubString(last, length), zone);
2737  }
2738  }
2739  return false;
2740  }
2741 
2742  ZoneList<ReplacementPart> parts_;
2743  ZoneList<Handle<String> > replacement_substrings_;
2744  Zone* zone_;
2745 };
2746 
2747 
2749  int capture_count,
2750  int subject_length) {
2751  {
2752  AssertNoAllocation no_alloc;
2753  String::FlatContent content = replacement->GetFlatContent();
2754  ASSERT(content.IsFlat());
2755  bool simple = false;
2756  if (content.IsAscii()) {
2757  simple = ParseReplacementPattern(&parts_,
2758  content.ToAsciiVector(),
2759  capture_count,
2760  subject_length,
2761  zone());
2762  } else {
2763  ASSERT(content.IsTwoByte());
2764  simple = ParseReplacementPattern(&parts_,
2765  content.ToUC16Vector(),
2766  capture_count,
2767  subject_length,
2768  zone());
2769  }
2770  if (simple) return true;
2771  }
2772 
2773  Isolate* isolate = replacement->GetIsolate();
2774  // Find substrings of replacement string and create them as String objects.
2775  int substring_index = 0;
2776  for (int i = 0, n = parts_.length(); i < n; i++) {
2777  int tag = parts_[i].tag;
2778  if (tag <= 0) { // A replacement string slice.
2779  int from = -tag;
2780  int to = parts_[i].data;
2781  replacement_substrings_.Add(
2782  isolate->factory()->NewSubString(replacement, from, to), zone());
2783  parts_[i].tag = REPLACEMENT_SUBSTRING;
2784  parts_[i].data = substring_index;
2785  substring_index++;
2786  } else if (tag == REPLACEMENT_STRING) {
2787  replacement_substrings_.Add(replacement, zone());
2788  parts_[i].data = substring_index;
2789  substring_index++;
2790  }
2791  }
2792  return false;
2793 }
2794 
2795 
2797  int match_from,
2798  int match_to,
2799  int32_t* match) {
2800  ASSERT_LT(0, parts_.length());
2801  for (int i = 0, n = parts_.length(); i < n; i++) {
2802  ReplacementPart part = parts_[i];
2803  switch (part.tag) {
2804  case SUBJECT_PREFIX:
2805  if (match_from > 0) builder->AddSubjectSlice(0, match_from);
2806  break;
2807  case SUBJECT_SUFFIX: {
2808  int subject_length = part.data;
2809  if (match_to < subject_length) {
2810  builder->AddSubjectSlice(match_to, subject_length);
2811  }
2812  break;
2813  }
2814  case SUBJECT_CAPTURE: {
2815  int capture = part.data;
2816  int from = match[capture * 2];
2817  int to = match[capture * 2 + 1];
2818  if (from >= 0 && to > from) {
2819  builder->AddSubjectSlice(from, to);
2820  }
2821  break;
2822  }
2823  case REPLACEMENT_SUBSTRING:
2824  case REPLACEMENT_STRING:
2825  builder->AddString(replacement_substrings_[part.data]);
2826  break;
2827  default:
2828  UNREACHABLE();
2829  }
2830  }
2831 }
2832 
2833 
2835  char pattern,
2836  ZoneList<int>* indices,
2837  unsigned int limit,
2838  Zone* zone) {
2839  ASSERT(limit > 0);
2840  // Collect indices of pattern in subject using memchr.
2841  // Stop after finding at most limit values.
2842  const char* subject_start = reinterpret_cast<const char*>(subject.start());
2843  const char* subject_end = subject_start + subject.length();
2844  const char* pos = subject_start;
2845  while (limit > 0) {
2846  pos = reinterpret_cast<const char*>(
2847  memchr(pos, pattern, subject_end - pos));
2848  if (pos == NULL) return;
2849  indices->Add(static_cast<int>(pos - subject_start), zone);
2850  pos++;
2851  limit--;
2852  }
2853 }
2854 
2855 
2856 template <typename SubjectChar, typename PatternChar>
2858  Vector<const SubjectChar> subject,
2859  Vector<const PatternChar> pattern,
2860  ZoneList<int>* indices,
2861  unsigned int limit,
2862  Zone* zone) {
2863  ASSERT(limit > 0);
2864  // Collect indices of pattern in subject.
2865  // Stop after finding at most limit values.
2866  int pattern_length = pattern.length();
2867  int index = 0;
2868  StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
2869  while (limit > 0) {
2870  index = search.Search(subject, index);
2871  if (index < 0) return;
2872  indices->Add(index, zone);
2873  index += pattern_length;
2874  limit--;
2875  }
2876 }
2877 
2878 
2880  String* subject,
2881  String* pattern,
2882  ZoneList<int>* indices,
2883  unsigned int limit,
2884  Zone* zone) {
2885  {
2886  AssertNoAllocation no_gc;
2887  String::FlatContent subject_content = subject->GetFlatContent();
2888  String::FlatContent pattern_content = pattern->GetFlatContent();
2889  ASSERT(subject_content.IsFlat());
2890  ASSERT(pattern_content.IsFlat());
2891  if (subject_content.IsAscii()) {
2892  Vector<const char> subject_vector = subject_content.ToAsciiVector();
2893  if (pattern_content.IsAscii()) {
2894  Vector<const char> pattern_vector = pattern_content.ToAsciiVector();
2895  if (pattern_vector.length() == 1) {
2896  FindAsciiStringIndices(subject_vector,
2897  pattern_vector[0],
2898  indices,
2899  limit,
2900  zone);
2901  } else {
2902  FindStringIndices(isolate,
2903  subject_vector,
2904  pattern_vector,
2905  indices,
2906  limit,
2907  zone);
2908  }
2909  } else {
2910  FindStringIndices(isolate,
2911  subject_vector,
2912  pattern_content.ToUC16Vector(),
2913  indices,
2914  limit,
2915  zone);
2916  }
2917  } else {
2918  Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
2919  if (pattern_content.IsAscii()) {
2920  FindStringIndices(isolate,
2921  subject_vector,
2922  pattern_content.ToAsciiVector(),
2923  indices,
2924  limit,
2925  zone);
2926  } else {
2927  FindStringIndices(isolate,
2928  subject_vector,
2929  pattern_content.ToUC16Vector(),
2930  indices,
2931  limit,
2932  zone);
2933  }
2934  }
2935  }
2936 }
2937 
2938 
2939 template<typename ResultSeqString>
2940 MUST_USE_RESULT static MaybeObject* StringReplaceAtomRegExpWithString(
2941  Isolate* isolate,
2942  Handle<String> subject,
2943  Handle<JSRegExp> pattern_regexp,
2944  Handle<String> replacement,
2945  Handle<JSArray> last_match_info) {
2946  ASSERT(subject->IsFlat());
2947  ASSERT(replacement->IsFlat());
2948 
2949  Zone* zone = isolate->runtime_zone();
2950  ZoneScope zone_space(zone, DELETE_ON_EXIT);
2951  ZoneList<int> indices(8, zone);
2952  ASSERT_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag());
2953  String* pattern =
2955  int subject_len = subject->length();
2956  int pattern_len = pattern->length();
2957  int replacement_len = replacement->length();
2958 
2960  isolate, *subject, pattern, &indices, 0xffffffff, zone);
2961 
2962  int matches = indices.length();
2963  if (matches == 0) return *subject;
2964 
2965  // Detect integer overflow.
2966  int64_t result_len_64 =
2967  (static_cast<int64_t>(replacement_len) -
2968  static_cast<int64_t>(pattern_len)) *
2969  static_cast<int64_t>(matches) +
2970  static_cast<int64_t>(subject_len);
2971  if (result_len_64 > INT_MAX) return Failure::OutOfMemoryException();
2972  int result_len = static_cast<int>(result_len_64);
2973 
2974  int subject_pos = 0;
2975  int result_pos = 0;
2976 
2977  Handle<ResultSeqString> result;
2978  if (ResultSeqString::kHasAsciiEncoding) {
2980  isolate->factory()->NewRawAsciiString(result_len));
2981  } else {
2983  isolate->factory()->NewRawTwoByteString(result_len));
2984  }
2985 
2986  for (int i = 0; i < matches; i++) {
2987  // Copy non-matched subject content.
2988  if (subject_pos < indices.at(i)) {
2989  String::WriteToFlat(*subject,
2990  result->GetChars() + result_pos,
2991  subject_pos,
2992  indices.at(i));
2993  result_pos += indices.at(i) - subject_pos;
2994  }
2995 
2996  // Replace match.
2997  if (replacement_len > 0) {
2998  String::WriteToFlat(*replacement,
2999  result->GetChars() + result_pos,
3000  0,
3001  replacement_len);
3002  result_pos += replacement_len;
3003  }
3004 
3005  subject_pos = indices.at(i) + pattern_len;
3006  }
3007  // Add remaining subject content at the end.
3008  if (subject_pos < subject_len) {
3009  String::WriteToFlat(*subject,
3010  result->GetChars() + result_pos,
3011  subject_pos,
3012  subject_len);
3013  }
3014 
3015  int32_t match_indices[] = { indices.at(matches - 1),
3016  indices.at(matches - 1) + pattern_len };
3017  RegExpImpl::SetLastMatchInfo(last_match_info, subject, 0, match_indices);
3018 
3019  return *result;
3020 }
3021 
3022 
3023 MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithString(
3024  Isolate* isolate,
3025  Handle<String> subject,
3026  Handle<JSRegExp> regexp,
3027  Handle<String> replacement,
3028  Handle<JSArray> last_match_info) {
3029  ASSERT(subject->IsFlat());
3030  ASSERT(replacement->IsFlat());
3031 
3032  bool is_global = regexp->GetFlags().is_global();
3033  int capture_count = regexp->CaptureCount();
3034  int subject_length = subject->length();
3035 
3036  // CompiledReplacement uses zone allocation.
3037  Zone* zone = isolate->runtime_zone();
3038  ZoneScope zonescope(zone, DELETE_ON_EXIT);
3039  CompiledReplacement compiled_replacement(zone);
3040  bool simple_replace = compiled_replacement.Compile(replacement,
3041  capture_count,
3042  subject_length);
3043 
3044  // Shortcut for simple non-regexp global replacements
3045  if (is_global &&
3046  regexp->TypeTag() == JSRegExp::ATOM &&
3047  simple_replace) {
3048  if (subject->HasOnlyAsciiChars() && replacement->HasOnlyAsciiChars()) {
3049  return StringReplaceAtomRegExpWithString<SeqAsciiString>(
3050  isolate, subject, regexp, replacement, last_match_info);
3051  } else {
3052  return StringReplaceAtomRegExpWithString<SeqTwoByteString>(
3053  isolate, subject, regexp, replacement, last_match_info);
3054  }
3055  }
3056 
3057  RegExpImpl::GlobalCache global_cache(regexp, subject, is_global, isolate);
3058  if (global_cache.HasException()) return Failure::Exception();
3059 
3060  int32_t* current_match = global_cache.FetchNext();
3061  if (current_match == NULL) {
3062  if (global_cache.HasException()) return Failure::Exception();
3063  return *subject;
3064  }
3065 
3066  // Guessing the number of parts that the final result string is built
3067  // from. Global regexps can match any number of times, so we guess
3068  // conservatively.
3069  int expected_parts =
3070  (compiled_replacement.parts() + 1) * (is_global ? 4 : 1) + 1;
3071  ReplacementStringBuilder builder(isolate->heap(),
3072  subject,
3073  expected_parts);
3074 
3075  // Number of parts added by compiled replacement plus preceeding
3076  // string and possibly suffix after last match. It is possible for
3077  // all components to use two elements when encoded as two smis.
3078  const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2);
3079 
3080  int prev = 0;
3081 
3082  do {
3083  builder.EnsureCapacity(parts_added_per_loop);
3084 
3085  int start = current_match[0];
3086  int end = current_match[1];
3087 
3088  if (prev < start) {
3089  builder.AddSubjectSlice(prev, start);
3090  }
3091 
3092  if (simple_replace) {
3093  builder.AddString(replacement);
3094  } else {
3095  compiled_replacement.Apply(&builder,
3096  start,
3097  end,
3098  current_match);
3099  }
3100  prev = end;
3101 
3102  // Only continue checking for global regexps.
3103  if (!is_global) break;
3104 
3105  current_match = global_cache.FetchNext();
3106  } while (current_match != NULL);
3107 
3108  if (global_cache.HasException()) return Failure::Exception();
3109 
3110  if (prev < subject_length) {
3111  builder.EnsureCapacity(2);
3112  builder.AddSubjectSlice(prev, subject_length);
3113  }
3114 
3115  RegExpImpl::SetLastMatchInfo(last_match_info,
3116  subject,
3117  capture_count,
3118  global_cache.LastSuccessfulMatch());
3119 
3120  return *(builder.ToString());
3121 }
3122 
3123 
3124 template <typename ResultSeqString>
3125 MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithEmptyString(
3126  Isolate* isolate,
3127  Handle<String> subject,
3128  Handle<JSRegExp> regexp,
3129  Handle<JSArray> last_match_info) {
3130  ASSERT(subject->IsFlat());
3131 
3132  bool is_global = regexp->GetFlags().is_global();
3133 
3134  // Shortcut for simple non-regexp global replacements
3135  if (is_global &&
3136  regexp->TypeTag() == JSRegExp::ATOM) {
3137  Handle<String> empty_string(HEAP->empty_string());
3138  if (subject->HasOnlyAsciiChars()) {
3139  return StringReplaceAtomRegExpWithString<SeqAsciiString>(
3140  isolate,
3141  subject,
3142  regexp,
3143  empty_string,
3144  last_match_info);
3145  } else {
3146  return StringReplaceAtomRegExpWithString<SeqTwoByteString>(
3147  isolate,
3148  subject,
3149  regexp,
3150  empty_string,
3151  last_match_info);
3152  }
3153  }
3154 
3155  RegExpImpl::GlobalCache global_cache(regexp, subject, is_global, isolate);
3156  if (global_cache.HasException()) return Failure::Exception();
3157 
3158  int32_t* current_match = global_cache.FetchNext();
3159  if (current_match == NULL) {
3160  if (global_cache.HasException()) return Failure::Exception();
3161  return *subject;
3162  }
3163 
3164  int start = current_match[0];
3165  int end = current_match[1];
3166  int capture_count = regexp->CaptureCount();
3167  int subject_length = subject->length();
3168 
3169  int new_length = subject_length - (end - start);
3170  if (new_length == 0) return isolate->heap()->empty_string();
3171 
3172  Handle<ResultSeqString> answer;
3173  if (ResultSeqString::kHasAsciiEncoding) {
3175  isolate->factory()->NewRawAsciiString(new_length));
3176  } else {
3178  isolate->factory()->NewRawTwoByteString(new_length));
3179  }
3180 
3181  if (!is_global) {
3183  last_match_info, subject, capture_count, current_match);
3184  if (start == end) {
3185  return *subject;
3186  } else {
3187  if (start > 0) {
3188  String::WriteToFlat(*subject, answer->GetChars(), 0, start);
3189  }
3190  if (end < subject_length) {
3192  *subject, answer->GetChars() + start, end, subject_length);
3193  }
3194  return *answer;
3195  }
3196  }
3197 
3198  int prev = 0;
3199  int position = 0;
3200 
3201  do {
3202  start = current_match[0];
3203  end = current_match[1];
3204  if (prev < start) {
3205  // Add substring subject[prev;start] to answer string.
3207  *subject, answer->GetChars() + position, prev, start);
3208  position += start - prev;
3209  }
3210  prev = end;
3211 
3212  current_match = global_cache.FetchNext();
3213  } while (current_match != NULL);
3214 
3215  if (global_cache.HasException()) return Failure::Exception();
3216 
3217  RegExpImpl::SetLastMatchInfo(last_match_info,
3218  subject,
3219  capture_count,
3220  global_cache.LastSuccessfulMatch());
3221 
3222  if (prev < subject_length) {
3223  // Add substring subject[prev;length] to answer string.
3225  *subject, answer->GetChars() + position, prev, subject_length);
3226  position += subject_length - prev;
3227  }
3228 
3229  if (position == 0) return isolate->heap()->empty_string();
3230 
3231  // Shorten string and fill
3232  int string_size = ResultSeqString::SizeFor(position);
3233  int allocated_string_size = ResultSeqString::SizeFor(new_length);
3234  int delta = allocated_string_size - string_size;
3235 
3236  answer->set_length(position);
3237  if (delta == 0) return *answer;
3238 
3239  Address end_of_string = answer->address() + string_size;
3240  isolate->heap()->CreateFillerObjectAt(end_of_string, delta);
3241  if (Marking::IsBlack(Marking::MarkBitFrom(*answer))) {
3242  MemoryChunk::IncrementLiveBytesFromMutator(answer->address(), -delta);
3243  }
3244 
3245  return *answer;
3246 }
3247 
3248 
3249 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceRegExpWithString) {
3250  ASSERT(args.length() == 4);
3251 
3252  HandleScope scope(isolate);
3253 
3254  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
3255  CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2);
3257  CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
3258 
3259  if (!subject->IsFlat()) subject = FlattenGetString(subject);
3260 
3261  if (!replacement->IsFlat()) replacement = FlattenGetString(replacement);
3262 
3263  ASSERT(last_match_info->HasFastObjectElements());
3264 
3265  if (replacement->length() == 0) {
3266  if (subject->HasOnlyAsciiChars()) {
3267  return StringReplaceRegExpWithEmptyString<SeqAsciiString>(
3268  isolate, subject, regexp, last_match_info);
3269  } else {
3270  return StringReplaceRegExpWithEmptyString<SeqTwoByteString>(
3271  isolate, subject, regexp, last_match_info);
3272  }
3273  }
3274 
3275  return StringReplaceRegExpWithString(
3276  isolate, subject, regexp, replacement, last_match_info);
3277 }
3278 
3279 
3281  Handle<String> subject,
3282  Handle<String> search,
3283  Handle<String> replace,
3284  bool* found,
3285  int recursion_limit) {
3286  if (recursion_limit == 0) return Handle<String>::null();
3287  if (subject->IsConsString()) {
3288  ConsString* cons = ConsString::cast(*subject);
3289  Handle<String> first = Handle<String>(cons->first());
3290  Handle<String> second = Handle<String>(cons->second());
3291  Handle<String> new_first =
3293  first,
3294  search,
3295  replace,
3296  found,
3297  recursion_limit - 1);
3298  if (*found) return isolate->factory()->NewConsString(new_first, second);
3299  if (new_first.is_null()) return new_first;
3300 
3301  Handle<String> new_second =
3303  second,
3304  search,
3305  replace,
3306  found,
3307  recursion_limit - 1);
3308  if (*found) return isolate->factory()->NewConsString(first, new_second);
3309  if (new_second.is_null()) return new_second;
3310 
3311  return subject;
3312  } else {
3313  int index = Runtime::StringMatch(isolate, subject, search, 0);
3314  if (index == -1) return subject;
3315  *found = true;
3316  Handle<String> first = isolate->factory()->NewSubString(subject, 0, index);
3317  Handle<String> cons1 = isolate->factory()->NewConsString(first, replace);
3318  Handle<String> second =
3319  isolate->factory()->NewSubString(subject, index + 1, subject->length());
3320  return isolate->factory()->NewConsString(cons1, second);
3321  }
3322 }
3323 
3324 
3325 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) {
3326  ASSERT(args.length() == 3);
3327  HandleScope scope(isolate);
3328  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
3329  CONVERT_ARG_HANDLE_CHECKED(String, search, 1);
3330  CONVERT_ARG_HANDLE_CHECKED(String, replace, 2);
3331 
3332  // If the cons string tree is too deep, we simply abort the recursion and
3333  // retry with a flattened subject string.
3334  const int kRecursionLimit = 0x1000;
3335  bool found = false;
3337  subject,
3338  search,
3339  replace,
3340  &found,
3341  kRecursionLimit);
3342  if (!result.is_null()) return *result;
3343  return *StringReplaceOneCharWithString(isolate,
3344  FlattenGetString(subject),
3345  search,
3346  replace,
3347  &found,
3348  kRecursionLimit);
3349 }
3350 
3351 
3352 // Perform string match of pattern on subject, starting at start index.
3353 // Caller must ensure that 0 <= start_index <= sub->length(),
3354 // and should check that pat->length() + start_index <= sub->length().
3356  Handle<String> sub,
3357  Handle<String> pat,
3358  int start_index) {
3359  ASSERT(0 <= start_index);
3360  ASSERT(start_index <= sub->length());
3361 
3362  int pattern_length = pat->length();
3363  if (pattern_length == 0) return start_index;
3364 
3365  int subject_length = sub->length();
3366  if (start_index + pattern_length > subject_length) return -1;
3367 
3368  if (!sub->IsFlat()) FlattenString(sub);
3369  if (!pat->IsFlat()) FlattenString(pat);
3370 
3371  AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
3372  // Extract flattened substrings of cons strings before determining asciiness.
3373  String::FlatContent seq_sub = sub->GetFlatContent();
3374  String::FlatContent seq_pat = pat->GetFlatContent();
3375 
3376  // dispatch on type of strings
3377  if (seq_pat.IsAscii()) {
3378  Vector<const char> pat_vector = seq_pat.ToAsciiVector();
3379  if (seq_sub.IsAscii()) {
3380  return SearchString(isolate,
3381  seq_sub.ToAsciiVector(),
3382  pat_vector,
3383  start_index);
3384  }
3385  return SearchString(isolate,
3386  seq_sub.ToUC16Vector(),
3387  pat_vector,
3388  start_index);
3389  }
3390  Vector<const uc16> pat_vector = seq_pat.ToUC16Vector();
3391  if (seq_sub.IsAscii()) {
3392  return SearchString(isolate,
3393  seq_sub.ToAsciiVector(),
3394  pat_vector,
3395  start_index);
3396  }
3397  return SearchString(isolate,
3398  seq_sub.ToUC16Vector(),
3399  pat_vector,
3400  start_index);
3401 }
3402 
3403 
3404 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringIndexOf) {
3405  HandleScope scope(isolate); // create a new handle scope
3406  ASSERT(args.length() == 3);
3407 
3410 
3411  Object* index = args[2];
3412  uint32_t start_index;
3413  if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
3414 
3415  RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
3416  int position =
3417  Runtime::StringMatch(isolate, sub, pat, start_index);
3418  return Smi::FromInt(position);
3419 }
3420 
3421 
3422 template <typename schar, typename pchar>
3423 static int StringMatchBackwards(Vector<const schar> subject,
3424  Vector<const pchar> pattern,
3425  int idx) {
3426  int pattern_length = pattern.length();
3427  ASSERT(pattern_length >= 1);
3428  ASSERT(idx + pattern_length <= subject.length());
3429 
3430  if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
3431  for (int i = 0; i < pattern_length; i++) {
3432  uc16 c = pattern[i];
3433  if (c > String::kMaxAsciiCharCode) {
3434  return -1;
3435  }
3436  }
3437  }
3438 
3439  pchar pattern_first_char = pattern[0];
3440  for (int i = idx; i >= 0; i--) {
3441  if (subject[i] != pattern_first_char) continue;
3442  int j = 1;
3443  while (j < pattern_length) {
3444  if (pattern[j] != subject[i+j]) {
3445  break;
3446  }
3447  j++;
3448  }
3449  if (j == pattern_length) {
3450  return i;
3451  }
3452  }
3453  return -1;
3454 }
3455 
3456 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
3457  HandleScope scope(isolate); // create a new handle scope
3458  ASSERT(args.length() == 3);
3459 
3462 
3463  Object* index = args[2];
3464  uint32_t start_index;
3465  if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
3466 
3467  uint32_t pat_length = pat->length();
3468  uint32_t sub_length = sub->length();
3469 
3470  if (start_index + pat_length > sub_length) {
3471  start_index = sub_length - pat_length;
3472  }
3473 
3474  if (pat_length == 0) {
3475  return Smi::FromInt(start_index);
3476  }
3477 
3478  if (!sub->IsFlat()) FlattenString(sub);
3479  if (!pat->IsFlat()) FlattenString(pat);
3480 
3481  int position = -1;
3482  AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
3483 
3484  String::FlatContent sub_content = sub->GetFlatContent();
3485  String::FlatContent pat_content = pat->GetFlatContent();
3486 
3487  if (pat_content.IsAscii()) {
3488  Vector<const char> pat_vector = pat_content.ToAsciiVector();
3489  if (sub_content.IsAscii()) {
3490  position = StringMatchBackwards(sub_content.ToAsciiVector(),
3491  pat_vector,
3492  start_index);
3493  } else {
3494  position = StringMatchBackwards(sub_content.ToUC16Vector(),
3495  pat_vector,
3496  start_index);
3497  }
3498  } else {
3499  Vector<const uc16> pat_vector = pat_content.ToUC16Vector();
3500  if (sub_content.IsAscii()) {
3501  position = StringMatchBackwards(sub_content.ToAsciiVector(),
3502  pat_vector,
3503  start_index);
3504  } else {
3505  position = StringMatchBackwards(sub_content.ToUC16Vector(),
3506  pat_vector,
3507  start_index);
3508  }
3509  }
3510 
3511  return Smi::FromInt(position);
3512 }
3513 
3514 
3515 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
3516  NoHandleAllocation ha;
3517  ASSERT(args.length() == 2);
3518 
3519  CONVERT_ARG_CHECKED(String, str1, 0);
3520  CONVERT_ARG_CHECKED(String, str2, 1);
3521 
3522  if (str1 == str2) return Smi::FromInt(0); // Equal.
3523  int str1_length = str1->length();
3524  int str2_length = str2->length();
3525 
3526  // Decide trivial cases without flattening.
3527  if (str1_length == 0) {
3528  if (str2_length == 0) return Smi::FromInt(0); // Equal.
3529  return Smi::FromInt(-str2_length);
3530  } else {
3531  if (str2_length == 0) return Smi::FromInt(str1_length);
3532  }
3533 
3534  int end = str1_length < str2_length ? str1_length : str2_length;
3535 
3536  // No need to flatten if we are going to find the answer on the first
3537  // character. At this point we know there is at least one character
3538  // in each string, due to the trivial case handling above.
3539  int d = str1->Get(0) - str2->Get(0);
3540  if (d != 0) return Smi::FromInt(d);
3541 
3542  str1->TryFlatten();
3543  str2->TryFlatten();
3544 
3545  StringInputBuffer& buf1 =
3546  *isolate->runtime_state()->string_locale_compare_buf1();
3547  StringInputBuffer& buf2 =
3548  *isolate->runtime_state()->string_locale_compare_buf2();
3549 
3550  buf1.Reset(str1);
3551  buf2.Reset(str2);
3552 
3553  for (int i = 0; i < end; i++) {
3554  uint16_t char1 = buf1.GetNext();
3555  uint16_t char2 = buf2.GetNext();
3556  if (char1 != char2) return Smi::FromInt(char1 - char2);
3557  }
3558 
3559  return Smi::FromInt(str1_length - str2_length);
3560 }
3561 
3562 
3563 RUNTIME_FUNCTION(MaybeObject*, Runtime_SubString) {
3564  NoHandleAllocation ha;
3565  ASSERT(args.length() == 3);
3566 
3567  CONVERT_ARG_CHECKED(String, value, 0);
3568  int start, end;
3569  // We have a fast integer-only case here to avoid a conversion to double in
3570  // the common case where from and to are Smis.
3571  if (args[1]->IsSmi() && args[2]->IsSmi()) {
3572  CONVERT_SMI_ARG_CHECKED(from_number, 1);
3573  CONVERT_SMI_ARG_CHECKED(to_number, 2);
3574  start = from_number;
3575  end = to_number;
3576  } else {
3577  CONVERT_DOUBLE_ARG_CHECKED(from_number, 1);
3578  CONVERT_DOUBLE_ARG_CHECKED(to_number, 2);
3579  start = FastD2IChecked(from_number);
3580  end = FastD2IChecked(to_number);
3581  }
3582  RUNTIME_ASSERT(end >= start);
3583  RUNTIME_ASSERT(start >= 0);
3584  RUNTIME_ASSERT(end <= value->length());
3585  isolate->counters()->sub_string_runtime()->Increment();
3586  return value->SubString(start, end);
3587 }
3588 
3589 
3590 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) {
3591  ASSERT_EQ(3, args.length());
3592 
3593  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
3595  CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2);
3596  HandleScope handles;
3597 
3598  RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
3599  if (global_cache.HasException()) return Failure::Exception();
3600 
3601  int capture_count = regexp->CaptureCount();
3602 
3603  Zone* zone = isolate->runtime_zone();
3604  ZoneScope zone_space(zone, DELETE_ON_EXIT);
3605  ZoneList<int> offsets(8, zone);
3606 
3607  while (true) {
3608  int32_t* match = global_cache.FetchNext();
3609  if (match == NULL) break;
3610  offsets.Add(match[0], zone); // start
3611  offsets.Add(match[1], zone); // end
3612  }
3613 
3614  if (global_cache.HasException()) return Failure::Exception();
3615 
3616  if (offsets.length() == 0) {
3617  // Not a single match.
3618  return isolate->heap()->null_value();
3619  }
3620 
3621  RegExpImpl::SetLastMatchInfo(regexp_info,
3622  subject,
3623  capture_count,
3624  global_cache.LastSuccessfulMatch());
3625 
3626  int matches = offsets.length() / 2;
3627  Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches);
3628  Handle<String> substring =
3629  isolate->factory()->NewSubString(subject, offsets.at(0), offsets.at(1));
3630  elements->set(0, *substring);
3631  for (int i = 1; i < matches; i++) {
3632  HandleScope temp_scope(isolate);
3633  int from = offsets.at(i * 2);
3634  int to = offsets.at(i * 2 + 1);
3635  Handle<String> substring =
3636  isolate->factory()->NewProperSubString(subject, from, to);
3637  elements->set(i, *substring);
3638  }
3639  Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements);
3640  result->set_length(Smi::FromInt(matches));
3641  return *result;
3642 }
3643 
3644 
3645 // Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain
3646 // separate last match info. See comment on that function.
3647 template<bool has_capture>
3648 static MaybeObject* SearchRegExpMultiple(
3649  Isolate* isolate,
3650  Handle<String> subject,
3651  Handle<JSRegExp> regexp,
3652  Handle<JSArray> last_match_array,
3653  Handle<JSArray> result_array) {
3654  ASSERT(subject->IsFlat());
3655  ASSERT_NE(has_capture, regexp->CaptureCount() == 0);
3656 
3657  int capture_count = regexp->CaptureCount();
3658  int subject_length = subject->length();
3659 
3660  static const int kMinLengthToCache = 0x1000;
3661 
3662  if (subject_length > kMinLengthToCache) {
3664  isolate->heap(),
3665  *subject,
3666  regexp->data(),
3668  if (*cached_answer != Smi::FromInt(0)) {
3669  Handle<FixedArray> cached_fixed_array =
3670  Handle<FixedArray>(FixedArray::cast(*cached_answer));
3671  // The cache FixedArray is a COW-array and can therefore be reused.
3672  isolate->factory()->SetContent(result_array, cached_fixed_array);
3673  // The actual length of the result array is stored in the last element of
3674  // the backing store (the backing FixedArray may have a larger capacity).
3675  Object* cached_fixed_array_last_element =
3676  cached_fixed_array->get(cached_fixed_array->length() - 1);
3677  Smi* js_array_length = Smi::cast(cached_fixed_array_last_element);
3678  result_array->set_length(js_array_length);
3680  last_match_array, subject, capture_count, NULL);
3681  return *result_array;
3682  }
3683  }
3684 
3685  RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
3686  if (global_cache.HasException()) return Failure::Exception();
3687 
3688  Handle<FixedArray> result_elements;
3689  if (result_array->HasFastObjectElements()) {
3690  result_elements =
3691  Handle<FixedArray>(FixedArray::cast(result_array->elements()));
3692  }
3693  if (result_elements.is_null() || result_elements->length() < 16) {
3694  result_elements = isolate->factory()->NewFixedArrayWithHoles(16);
3695  }
3696 
3697  FixedArrayBuilder builder(result_elements);
3698 
3699  // Position to search from.
3700  int match_start = -1;
3701  int match_end = 0;
3702  bool first = true;
3703 
3704  // Two smis before and after the match, for very long strings.
3705  static const int kMaxBuilderEntriesPerRegExpMatch = 5;
3706 
3707  while (true) {
3708  int32_t* current_match = global_cache.FetchNext();
3709  if (current_match == NULL) break;
3710  match_start = current_match[0];
3711  builder.EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3712  if (match_end < match_start) {
3714  match_end,
3715  match_start);
3716  }
3717  match_end = current_match[1];
3718  {
3719  // Avoid accumulating new handles inside loop.
3720  HandleScope temp_scope(isolate);
3721  Handle<String> match;
3722  if (!first) {
3723  match = isolate->factory()->NewProperSubString(subject,
3724  match_start,
3725  match_end);
3726  } else {
3727  match = isolate->factory()->NewSubString(subject,
3728  match_start,
3729  match_end);
3730  first = false;
3731  }
3732 
3733  if (has_capture) {
3734  // Arguments array to replace function is match, captures, index and
3735  // subject, i.e., 3 + capture count in total.
3736  Handle<FixedArray> elements =
3737  isolate->factory()->NewFixedArray(3 + capture_count);
3738 
3739  elements->set(0, *match);
3740  for (int i = 1; i <= capture_count; i++) {
3741  int start = current_match[i * 2];
3742  if (start >= 0) {
3743  int end = current_match[i * 2 + 1];
3744  ASSERT(start <= end);
3745  Handle<String> substring =
3746  isolate->factory()->NewSubString(subject, start, end);
3747  elements->set(i, *substring);
3748  } else {
3749  ASSERT(current_match[i * 2 + 1] < 0);
3750  elements->set(i, isolate->heap()->undefined_value());
3751  }
3752  }
3753  elements->set(capture_count + 1, Smi::FromInt(match_start));
3754  elements->set(capture_count + 2, *subject);
3755  builder.Add(*isolate->factory()->NewJSArrayWithElements(elements));
3756  } else {
3757  builder.Add(*match);
3758  }
3759  }
3760  }
3761 
3762  if (global_cache.HasException()) return Failure::Exception();
3763 
3764  if (match_start >= 0) {
3765  // Finished matching, with at least one match.
3766  if (match_end < subject_length) {
3768  match_end,
3769  subject_length);
3770  }
3771 
3773  last_match_array, subject, capture_count, NULL);
3774 
3775  if (subject_length > kMinLengthToCache) {
3776  // Store the length of the result array into the last element of the
3777  // backing FixedArray.
3778  builder.EnsureCapacity(1);
3779  Handle<FixedArray> fixed_array = builder.array();
3780  fixed_array->set(fixed_array->length() - 1,
3781  Smi::FromInt(builder.length()));
3782  // Cache the result and turn the FixedArray into a COW array.
3783  RegExpResultsCache::Enter(isolate->heap(),
3784  *subject,
3785  regexp->data(),
3786  *fixed_array,
3788  }
3789  return *builder.ToJSArray(result_array);
3790  } else {
3791  return isolate->heap()->null_value(); // No matches at all.
3792  }
3793 }
3794 
3795 
3796 // This is only called for StringReplaceGlobalRegExpWithFunction. This sets
3797 // lastMatchInfoOverride to maintain the last match info, so we don't need to
3798 // set any other last match array info.
3799 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) {
3800  ASSERT(args.length() == 4);
3801  HandleScope handles(isolate);
3802 
3803  CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
3804  if (!subject->IsFlat()) FlattenString(subject);
3806  CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2);
3807  CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3);
3808 
3809  ASSERT(last_match_info->HasFastObjectElements());
3810  ASSERT(regexp->GetFlags().is_global());
3811 
3812  if (regexp->CaptureCount() == 0) {
3813  return SearchRegExpMultiple<false>(
3814  isolate, subject, regexp, last_match_info, result_array);
3815  } else {
3816  return SearchRegExpMultiple<true>(
3817  isolate, subject, regexp, last_match_info, result_array);
3818  }
3819 }
3820 
3821 
3822 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) {
3823  NoHandleAllocation ha;
3824  ASSERT(args.length() == 2);
3825  CONVERT_SMI_ARG_CHECKED(radix, 1);
3826  RUNTIME_ASSERT(2 <= radix && radix <= 36);
3827 
3828  // Fast case where the result is a one character string.
3829  if (args[0]->IsSmi()) {
3830  int value = args.smi_at(0);
3831  if (value >= 0 && value < radix) {
3832  // Character array used for conversion.
3833  static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
3834  return isolate->heap()->
3835  LookupSingleCharacterStringFromCode(kCharTable[value]);
3836  }
3837  }
3838 
3839  // Slow case.
3840  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
3841  if (isnan(value)) {
3842  return *isolate->factory()->nan_symbol();
3843  }
3844  if (isinf(value)) {
3845  if (value < 0) {
3846  return *isolate->factory()->minus_infinity_symbol();
3847  }
3848  return *isolate->factory()->infinity_symbol();
3849  }
3850  char* str = DoubleToRadixCString(value, radix);
3851  MaybeObject* result =
3852  isolate->heap()->AllocateStringFromAscii(CStrVector(str));
3853  DeleteArray(str);
3854  return result;
3855 }
3856 
3857 
3858 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) {
3859  NoHandleAllocation ha;
3860  ASSERT(args.length() == 2);
3861 
3862  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
3863  if (isnan(value)) {
3864  return *isolate->factory()->nan_symbol();
3865  }
3866  if (isinf(value)) {
3867  if (value < 0) {
3868  return *isolate->factory()->minus_infinity_symbol();
3869  }
3870  return *isolate->factory()->infinity_symbol();
3871  }
3872  CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
3873  int f = FastD2IChecked(f_number);
3874  RUNTIME_ASSERT(f >= 0);
3875  char* str = DoubleToFixedCString(value, f);
3876  MaybeObject* res =
3877  isolate->heap()->AllocateStringFromAscii(CStrVector(str));
3878  DeleteArray(str);
3879  return res;
3880 }
3881 
3882 
3883 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) {
3884  NoHandleAllocation ha;
3885  ASSERT(args.length() == 2);
3886 
3887  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
3888  if (isnan(value)) {
3889  return *isolate->factory()->nan_symbol();
3890  }
3891  if (isinf(value)) {
3892  if (value < 0) {
3893  return *isolate->factory()->minus_infinity_symbol();
3894  }
3895  return *isolate->factory()->infinity_symbol();
3896  }
3897  CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
3898  int f = FastD2IChecked(f_number);
3899  RUNTIME_ASSERT(f >= -1 && f <= 20);
3900  char* str = DoubleToExponentialCString(value, f);
3901  MaybeObject* res =
3902  isolate->heap()->AllocateStringFromAscii(CStrVector(str));
3903  DeleteArray(str);
3904  return res;
3905 }
3906 
3907 
3908 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) {
3909  NoHandleAllocation ha;
3910  ASSERT(args.length() == 2);
3911 
3912  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
3913  if (isnan(value)) {
3914  return *isolate->factory()->nan_symbol();
3915  }
3916  if (isinf(value)) {
3917  if (value < 0) {
3918  return *isolate->factory()->minus_infinity_symbol();
3919  }
3920  return *isolate->factory()->infinity_symbol();
3921  }
3922  CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
3923  int f = FastD2IChecked(f_number);
3924  RUNTIME_ASSERT(f >= 1 && f <= 21);
3925  char* str = DoubleToPrecisionCString(value, f);
3926  MaybeObject* res =
3927  isolate->heap()->AllocateStringFromAscii(CStrVector(str));
3928  DeleteArray(str);
3929  return res;
3930 }
3931 
3932 
3933 // Returns a single character string where first character equals
3934 // string->Get(index).
3935 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
3936  if (index < static_cast<uint32_t>(string->length())) {
3937  string->TryFlatten();
3939  string->Get(index));
3940  }
3941  return Execution::CharAt(string, index);
3942 }
3943 
3944 
3945 MaybeObject* Runtime::GetElementOrCharAt(Isolate* isolate,
3946  Handle<Object> object,
3947  uint32_t index) {
3948  // Handle [] indexing on Strings
3949  if (object->IsString()) {
3950  Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
3951  if (!result->IsUndefined()) return *result;
3952  }
3953 
3954  // Handle [] indexing on String objects
3955  if (object->IsStringObjectWithCharacterAt(index)) {
3956  Handle<JSValue> js_value = Handle<JSValue>::cast(object);
3957  Handle<Object> result =
3958  GetCharAt(Handle<String>(String::cast(js_value->value())), index);
3959  if (!result->IsUndefined()) return *result;
3960  }
3961 
3962  if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
3963  return object->GetPrototype()->GetElement(index);
3964  }
3965 
3966  return object->GetElement(index);
3967 }
3968 
3969 
3970 MaybeObject* Runtime::GetObjectProperty(Isolate* isolate,
3971  Handle<Object> object,
3972  Handle<Object> key) {
3973  HandleScope scope(isolate);
3974 
3975  if (object->IsUndefined() || object->IsNull()) {
3976  Handle<Object> args[2] = { key, object };
3977  Handle<Object> error =
3978  isolate->factory()->NewTypeError("non_object_property_load",
3979  HandleVector(args, 2));
3980  return isolate->Throw(*error);
3981  }
3982 
3983  // Check if the given key is an array index.
3984  uint32_t index;
3985  if (key->ToArrayIndex(&index)) {
3986  return GetElementOrCharAt(isolate, object, index);
3987  }
3988 
3989  // Convert the key to a string - possibly by calling back into JavaScript.
3990  Handle<String> name;
3991  if (key->IsString()) {
3992  name = Handle<String>::cast(key);
3993  } else {
3994  bool has_pending_exception = false;
3995  Handle<Object> converted =
3996  Execution::ToString(key, &has_pending_exception);
3997  if (has_pending_exception) return Failure::Exception();
3998  name = Handle<String>::cast(converted);
3999  }
4000 
4001  // Check if the name is trivially convertible to an index and get
4002  // the element if so.
4003  if (name->AsArrayIndex(&index)) {
4004  return GetElementOrCharAt(isolate, object, index);
4005  } else {
4006  return object->GetProperty(*name);
4007  }
4008 }
4009 
4010 
4011 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetProperty) {
4012  NoHandleAllocation ha;
4013  ASSERT(args.length() == 2);
4014 
4015  Handle<Object> object = args.at<Object>(0);
4016  Handle<Object> key = args.at<Object>(1);
4017 
4018  return Runtime::GetObjectProperty(isolate, object, key);
4019 }
4020 
4021 
4022 // KeyedStringGetProperty is called from KeyedLoadIC::GenerateGeneric.
4023 RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
4024  NoHandleAllocation ha;
4025  ASSERT(args.length() == 2);
4026 
4027  // Fast cases for getting named properties of the receiver JSObject
4028  // itself.
4029  //
4030  // The global proxy objects has to be excluded since LocalLookup on
4031  // the global proxy object can return a valid result even though the
4032  // global proxy object never has properties. This is the case
4033  // because the global proxy object forwards everything to its hidden
4034  // prototype including local lookups.
4035  //
4036  // Additionally, we need to make sure that we do not cache results
4037  // for objects that require access checks.
4038  if (args[0]->IsJSObject()) {
4039  if (!args[0]->IsJSGlobalProxy() &&
4040  !args[0]->IsAccessCheckNeeded() &&
4041  args[1]->IsString()) {
4042  JSObject* receiver = JSObject::cast(args[0]);
4043  String* key = String::cast(args[1]);
4044  if (receiver->HasFastProperties()) {
4045  // Attempt to use lookup cache.
4046  Map* receiver_map = receiver->map();
4047  KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache();
4048  int offset = keyed_lookup_cache->Lookup(receiver_map, key);
4049  if (offset != -1) {
4050  Object* value = receiver->FastPropertyAt(offset);
4051  return value->IsTheHole()
4052  ? isolate->heap()->undefined_value()
4053  : value;
4054  }
4055  // Lookup cache miss. Perform lookup and update the cache if
4056  // appropriate.
4057  LookupResult result(isolate);
4058  receiver->LocalLookup(key, &result);
4059  if (result.IsField()) {
4060  int offset = result.GetFieldIndex();
4061  keyed_lookup_cache->Update(receiver_map, key, offset);
4062  return receiver->FastPropertyAt(offset);
4063  }
4064  } else {
4065  // Attempt dictionary lookup.
4066  StringDictionary* dictionary = receiver->property_dictionary();
4067  int entry = dictionary->FindEntry(key);
4068  if ((entry != StringDictionary::kNotFound) &&
4069  (dictionary->DetailsAt(entry).type() == NORMAL)) {
4070  Object* value = dictionary->ValueAt(entry);
4071  if (!receiver->IsGlobalObject()) return value;
4072  value = JSGlobalPropertyCell::cast(value)->value();
4073  if (!value->IsTheHole()) return value;
4074  // If value is the hole do the general lookup.
4075  }
4076  }
4077  } else if (FLAG_smi_only_arrays && args.at<Object>(1)->IsSmi()) {
4078  // JSObject without a string key. If the key is a Smi, check for a
4079  // definite out-of-bounds access to elements, which is a strong indicator
4080  // that subsequent accesses will also call the runtime. Proactively
4081  // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
4082  // doubles for those future calls in the case that the elements would
4083  // become FAST_DOUBLE_ELEMENTS.
4084  Handle<JSObject> js_object(args.at<JSObject>(0));
4085  ElementsKind elements_kind = js_object->GetElementsKind();
4086  if (IsFastElementsKind(elements_kind) &&
4087  !IsFastObjectElementsKind(elements_kind)) {
4088  FixedArrayBase* elements = js_object->elements();
4089  if (args.at<Smi>(1)->value() >= elements->length()) {
4090  if (IsFastHoleyElementsKind(elements_kind)) {
4091  elements_kind = FAST_HOLEY_ELEMENTS;
4092  } else {
4093  elements_kind = FAST_ELEMENTS;
4094  }
4095  MaybeObject* maybe_object = TransitionElements(js_object,
4096  elements_kind,
4097  isolate);
4098  if (maybe_object->IsFailure()) return maybe_object;
4099  }
4100  }
4101  }
4102  } else if (args[0]->IsString() && args[1]->IsSmi()) {
4103  // Fast case for string indexing using [] with a smi index.
4104  HandleScope scope(isolate);
4105  Handle<String> str = args.at<String>(0);
4106  int index = args.smi_at(1);
4107  if (index >= 0 && index < str->length()) {
4108  Handle<Object> result = GetCharAt(str, index);
4109  return *result;
4110  }
4111  }
4112 
4113  // Fall back to GetObjectProperty.
4114  return Runtime::GetObjectProperty(isolate,
4115  args.at<Object>(0),
4116  args.at<Object>(1));
4117 }
4118 
4119 
4120 static bool IsValidAccessor(Handle<Object> obj) {
4121  return obj->IsUndefined() || obj->IsSpecFunction() || obj->IsNull();
4122 }
4123 
4124 
4125 // Implements part of 8.12.9 DefineOwnProperty.
4126 // There are 3 cases that lead here:
4127 // Step 4b - define a new accessor property.
4128 // Steps 9c & 12 - replace an existing data property with an accessor property.
4129 // Step 12 - update an existing accessor property with an accessor or generic
4130 // descriptor.
4131 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) {
4132  ASSERT(args.length() == 5);
4133  HandleScope scope(isolate);
4135  RUNTIME_ASSERT(!obj->IsNull());
4137  CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
4138  RUNTIME_ASSERT(IsValidAccessor(getter));
4139  CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
4140  RUNTIME_ASSERT(IsValidAccessor(setter));
4141  CONVERT_SMI_ARG_CHECKED(unchecked, 4);
4142  RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4143  PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
4144 
4145  bool fast = obj->HasFastProperties();
4146  JSObject::DefineAccessor(obj, name, getter, setter, attr);
4147  if (fast) JSObject::TransformToFastProperties(obj, 0);
4148  return isolate->heap()->undefined_value();
4149 }
4150 
4151 // Implements part of 8.12.9 DefineOwnProperty.
4152 // There are 3 cases that lead here:
4153 // Step 4a - define a new data property.
4154 // Steps 9b & 12 - replace an existing accessor property with a data property.
4155 // Step 12 - update an existing data property with a data or generic
4156 // descriptor.
4157 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
4158  ASSERT(args.length() == 4);
4159  HandleScope scope(isolate);
4160  CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
4162  CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2);
4163  CONVERT_SMI_ARG_CHECKED(unchecked, 3);
4164  RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4165  PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
4166 
4167  LookupResult result(isolate);
4168  js_object->LocalLookupRealNamedProperty(*name, &result);
4169 
4170  // Special case for callback properties.
4171  if (result.IsPropertyCallbacks()) {
4172  Object* callback = result.GetCallbackObject();
4173  // To be compatible with Safari we do not change the value on API objects
4174  // in Object.defineProperty(). Firefox disagrees here, and actually changes
4175  // the value.
4176  if (callback->IsAccessorInfo()) {
4177  return isolate->heap()->undefined_value();
4178  }
4179  // Avoid redefining foreign callback as data property, just use the stored
4180  // setter to update the value instead.
4181  // TODO(mstarzinger): So far this only works if property attributes don't
4182  // change, this should be fixed once we cleanup the underlying code.
4183  if (callback->IsForeign() && result.GetAttributes() == attr) {
4184  return js_object->SetPropertyWithCallback(callback,
4185  *name,
4186  *obj_value,
4187  result.holder(),
4188  kStrictMode);
4189  }
4190  }
4191 
4192  // Take special care when attributes are different and there is already
4193  // a property. For simplicity we normalize the property which enables us
4194  // to not worry about changing the instance_descriptor and creating a new
4195  // map. The current version of SetObjectProperty does not handle attributes
4196  // correctly in the case where a property is a field and is reset with
4197  // new attributes.
4198  if (result.IsFound() &&
4199  (attr != result.GetAttributes() || result.IsPropertyCallbacks())) {
4200  // New attributes - normalize to avoid writing to instance descriptor
4201  if (js_object->IsJSGlobalProxy()) {
4202  // Since the result is a property, the prototype will exist so
4203  // we don't have to check for null.
4204  js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype()));
4205  }
4207  // Use IgnoreAttributes version since a readonly property may be
4208  // overridden and SetProperty does not allow this.
4209  return js_object->SetLocalPropertyIgnoreAttributes(*name,
4210  *obj_value,
4211  attr);
4212  }
4213 
4214  return Runtime::ForceSetObjectProperty(isolate,
4215  js_object,
4216  name,
4217  obj_value,
4218  attr);
4219 }
4220 
4221 
4222 MaybeObject* Runtime::SetObjectProperty(Isolate* isolate,
4223  Handle<Object> object,
4224  Handle<Object> key,
4225  Handle<Object> value,
4226  PropertyAttributes attr,
4227  StrictModeFlag strict_mode) {
4228  SetPropertyMode set_mode = attr == NONE ? SET_PROPERTY : DEFINE_PROPERTY;
4229  HandleScope scope(isolate);
4230 
4231  if (object->IsUndefined() || object->IsNull()) {
4232  Handle<Object> args[2] = { key, object };
4233  Handle<Object> error =
4234  isolate->factory()->NewTypeError("non_object_property_store",
4235  HandleVector(args, 2));
4236  return isolate->Throw(*error);
4237  }
4238 
4239  if (object->IsJSProxy()) {
4240  bool has_pending_exception = false;
4241  Handle<Object> name = Execution::ToString(key, &has_pending_exception);
4242  if (has_pending_exception) return Failure::Exception();
4243  return JSProxy::cast(*object)->SetProperty(
4244  String::cast(*name), *value, attr, strict_mode);
4245  }
4246 
4247  // If the object isn't a JavaScript object, we ignore the store.
4248  if (!object->IsJSObject()) return *value;
4249 
4250  Handle<JSObject> js_object = Handle<JSObject>::cast(object);
4251 
4252  // Check if the given key is an array index.
4253  uint32_t index;
4254  if (key->ToArrayIndex(&index)) {
4255  // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
4256  // of a string using [] notation. We need to support this too in
4257  // JavaScript.
4258  // In the case of a String object we just need to redirect the assignment to
4259  // the underlying string if the index is in range. Since the underlying
4260  // string does nothing with the assignment then we can ignore such
4261  // assignments.
4262  if (js_object->IsStringObjectWithCharacterAt(index)) {
4263  return *value;
4264  }
4265 
4266  js_object->ValidateElements();
4268  js_object, index, value, attr, strict_mode, set_mode);
4269  js_object->ValidateElements();
4270  if (result.is_null()) return Failure::Exception();
4271  return *value;
4272  }
4273 
4274  if (key->IsString()) {
4275  Handle<Object> result;
4276  if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
4277  result = JSObject::SetElement(
4278  js_object, index, value, attr, strict_mode, set_mode);
4279  } else {
4280  Handle<String> key_string = Handle<String>::cast(key);
4281  key_string->TryFlatten();
4282  result = JSReceiver::SetProperty(
4283  js_object, key_string, value, attr, strict_mode);
4284  }
4285  if (result.is_null()) return Failure::Exception();
4286  return *value;
4287  }
4288 
4289  // Call-back into JavaScript to convert the key to a string.
4290  bool has_pending_exception = false;
4291  Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
4292  if (has_pending_exception) return Failure::Exception();
4293  Handle<String> name = Handle<String>::cast(converted);
4294 
4295  if (name->AsArrayIndex(&index)) {
4296  return js_object->SetElement(
4297  index, *value, attr, strict_mode, true, set_mode);
4298  } else {
4299  return js_object->SetProperty(*name, *value, attr, strict_mode);
4300  }
4301 }
4302 
4303 
4305  Handle<JSObject> js_object,
4306  Handle<Object> key,
4307  Handle<Object> value,
4308  PropertyAttributes attr) {
4309  HandleScope scope(isolate);
4310 
4311  // Check if the given key is an array index.
4312  uint32_t index;
4313  if (key->ToArrayIndex(&index)) {
4314  // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
4315  // of a string using [] notation. We need to support this too in
4316  // JavaScript.
4317  // In the case of a String object we just need to redirect the assignment to
4318  // the underlying string if the index is in range. Since the underlying
4319  // string does nothing with the assignment then we can ignore such
4320  // assignments.
4321  if (js_object->IsStringObjectWithCharacterAt(index)) {
4322  return *value;
4323  }
4324 
4325  return js_object->SetElement(
4326  index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
4327  }
4328 
4329  if (key->IsString()) {
4330  if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
4331  return js_object->SetElement(
4332  index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
4333  } else {
4334  Handle<String> key_string = Handle<String>::cast(key);
4335  key_string->TryFlatten();
4336  return js_object->SetLocalPropertyIgnoreAttributes(*key_string,
4337  *value,
4338  attr);
4339  }
4340  }
4341 
4342  // Call-back into JavaScript to convert the key to a string.
4343  bool has_pending_exception = false;
4344  Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
4345  if (has_pending_exception) return Failure::Exception();
4346  Handle<String> name = Handle<String>::cast(converted);
4347 
4348  if (name->AsArrayIndex(&index)) {
4349  return js_object->SetElement(
4350  index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
4351  } else {
4352  return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr);
4353  }
4354 }
4355 
4356 
4358  Handle<JSReceiver> receiver,
4359  Handle<Object> key) {
4360  HandleScope scope(isolate);
4361 
4362  // Check if the given key is an array index.
4363  uint32_t index;
4364  if (key->ToArrayIndex(&index)) {
4365  // In Firefox/SpiderMonkey, Safari and Opera you can access the
4366  // characters of a string using [] notation. In the case of a
4367  // String object we just need to redirect the deletion to the
4368  // underlying string if the index is in range. Since the
4369  // underlying string does nothing with the deletion, we can ignore
4370  // such deletions.
4371  if (receiver->IsStringObjectWithCharacterAt(index)) {
4372  return isolate->heap()->true_value();
4373  }
4374 
4375  return receiver->DeleteElement(index, JSReceiver::FORCE_DELETION);
4376  }
4377 
4378  Handle<String> key_string;
4379  if (key->IsString()) {
4380  key_string = Handle<String>::cast(key);
4381  } else {
4382  // Call-back into JavaScript to convert the key to a string.
4383  bool has_pending_exception = false;
4384  Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
4385  if (has_pending_exception) return Failure::Exception();
4386  key_string = Handle<String>::cast(converted);
4387  }
4388 
4389  key_string->TryFlatten();
4390  return receiver->DeleteProperty(*key_string, JSReceiver::FORCE_DELETION);
4391 }
4392 
4393 
4394 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) {
4395  NoHandleAllocation ha;
4396  RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
4397 
4398  Handle<Object> object = args.at<Object>(0);
4399  Handle<Object> key = args.at<Object>(1);
4400  Handle<Object> value = args.at<Object>(2);
4401  CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3);
4403  (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4404  // Compute attributes.
4405  PropertyAttributes attributes =
4406  static_cast<PropertyAttributes>(unchecked_attributes);
4407 
4408  StrictModeFlag strict_mode = kNonStrictMode;
4409  if (args.length() == 5) {
4410  CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode_flag, 4);
4411  strict_mode = strict_mode_flag;
4412  }
4413 
4414  return Runtime::SetObjectProperty(isolate,
4415  object,
4416  key,
4417  value,
4418  attributes,
4419  strict_mode);
4420 }
4421 
4422 
4423 RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsSmiToDouble) {
4424  NoHandleAllocation ha;
4425  RUNTIME_ASSERT(args.length() == 1);
4426  Handle<Object> object = args.at<Object>(0);
4427  if (object->IsJSObject()) {
4428  Handle<JSObject> js_object(Handle<JSObject>::cast(object));
4429  ElementsKind new_kind = js_object->HasFastHoleyElements()
4432  return TransitionElements(object, new_kind, isolate);
4433  } else {
4434  return *object;
4435  }
4436 }
4437 
4438 
4439 RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsDoubleToObject) {
4440  NoHandleAllocation ha;
4441  RUNTIME_ASSERT(args.length() == 1);
4442  Handle<Object> object = args.at<Object>(0);
4443  if (object->IsJSObject()) {
4444  Handle<JSObject> js_object(Handle<JSObject>::cast(object));
4445  ElementsKind new_kind = js_object->HasFastHoleyElements()
4447  : FAST_ELEMENTS;
4448  return TransitionElements(object, new_kind, isolate);
4449  } else {
4450  return *object;
4451  }
4452 }
4453 
4454 
4455 // Set the native flag on the function.
4456 // This is used to decide if we should transform null and undefined
4457 // into the global object when doing call and apply.
4458 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) {
4459  NoHandleAllocation ha;
4460  RUNTIME_ASSERT(args.length() == 1);
4461 
4462  Handle<Object> object = args.at<Object>(0);
4463 
4464  if (object->IsJSFunction()) {
4465  JSFunction* func = JSFunction::cast(*object);
4466  func->shared()->set_native(true);
4467  }
4468  return isolate->heap()->undefined_value();
4469 }
4470 
4471 
4472 RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) {
4473  RUNTIME_ASSERT(args.length() == 5);
4475  CONVERT_SMI_ARG_CHECKED(store_index, 1);
4476  Handle<Object> value = args.at<Object>(2);
4477  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 3);
4478  CONVERT_SMI_ARG_CHECKED(literal_index, 4);
4479  HandleScope scope;
4480 
4481  Object* raw_boilerplate_object = literals->get(literal_index);
4482  Handle<JSArray> boilerplate_object(JSArray::cast(raw_boilerplate_object));
4483  ElementsKind elements_kind = object->GetElementsKind();
4484  ASSERT(IsFastElementsKind(elements_kind));
4485  // Smis should never trigger transitions.
4486  ASSERT(!value->IsSmi());
4487 
4488  if (value->IsNumber()) {
4489  ASSERT(IsFastSmiElementsKind(elements_kind));
4490  ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
4494  boilerplate_object->GetElementsKind(),
4495  transitioned_kind)) {
4496  JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
4497  }
4498  JSObject::TransitionElementsKind(object, transitioned_kind);
4499  ASSERT(IsFastDoubleElementsKind(object->GetElementsKind()));
4500  FixedDoubleArray* double_array = FixedDoubleArray::cast(object->elements());
4501  HeapNumber* number = HeapNumber::cast(*value);
4502  double_array->set(store_index, number->Number());
4503  } else {
4504  ASSERT(IsFastSmiElementsKind(elements_kind) ||
4505  IsFastDoubleElementsKind(elements_kind));
4506  ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
4508  : FAST_ELEMENTS;
4509  JSObject::TransitionElementsKind(object, transitioned_kind);
4511  boilerplate_object->GetElementsKind(),
4512  transitioned_kind)) {
4513  JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
4514  }
4515  FixedArray* object_array = FixedArray::cast(object->elements());
4516  object_array->set(store_index, *value);
4517  }
4518  return *object;
4519 }
4520 
4521 
4522 // Check whether debugger and is about to step into the callback that is passed
4523 // to a built-in function such as Array.forEach.
4524 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugCallbackSupportsStepping) {
4525 #ifdef ENABLE_DEBUGGER_SUPPORT
4526  if (!isolate->IsDebuggerActive() || !isolate->debug()->StepInActive()) {
4527  return isolate->heap()->false_value();
4528  }
4529  CONVERT_ARG_CHECKED(Object, callback, 0);
4530  // We do not step into the callback if it's a builtin or not even a function.
4531  if (!callback->IsJSFunction() || JSFunction::cast(callback)->IsBuiltin()) {
4532  return isolate->heap()->false_value();
4533  }
4534  return isolate->heap()->true_value();
4535 #else
4536  return isolate->heap()->false_value();
4537 #endif // ENABLE_DEBUGGER_SUPPORT
4538 }
4539 
4540 
4541 // Set one shot breakpoints for the callback function that is passed to a
4542 // built-in function such as Array.forEach to enable stepping into the callback.
4543 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrepareStepInIfStepping) {
4544 #ifdef ENABLE_DEBUGGER_SUPPORT
4545  Debug* debug = isolate->debug();
4546  if (!debug->IsStepping()) return isolate->heap()->undefined_value();
4547  CONVERT_ARG_HANDLE_CHECKED(JSFunction, callback, 0);
4548  HandleScope scope(isolate);
4549  // When leaving the callback, step out has been activated, but not performed
4550  // if we do not leave the builtin. To be able to step into the callback
4551  // again, we need to clear the step out at this point.
4552  debug->ClearStepOut();
4553  debug->FloodWithOneShot(callback);
4554 #endif // ENABLE_DEBUGGER_SUPPORT
4555  return isolate->heap()->undefined_value();
4556 }
4557 
4558 
4559 // Set a local property, even if it is READ_ONLY. If the property does not
4560 // exist, it will be added with attributes NONE.
4561 RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) {
4562  NoHandleAllocation ha;
4563  RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
4564  CONVERT_ARG_CHECKED(JSObject, object, 0);
4565  CONVERT_ARG_CHECKED(String, name, 1);
4566  // Compute attributes.
4567  PropertyAttributes attributes = NONE;
4568  if (args.length() == 4) {
4569  CONVERT_SMI_ARG_CHECKED(unchecked_value, 3);
4570  // Only attribute bits should be set.
4572  (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4573  attributes = static_cast<PropertyAttributes>(unchecked_value);
4574  }
4575 
4576  return object->
4577  SetLocalPropertyIgnoreAttributes(name, args[2], attributes);
4578 }
4579 
4580 
4581 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteProperty) {
4582  NoHandleAllocation ha;
4583  ASSERT(args.length() == 3);
4584 
4585  CONVERT_ARG_CHECKED(JSReceiver, object, 0);
4586  CONVERT_ARG_CHECKED(String, key, 1);
4587  CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2);
4588  return object->DeleteProperty(key, (strict_mode == kStrictMode)
4591 }
4592 
4593 
4594 static Object* HasLocalPropertyImplementation(Isolate* isolate,
4595  Handle<JSObject> object,
4596  Handle<String> key) {
4597  if (object->HasLocalProperty(*key)) return isolate->heap()->true_value();
4598  // Handle hidden prototypes. If there's a hidden prototype above this thing
4599  // then we have to check it for properties, because they are supposed to
4600  // look like they are on this object.
4601  Handle<Object> proto(object->GetPrototype());
4602  if (proto->IsJSObject() &&
4603  Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) {
4604  return HasLocalPropertyImplementation(isolate,
4605  Handle<JSObject>::cast(proto),
4606  key);
4607  }
4608  return isolate->heap()->false_value();
4609 }
4610 
4611 
4612 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) {
4613  NoHandleAllocation ha;
4614  ASSERT(args.length() == 2);
4615  CONVERT_ARG_CHECKED(String, key, 1);
4616 
4617  uint32_t index;
4618  const bool key_is_array_index = key->AsArrayIndex(&index);
4619 
4620  Object* obj = args[0];
4621  // Only JS objects can have properties.
4622  if (obj->IsJSObject()) {
4623  JSObject* object = JSObject::cast(obj);
4624  // Fast case: either the key is a real named property or it is not
4625  // an array index and there are no interceptors or hidden
4626  // prototypes.
4627  if (object->HasRealNamedProperty(key)) return isolate->heap()->true_value();
4628  Map* map = object->map();
4629  if (!key_is_array_index &&
4630  !map->has_named_interceptor() &&
4631  !HeapObject::cast(map->prototype())->map()->is_hidden_prototype()) {
4632  return isolate->heap()->false_value();
4633  }
4634  // Slow case.
4635  HandleScope scope(isolate);
4636  return HasLocalPropertyImplementation(isolate,
4637  Handle<JSObject>(object),
4638  Handle<String>(key));
4639  } else if (obj->IsString() && key_is_array_index) {
4640  // Well, there is one exception: Handle [] on strings.
4641  String* string = String::cast(obj);
4642  if (index < static_cast<uint32_t>(string->length())) {
4643  return isolate->heap()->true_value();
4644  }
4645  }
4646  return isolate->heap()->false_value();
4647 }
4648 
4649 
4650 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) {
4651  NoHandleAllocation na;
4652  ASSERT(args.length() == 2);
4653  CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
4654  CONVERT_ARG_CHECKED(String, key, 1);
4655 
4656  bool result = receiver->HasProperty(key);
4657  if (isolate->has_pending_exception()) return Failure::Exception();
4658  return isolate->heap()->ToBoolean(result);
4659 }
4660 
4661 
4662 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasElement) {
4663  NoHandleAllocation na;
4664  ASSERT(args.length() == 2);
4665  CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
4666  CONVERT_SMI_ARG_CHECKED(index, 1);
4667 
4668  bool result = receiver->HasElement(index);
4669  if (isolate->has_pending_exception()) return Failure::Exception();
4670  return isolate->heap()->ToBoolean(result);
4671 }
4672 
4673 
4674 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) {
4675  NoHandleAllocation ha;
4676  ASSERT(args.length() == 2);
4677 
4678  CONVERT_ARG_CHECKED(JSObject, object, 0);
4679  CONVERT_ARG_CHECKED(String, key, 1);
4680 
4681  uint32_t index;
4682  if (key->AsArrayIndex(&index)) {
4683  JSObject::LocalElementType type = object->HasLocalElement(index);
4684  switch (type) {
4687  return isolate->heap()->false_value();
4690  return isolate->heap()->true_value();
4692  if (object->IsJSGlobalProxy()) {
4693  Object* proto = object->GetPrototype();
4694  if (proto->IsNull()) {
4695  return isolate->heap()->false_value();
4696  }
4697  ASSERT(proto->IsJSGlobalObject());
4698  object = JSObject::cast(proto);
4699  }
4700  FixedArray* elements = FixedArray::cast(object->elements());
4701  SeededNumberDictionary* dictionary = NULL;
4702  if (elements->map() ==
4703  isolate->heap()->non_strict_arguments_elements_map()) {
4704  dictionary = SeededNumberDictionary::cast(elements->get(1));
4705  } else {
4706  dictionary = SeededNumberDictionary::cast(elements);
4707  }
4708  int entry = dictionary->FindEntry(index);
4710  PropertyDetails details = dictionary->DetailsAt(entry);
4711  return isolate->heap()->ToBoolean(!details.IsDontEnum());
4712  }
4713  }
4714  }
4715 
4716  PropertyAttributes att = object->GetLocalPropertyAttribute(key);
4717  return isolate->heap()->ToBoolean(att != ABSENT && (att & DONT_ENUM) == 0);
4718 }
4719 
4720 
4721 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNames) {
4722  HandleScope scope(isolate);
4723  ASSERT(args.length() == 1);
4725  bool threw = false;
4726  Handle<JSArray> result = GetKeysFor(object, &threw);
4727  if (threw) return Failure::Exception();
4728  return *result;
4729 }
4730 
4731 
4732 // Returns either a FixedArray as Runtime_GetPropertyNames,
4733 // or, if the given object has an enum cache that contains
4734 // all enumerable properties of the object and its prototypes
4735 // have none, the map of the object. This is used to speed up
4736 // the check for deletions during a for-in.
4737 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNamesFast) {
4738  ASSERT(args.length() == 1);
4739 
4740  CONVERT_ARG_CHECKED(JSReceiver, raw_object, 0);
4741 
4742  if (raw_object->IsSimpleEnum()) return raw_object->map();
4743 
4744  HandleScope scope(isolate);
4745  Handle<JSReceiver> object(raw_object);
4746  bool threw = false;
4747  Handle<FixedArray> content =
4748  GetKeysInFixedArrayFor(object, INCLUDE_PROTOS, &threw);
4749  if (threw) return Failure::Exception();
4750 
4751  // Test again, since cache may have been built by preceding call.
4752  if (object->IsSimpleEnum()) return object->map();
4753 
4754  return *content;
4755 }
4756 
4757 
4758 // Find the length of the prototype chain that is to to handled as one. If a
4759 // prototype object is hidden it is to be viewed as part of the the object it
4760 // is prototype for.
4761 static int LocalPrototypeChainLength(JSObject* obj) {
4762  int count = 1;
4763  Object* proto = obj->GetPrototype();
4764  while (proto->IsJSObject() &&
4765  JSObject::cast(proto)->map()->is_hidden_prototype()) {
4766  count++;
4767  proto = JSObject::cast(proto)->GetPrototype();
4768  }
4769  return count;
4770 }
4771 
4772 
4773 // Return the names of the local named properties.
4774 // args[0]: object
4775 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) {
4776  HandleScope scope(isolate);
4777  ASSERT(args.length() == 1);
4778  if (!args[0]->IsJSObject()) {
4779  return isolate->heap()->undefined_value();
4780  }
4782 
4783  // Skip the global proxy as it has no properties and always delegates to the
4784  // real global object.
4785  if (obj->IsJSGlobalProxy()) {
4786  // Only collect names if access is permitted.
4787  if (obj->IsAccessCheckNeeded() &&
4788  !isolate->MayNamedAccess(*obj,
4789  isolate->heap()->undefined_value(),
4790  v8::ACCESS_KEYS)) {
4791  isolate->ReportFailedAccessCheck(*obj, v8::ACCESS_KEYS);
4792  return *isolate->factory()->NewJSArray(0);
4793  }
4794  obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
4795  }
4796 
4797  // Find the number of objects making up this.
4798  int length = LocalPrototypeChainLength(*obj);
4799 
4800  // Find the number of local properties for each of the objects.
4801  ScopedVector<int> local_property_count(length);
4802  int total_property_count = 0;
4803  Handle<JSObject> jsproto = obj;
4804  for (int i = 0; i < length; i++) {
4805  // Only collect names if access is permitted.
4806  if (jsproto->IsAccessCheckNeeded() &&
4807  !isolate->MayNamedAccess(*jsproto,
4808  isolate->heap()->undefined_value(),
4809  v8::ACCESS_KEYS)) {
4810  isolate->ReportFailedAccessCheck(*jsproto, v8::ACCESS_KEYS);
4811  return *isolate->factory()->NewJSArray(0);
4812  }
4813  int n;
4814  n = jsproto->NumberOfLocalProperties();
4815  local_property_count[i] = n;
4816  total_property_count += n;
4817  if (i < length - 1) {
4818  jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
4819  }
4820  }
4821 
4822  // Allocate an array with storage for all the property names.
4823  Handle<FixedArray> names =
4824  isolate->factory()->NewFixedArray(total_property_count);
4825 
4826  // Get the property names.
4827  jsproto = obj;
4828  int proto_with_hidden_properties = 0;
4829  int next_copy_index = 0;
4830  for (int i = 0; i < length; i++) {
4831  jsproto->GetLocalPropertyNames(*names, next_copy_index);
4832  next_copy_index += local_property_count[i];
4833  if (jsproto->HasHiddenProperties()) {
4834  proto_with_hidden_properties++;
4835  }
4836  if (i < length - 1) {
4837  jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
4838  }
4839  }
4840 
4841  // Filter out name of hidden propeties object.
4842  if (proto_with_hidden_properties > 0) {
4843  Handle<FixedArray> old_names = names;
4844  names = isolate->factory()->NewFixedArray(
4845  names->length() - proto_with_hidden_properties);
4846  int dest_pos = 0;
4847  for (int i = 0; i < total_property_count; i++) {
4848  Object* name = old_names->get(i);
4849  if (name == isolate->heap()->hidden_symbol()) {
4850  continue;
4851  }
4852  names->set(dest_pos++, name);
4853  }
4854  }
4855 
4856  return *isolate->factory()->NewJSArrayWithElements(names);
4857 }
4858 
4859 
4860 // Return the names of the local indexed properties.
4861 // args[0]: object
4862 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalElementNames) {
4863  HandleScope scope(isolate);
4864  ASSERT(args.length() == 1);
4865  if (!args[0]->IsJSObject()) {
4866  return isolate->heap()->undefined_value();
4867  }
4869 
4870  int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
4871  Handle<FixedArray> names = isolate->factory()->NewFixedArray(n);
4872  obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
4873  return *isolate->factory()->NewJSArrayWithElements(names);
4874 }
4875 
4876 
4877 // Return information on whether an object has a named or indexed interceptor.
4878 // args[0]: object
4879 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetInterceptorInfo) {
4880  HandleScope scope(isolate);
4881  ASSERT(args.length() == 1);
4882  if (!args[0]->IsJSObject()) {
4883  return Smi::FromInt(0);
4884  }
4886 
4887  int result = 0;
4888  if (obj->HasNamedInterceptor()) result |= 2;
4889  if (obj->HasIndexedInterceptor()) result |= 1;
4890 
4891  return Smi::FromInt(result);
4892 }
4893 
4894 
4895 // Return property names from named interceptor.
4896 // args[0]: object
4897 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetNamedInterceptorPropertyNames) {
4898  HandleScope scope(isolate);
4899  ASSERT(args.length() == 1);
4901 
4902  if (obj->HasNamedInterceptor()) {
4904  if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
4905  }
4906  return isolate->heap()->undefined_value();
4907 }
4908 
4909 
4910 // Return element names from indexed interceptor.
4911 // args[0]: object
4912 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetIndexedInterceptorElementNames) {
4913  HandleScope scope(isolate);
4914  ASSERT(args.length() == 1);
4916 
4917  if (obj->HasIndexedInterceptor()) {
4919  if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
4920  }
4921  return isolate->heap()->undefined_value();
4922 }
4923 
4924 
4925 RUNTIME_FUNCTION(MaybeObject*, Runtime_LocalKeys) {
4926  ASSERT_EQ(args.length(), 1);
4927  CONVERT_ARG_CHECKED(JSObject, raw_object, 0);
4928  HandleScope scope(isolate);
4929  Handle<JSObject> object(raw_object);
4930 
4931  if (object->IsJSGlobalProxy()) {
4932  // Do access checks before going to the global object.
4933  if (object->IsAccessCheckNeeded() &&
4934  !isolate->MayNamedAccess(*object, isolate->heap()->undefined_value(),
4935  v8::ACCESS_KEYS)) {
4936  isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
4937  return *isolate->factory()->NewJSArray(0);
4938  }
4939 
4940  Handle<Object> proto(object->GetPrototype());
4941  // If proxy is detached we simply return an empty array.
4942  if (proto->IsNull()) return *isolate->factory()->NewJSArray(0);
4943  object = Handle<JSObject>::cast(proto);
4944  }
4945 
4946  bool threw = false;
4947  Handle<FixedArray> contents =
4948  GetKeysInFixedArrayFor(object, LOCAL_ONLY, &threw);
4949  if (threw) return Failure::Exception();
4950 
4951  // Some fast paths through GetKeysInFixedArrayFor reuse a cached
4952  // property array and since the result is mutable we have to create
4953  // a fresh clone on each invocation.
4954  int length = contents->length();
4955  Handle<FixedArray> copy = isolate->factory()->NewFixedArray(length);
4956  for (int i = 0; i < length; i++) {
4957  Object* entry = contents->get(i);
4958  if (entry->IsString()) {
4959  copy->set(i, entry);
4960  } else {
4961  ASSERT(entry->IsNumber());
4962  HandleScope scope(isolate);
4963  Handle<Object> entry_handle(entry, isolate);
4964  Handle<Object> entry_str =
4965  isolate->factory()->NumberToString(entry_handle);
4966  copy->set(i, *entry_str);
4967  }
4968  }
4969  return *isolate->factory()->NewJSArrayWithElements(copy);
4970 }
4971 
4972 
4973 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
4974  NoHandleAllocation ha;
4975  ASSERT(args.length() == 1);
4976 
4977  // Compute the frame holding the arguments.
4978  JavaScriptFrameIterator it(isolate);
4979  it.AdvanceToArgumentsFrame();
4980  JavaScriptFrame* frame = it.frame();
4981 
4982  // Get the actual number of provided arguments.
4983  const uint32_t n = frame->ComputeParametersCount();
4984 
4985  // Try to convert the key to an index. If successful and within
4986  // index return the the argument from the frame.
4987  uint32_t index;
4988  if (args[0]->ToArrayIndex(&index) && index < n) {
4989  return frame->GetParameter(index);
4990  }
4991 
4992  // Convert the key to a string.
4993  HandleScope scope(isolate);
4994  bool exception = false;
4995  Handle<Object> converted =
4996  Execution::ToString(args.at<Object>(0), &exception);
4997  if (exception) return Failure::Exception();
4998  Handle<String> key = Handle<String>::cast(converted);
4999 
5000  // Try to convert the string key into an array index.
5001  if (key->AsArrayIndex(&index)) {
5002  if (index < n) {
5003  return frame->GetParameter(index);
5004  } else {
5005  return isolate->initial_object_prototype()->GetElement(index);
5006  }
5007  }
5008 
5009  // Handle special arguments properties.
5010  if (key->Equals(isolate->heap()->length_symbol())) return Smi::FromInt(n);
5011  if (key->Equals(isolate->heap()->callee_symbol())) {
5012  Object* function = frame->function();
5013  if (function->IsJSFunction() &&
5014  !JSFunction::cast(function)->shared()->is_classic_mode()) {
5015  return isolate->Throw(*isolate->factory()->NewTypeError(
5016  "strict_arguments_callee", HandleVector<Object>(NULL, 0)));
5017  }
5018  return function;
5019  }
5020 
5021  // Lookup in the initial Object.prototype object.
5022  return isolate->initial_object_prototype()->GetProperty(*key);
5023 }
5024 
5025 
5026 RUNTIME_FUNCTION(MaybeObject*, Runtime_ToFastProperties) {
5027  ASSERT(args.length() == 1);
5028  Object* object = args[0];
5029  return (object->IsJSObject() && !object->IsGlobalObject())
5031  : object;
5032 }
5033 
5034 
5035 RUNTIME_FUNCTION(MaybeObject*, Runtime_ToBool) {
5036  NoHandleAllocation ha;
5037  ASSERT(args.length() == 1);
5038 
5039  return args[0]->ToBoolean();
5040 }
5041 
5042 
5043 // Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
5044 // Possible optimizations: put the type string into the oddballs.
5045 RUNTIME_FUNCTION(MaybeObject*, Runtime_Typeof) {
5046  NoHandleAllocation ha;
5047 
5048  Object* obj = args[0];
5049  if (obj->IsNumber()) return isolate->heap()->number_symbol();
5050  HeapObject* heap_obj = HeapObject::cast(obj);
5051 
5052  // typeof an undetectable object is 'undefined'
5053  if (heap_obj->map()->is_undetectable()) {
5054  return isolate->heap()->undefined_symbol();
5055  }
5056 
5057  InstanceType instance_type = heap_obj->map()->instance_type();
5058  if (instance_type < FIRST_NONSTRING_TYPE) {
5059  return isolate->heap()->string_symbol();
5060  }
5061 
5062  switch (instance_type) {
5063  case ODDBALL_TYPE:
5064  if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
5065  return isolate->heap()->boolean_symbol();
5066  }
5067  if (heap_obj->IsNull()) {
5068  return FLAG_harmony_typeof
5069  ? isolate->heap()->null_symbol()
5070  : isolate->heap()->object_symbol();
5071  }
5072  ASSERT(heap_obj->IsUndefined());
5073  return isolate->heap()->undefined_symbol();
5074  case JS_FUNCTION_TYPE:
5076  return isolate->heap()->function_symbol();
5077  default:
5078  // For any kind of object not handled above, the spec rule for
5079  // host objects gives that it is okay to return "object"
5080  return isolate->heap()->object_symbol();
5081  }
5082 }
5083 
5084 
5085 static bool AreDigits(const char*s, int from, int to) {
5086  for (int i = from; i < to; i++) {
5087  if (s[i] < '0' || s[i] > '9') return false;
5088  }
5089 
5090  return true;
5091 }
5092 
5093 
5094 static int ParseDecimalInteger(const char*s, int from, int to) {
5095  ASSERT(to - from < 10); // Overflow is not possible.
5096  ASSERT(from < to);
5097  int d = s[from] - '0';
5098 
5099  for (int i = from + 1; i < to; i++) {
5100  d = 10 * d + (s[i] - '0');
5101  }
5102 
5103  return d;
5104 }
5105 
5106 
5107 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
5108  NoHandleAllocation ha;
5109  ASSERT(args.length() == 1);
5110  CONVERT_ARG_CHECKED(String, subject, 0);
5111  subject->TryFlatten();
5112 
5113  // Fast case: short integer or some sorts of junk values.
5114  int len = subject->length();
5115  if (subject->IsSeqAsciiString()) {
5116  if (len == 0) return Smi::FromInt(0);
5117 
5118  char const* data = SeqAsciiString::cast(subject)->GetChars();
5119  bool minus = (data[0] == '-');
5120  int start_pos = (minus ? 1 : 0);
5121 
5122  if (start_pos == len) {
5123  return isolate->heap()->nan_value();
5124  } else if (data[start_pos] > '9') {
5125  // Fast check for a junk value. A valid string may start from a
5126  // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit or
5127  // the 'I' character ('Infinity'). All of that have codes not greater than
5128  // '9' except 'I'.
5129  if (data[start_pos] != 'I') {
5130  return isolate->heap()->nan_value();
5131  }
5132  } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
5133  // The maximal/minimal smi has 10 digits. If the string has less digits we
5134  // know it will fit into the smi-data type.
5135  int d = ParseDecimalInteger(data, start_pos, len);
5136  if (minus) {
5137  if (d == 0) return isolate->heap()->minus_zero_value();
5138  d = -d;
5139  } else if (!subject->HasHashCode() &&
5140  len <= String::kMaxArrayIndexSize &&
5141  (len == 1 || data[0] != '0')) {
5142  // String hash is not calculated yet but all the data are present.
5143  // Update the hash field to speed up sequential convertions.
5144  uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
5145 #ifdef DEBUG
5146  subject->Hash(); // Force hash calculation.
5147  ASSERT_EQ(static_cast<int>(subject->hash_field()),
5148  static_cast<int>(hash));
5149 #endif
5150  subject->set_hash_field(hash);
5151  }
5152  return Smi::FromInt(d);
5153  }
5154  }
5155 
5156  // Slower case.
5157  return isolate->heap()->NumberFromDouble(
5158  StringToDouble(isolate->unicode_cache(), subject, ALLOW_HEX));
5159 }
5160 
5161 
5162 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringFromCharCodeArray) {
5163  NoHandleAllocation ha;
5164  ASSERT(args.length() == 1);
5165 
5166  CONVERT_ARG_CHECKED(JSArray, codes, 0);
5167  int length = Smi::cast(codes->length())->value();
5168 
5169  // Check if the string can be ASCII.
5170  int i;
5171  for (i = 0; i < length; i++) {
5172  Object* element;
5173  { MaybeObject* maybe_element = codes->GetElement(i);
5174  // We probably can't get an exception here, but just in order to enforce
5175  // the checking of inputs in the runtime calls we check here.
5176  if (!maybe_element->ToObject(&element)) return maybe_element;
5177  }
5178  CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
5179  if ((chr & 0xffff) > String::kMaxAsciiCharCode)
5180  break;
5181  }
5182 
5183  MaybeObject* maybe_object = NULL;
5184  if (i == length) { // The string is ASCII.
5185  maybe_object = isolate->heap()->AllocateRawAsciiString(length);
5186  } else { // The string is not ASCII.
5187  maybe_object = isolate->heap()->AllocateRawTwoByteString(length);
5188  }
5189 
5190  Object* object = NULL;
5191  if (!maybe_object->ToObject(&object)) return maybe_object;
5192  String* result = String::cast(object);
5193  for (int i = 0; i < length; i++) {
5194  Object* element;
5195  { MaybeObject* maybe_element = codes->GetElement(i);
5196  if (!maybe_element->ToObject(&element)) return maybe_element;
5197  }
5198  CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
5199  result->Set(i, chr & 0xffff);
5200  }
5201  return result;
5202 }
5203 
5204 
5205 // kNotEscaped is generated by the following:
5206 //
5207 // #!/bin/perl
5208 // for (my $i = 0; $i < 256; $i++) {
5209 // print "\n" if $i % 16 == 0;
5210 // my $c = chr($i);
5211 // my $escaped = 1;
5212 // $escaped = 0 if $c =~ m#[A-Za-z0-9@*_+./-]#;
5213 // print $escaped ? "0, " : "1, ";
5214 // }
5215 
5216 
5217 static bool IsNotEscaped(uint16_t character) {
5218  // Only for 8 bit characters, the rest are always escaped (in a different way)
5219  ASSERT(character < 256);
5220  static const char kNotEscaped[256] = {
5221  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5222  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5223  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
5224  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
5225  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5226  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
5227  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5228  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
5229  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5230  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5231  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5232  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5233  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5234  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5235  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5236  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5237  };
5238  return kNotEscaped[character] != 0;
5239 }
5240 
5241 
5242 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIEscape) {
5243  const char hex_chars[] = "0123456789ABCDEF";
5244  NoHandleAllocation ha;
5245  ASSERT(args.length() == 1);
5246  CONVERT_ARG_CHECKED(String, source, 0);
5247 
5248  source->TryFlatten();
5249 
5250  int escaped_length = 0;
5251  int length = source->length();
5252  {
5254  isolate->runtime_state()->string_input_buffer());
5255  buffer->Reset(source);
5256  while (buffer->has_more()) {
5257  uint16_t character = buffer->GetNext();
5258  if (character >= 256) {
5259  escaped_length += 6;
5260  } else if (IsNotEscaped(character)) {
5261  escaped_length++;
5262  } else {
5263  escaped_length += 3;
5264  }
5265  // We don't allow strings that are longer than a maximal length.
5266  ASSERT(String::kMaxLength < 0x7fffffff - 6); // Cannot overflow.
5267  if (escaped_length > String::kMaxLength) {
5268  isolate->context()->mark_out_of_memory();
5270  }
5271  }
5272  }
5273  // No length change implies no change. Return original string if no change.
5274  if (escaped_length == length) {
5275  return source;
5276  }
5277  Object* o;
5278  { MaybeObject* maybe_o =
5279  isolate->heap()->AllocateRawAsciiString(escaped_length);
5280  if (!maybe_o->ToObject(&o)) return maybe_o;
5281  }
5282  String* destination = String::cast(o);
5283  int dest_position = 0;
5284 
5286  isolate->runtime_state()->string_input_buffer());
5287  buffer->Rewind();
5288  while (buffer->has_more()) {
5289  uint16_t chr = buffer->GetNext();
5290  if (chr >= 256) {
5291  destination->Set(dest_position, '%');
5292  destination->Set(dest_position+1, 'u');
5293  destination->Set(dest_position+2, hex_chars[chr >> 12]);
5294  destination->Set(dest_position+3, hex_chars[(chr >> 8) & 0xf]);
5295  destination->Set(dest_position+4, hex_chars[(chr >> 4) & 0xf]);
5296  destination->Set(dest_position+5, hex_chars[chr & 0xf]);
5297  dest_position += 6;
5298  } else if (IsNotEscaped(chr)) {
5299  destination->Set(dest_position, chr);
5300  dest_position++;
5301  } else {
5302  destination->Set(dest_position, '%');
5303  destination->Set(dest_position+1, hex_chars[chr >> 4]);
5304  destination->Set(dest_position+2, hex_chars[chr & 0xf]);
5305  dest_position += 3;
5306  }
5307  }
5308  return destination;
5309 }
5310 
5311 
5312 static inline int TwoDigitHex(uint16_t character1, uint16_t character2) {
5313  static const signed char kHexValue['g'] = {
5314  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5315  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5316  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5317  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
5318  -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5319  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5320  -1, 10, 11, 12, 13, 14, 15 };
5321 
5322  if (character1 > 'f') return -1;
5323  int hi = kHexValue[character1];
5324  if (hi == -1) return -1;
5325  if (character2 > 'f') return -1;
5326  int lo = kHexValue[character2];
5327  if (lo == -1) return -1;
5328  return (hi << 4) + lo;
5329 }
5330 
5331 
5332 static inline int Unescape(String* source,
5333  int i,
5334  int length,
5335  int* step) {
5336  uint16_t character = source->Get(i);
5337  int32_t hi = 0;
5338  int32_t lo = 0;
5339  if (character == '%' &&
5340  i <= length - 6 &&
5341  source->Get(i + 1) == 'u' &&
5342  (hi = TwoDigitHex(source->Get(i + 2),
5343  source->Get(i + 3))) != -1 &&
5344  (lo = TwoDigitHex(source->Get(i + 4),
5345  source->Get(i + 5))) != -1) {
5346  *step = 6;
5347  return (hi << 8) + lo;
5348  } else if (character == '%' &&
5349  i <= length - 3 &&
5350  (lo = TwoDigitHex(source->Get(i + 1),
5351  source->Get(i + 2))) != -1) {
5352  *step = 3;
5353  return lo;
5354  } else {
5355  *step = 1;
5356  return character;
5357  }
5358 }
5359 
5360 
5361 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) {
5362  NoHandleAllocation ha;
5363  ASSERT(args.length() == 1);
5364  CONVERT_ARG_CHECKED(String, source, 0);
5365 
5366  source->TryFlatten();
5367 
5368  bool ascii = true;
5369  int length = source->length();
5370 
5371  int unescaped_length = 0;
5372  for (int i = 0; i < length; unescaped_length++) {
5373  int step;
5374  if (Unescape(source, i, length, &step) > String::kMaxAsciiCharCode) {
5375  ascii = false;
5376  }
5377  i += step;
5378  }
5379 
5380  // No length change implies no change. Return original string if no change.
5381  if (unescaped_length == length)
5382  return source;
5383 
5384  Object* o;
5385  { MaybeObject* maybe_o =
5386  ascii ?
5387  isolate->heap()->AllocateRawAsciiString(unescaped_length) :
5388  isolate->heap()->AllocateRawTwoByteString(unescaped_length);
5389  if (!maybe_o->ToObject(&o)) return maybe_o;
5390  }
5391  String* destination = String::cast(o);
5392 
5393  int dest_position = 0;
5394  for (int i = 0; i < length; dest_position++) {
5395  int step;
5396  destination->Set(dest_position, Unescape(source, i, length, &step));
5397  i += step;
5398  }
5399  return destination;
5400 }
5401 
5402 
5403 static const unsigned int kQuoteTableLength = 128u;
5404 
5405 static const int kJsonQuotesCharactersPerEntry = 8;
5406 static const char* const JsonQuotes =
5407  "\\u0000 \\u0001 \\u0002 \\u0003 "
5408  "\\u0004 \\u0005 \\u0006 \\u0007 "
5409  "\\b \\t \\n \\u000b "
5410  "\\f \\r \\u000e \\u000f "
5411  "\\u0010 \\u0011 \\u0012 \\u0013 "
5412  "\\u0014 \\u0015 \\u0016 \\u0017 "
5413  "\\u0018 \\u0019 \\u001a \\u001b "
5414  "\\u001c \\u001d \\u001e \\u001f "
5415  " ! \\\" # "
5416  "$ % & ' "
5417  "( ) * + "
5418  ", - . / "
5419  "0 1 2 3 "
5420  "4 5 6 7 "
5421  "8 9 : ; "
5422  "< = > ? "
5423  "@ A B C "
5424  "D E F G "
5425  "H I J K "
5426  "L M N O "
5427  "P Q R S "
5428  "T U V W "
5429  "X Y Z [ "
5430  "\\\\ ] ^ _ "
5431  "` a b c "
5432  "d e f g "
5433  "h i j k "
5434  "l m n o "
5435  "p q r s "
5436  "t u v w "
5437  "x y z { "
5438  "| } ~ \177 ";
5439 
5440 
5441 // For a string that is less than 32k characters it should always be
5442 // possible to allocate it in new space.
5443 static const int kMaxGuaranteedNewSpaceString = 32 * 1024;
5444 
5445 
5446 // Doing JSON quoting cannot make the string more than this many times larger.
5447 static const int kJsonQuoteWorstCaseBlowup = 6;
5448 
5449 static const int kSpaceForQuotesAndComma = 3;
5450 static const int kSpaceForBrackets = 2;
5451 
5452 // Covers the entire ASCII range (all other characters are unchanged by JSON
5453 // quoting).
5454 static const byte JsonQuoteLengths[kQuoteTableLength] = {
5455  6, 6, 6, 6, 6, 6, 6, 6,
5456  2, 2, 2, 6, 2, 2, 6, 6,
5457  6, 6, 6, 6, 6, 6, 6, 6,
5458  6, 6, 6, 6, 6, 6, 6, 6,
5459  1, 1, 2, 1, 1, 1, 1, 1,
5460  1, 1, 1, 1, 1, 1, 1, 1,
5461  1, 1, 1, 1, 1, 1, 1, 1,
5462  1, 1, 1, 1, 1, 1, 1, 1,
5463  1, 1, 1, 1, 1, 1, 1, 1,
5464  1, 1, 1, 1, 1, 1, 1, 1,
5465  1, 1, 1, 1, 1, 1, 1, 1,
5466  1, 1, 1, 1, 2, 1, 1, 1,
5467  1, 1, 1, 1, 1, 1, 1, 1,
5468  1, 1, 1, 1, 1, 1, 1, 1,
5469  1, 1, 1, 1, 1, 1, 1, 1,
5470  1, 1, 1, 1, 1, 1, 1, 1,
5471 };
5472 
5473 
5474 template <typename StringType>
5475 MaybeObject* AllocateRawString(Isolate* isolate, int length);
5476 
5477 
5478 template <>
5479 MaybeObject* AllocateRawString<SeqTwoByteString>(Isolate* isolate, int length) {
5480  return isolate->heap()->AllocateRawTwoByteString(length);
5481 }
5482 
5483 
5484 template <>
5485 MaybeObject* AllocateRawString<SeqAsciiString>(Isolate* isolate, int length) {
5486  return isolate->heap()->AllocateRawAsciiString(length);
5487 }
5488 
5489 
5490 template <typename Char, typename StringType, bool comma>
5491 static MaybeObject* SlowQuoteJsonString(Isolate* isolate,
5492  Vector<const Char> characters) {
5493  int length = characters.length();
5494  const Char* read_cursor = characters.start();
5495  const Char* end = read_cursor + length;
5496  const int kSpaceForQuotes = 2 + (comma ? 1 :0);
5497  int quoted_length = kSpaceForQuotes;
5498  while (read_cursor < end) {
5499  Char c = *(read_cursor++);
5500  if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) {
5501  quoted_length++;
5502  } else {
5503  quoted_length += JsonQuoteLengths[static_cast<unsigned>(c)];
5504  }
5505  }
5506  MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
5507  quoted_length);
5508  Object* new_object;
5509  if (!new_alloc->ToObject(&new_object)) {
5510  return new_alloc;
5511  }
5512  StringType* new_string = StringType::cast(new_object);
5513 
5514  Char* write_cursor = reinterpret_cast<Char*>(
5515  new_string->address() + SeqString::kHeaderSize);
5516  if (comma) *(write_cursor++) = ',';
5517  *(write_cursor++) = '"';
5518 
5519  read_cursor = characters.start();
5520  while (read_cursor < end) {
5521  Char c = *(read_cursor++);
5522  if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) {
5523  *(write_cursor++) = c;
5524  } else {
5525  int len = JsonQuoteLengths[static_cast<unsigned>(c)];
5526  const char* replacement = JsonQuotes +
5527  static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry;
5528  for (int i = 0; i < len; i++) {
5529  *write_cursor++ = *replacement++;
5530  }
5531  }
5532  }
5533  *(write_cursor++) = '"';
5534  return new_string;
5535 }
5536 
5537 
5538 template <typename SinkChar, typename SourceChar>
5539 static inline SinkChar* WriteQuoteJsonString(
5540  Isolate* isolate,
5541  SinkChar* write_cursor,
5542  Vector<const SourceChar> characters) {
5543  // SinkChar is only char if SourceChar is guaranteed to be char.
5544  ASSERT(sizeof(SinkChar) >= sizeof(SourceChar));
5545  const SourceChar* read_cursor = characters.start();
5546  const SourceChar* end = read_cursor + characters.length();
5547  *(write_cursor++) = '"';
5548  while (read_cursor < end) {
5549  SourceChar c = *(read_cursor++);
5550  if (sizeof(SourceChar) > 1u &&
5551  static_cast<unsigned>(c) >= kQuoteTableLength) {
5552  *(write_cursor++) = static_cast<SinkChar>(c);
5553  } else {
5554  int len = JsonQuoteLengths[static_cast<unsigned>(c)];
5555  const char* replacement = JsonQuotes +
5556  static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry;
5557  write_cursor[0] = replacement[0];
5558  if (len > 1) {
5559  write_cursor[1] = replacement[1];
5560  if (len > 2) {
5561  ASSERT(len == 6);
5562  write_cursor[2] = replacement[2];
5563  write_cursor[3] = replacement[3];
5564  write_cursor[4] = replacement[4];
5565  write_cursor[5] = replacement[5];
5566  }
5567  }
5568  write_cursor += len;
5569  }
5570  }
5571  *(write_cursor++) = '"';
5572  return write_cursor;
5573 }
5574 
5575 
5576 template <typename Char, typename StringType, bool comma>
5577 static MaybeObject* QuoteJsonString(Isolate* isolate,
5578  Vector<const Char> characters) {
5579  int length = characters.length();
5580  isolate->counters()->quote_json_char_count()->Increment(length);
5581  int worst_case_length =
5582  length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotesAndComma;
5583  if (worst_case_length > kMaxGuaranteedNewSpaceString) {
5584  return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters);
5585  }
5586 
5587  MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
5588  worst_case_length);
5589  Object* new_object;
5590  if (!new_alloc->ToObject(&new_object)) {
5591  return new_alloc;
5592  }
5593  if (!isolate->heap()->new_space()->Contains(new_object)) {
5594  // Even if our string is small enough to fit in new space we still have to
5595  // handle it being allocated in old space as may happen in the third
5596  // attempt. See CALL_AND_RETRY in heap-inl.h and similar code in
5597  // CEntryStub::GenerateCore.
5598  return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters);
5599  }
5600  StringType* new_string = StringType::cast(new_object);
5601  ASSERT(isolate->heap()->new_space()->Contains(new_string));
5602 
5603  Char* write_cursor = reinterpret_cast<Char*>(
5604  new_string->address() + SeqString::kHeaderSize);
5605  if (comma) *(write_cursor++) = ',';
5606  write_cursor = WriteQuoteJsonString<Char, Char>(isolate,
5607  write_cursor,
5608  characters);
5609  int final_length = static_cast<int>(
5610  write_cursor - reinterpret_cast<Char*>(
5611  new_string->address() + SeqString::kHeaderSize));
5612  isolate->heap()->new_space()->
5613  template ShrinkStringAtAllocationBoundary<StringType>(
5614  new_string, final_length);
5615  return new_string;
5616 }
5617 
5618 
5619 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONString) {
5620  NoHandleAllocation ha;
5621  CONVERT_ARG_CHECKED(String, str, 0);
5622  if (!str->IsFlat()) {
5623  MaybeObject* try_flatten = str->TryFlatten();
5624  Object* flat;
5625  if (!try_flatten->ToObject(&flat)) {
5626  return try_flatten;
5627  }
5628  str = String::cast(flat);
5629  ASSERT(str->IsFlat());
5630  }
5631  String::FlatContent flat = str->GetFlatContent();
5632  ASSERT(flat.IsFlat());
5633  if (flat.IsTwoByte()) {
5634  return QuoteJsonString<uc16, SeqTwoByteString, false>(isolate,
5635  flat.ToUC16Vector());
5636  } else {
5637  return QuoteJsonString<char, SeqAsciiString, false>(isolate,
5638  flat.ToAsciiVector());
5639  }
5640 }
5641 
5642 
5643 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringComma) {
5644  NoHandleAllocation ha;
5645  CONVERT_ARG_CHECKED(String, str, 0);
5646  if (!str->IsFlat()) {
5647  MaybeObject* try_flatten = str->TryFlatten();
5648  Object* flat;
5649  if (!try_flatten->ToObject(&flat)) {
5650  return try_flatten;
5651  }
5652  str = String::cast(flat);
5653  ASSERT(str->IsFlat());
5654  }
5655  String::FlatContent flat = str->GetFlatContent();
5656  if (flat.IsTwoByte()) {
5657  return QuoteJsonString<uc16, SeqTwoByteString, true>(isolate,
5658  flat.ToUC16Vector());
5659  } else {
5660  return QuoteJsonString<char, SeqAsciiString, true>(isolate,
5661  flat.ToAsciiVector());
5662  }
5663 }
5664 
5665 
5666 template <typename Char, typename StringType>
5667 static MaybeObject* QuoteJsonStringArray(Isolate* isolate,
5668  FixedArray* array,
5669  int worst_case_length) {
5670  int length = array->length();
5671 
5672  MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
5673  worst_case_length);
5674  Object* new_object;
5675  if (!new_alloc->ToObject(&new_object)) {
5676  return new_alloc;
5677  }
5678  if (!isolate->heap()->new_space()->Contains(new_object)) {
5679  // Even if our string is small enough to fit in new space we still have to
5680  // handle it being allocated in old space as may happen in the third
5681  // attempt. See CALL_AND_RETRY in heap-inl.h and similar code in
5682  // CEntryStub::GenerateCore.
5683  return isolate->heap()->undefined_value();
5684  }
5685  AssertNoAllocation no_gc;
5686  StringType* new_string = StringType::cast(new_object);
5687  ASSERT(isolate->heap()->new_space()->Contains(new_string));
5688 
5689  Char* write_cursor = reinterpret_cast<Char*>(
5690  new_string->address() + SeqString::kHeaderSize);
5691  *(write_cursor++) = '[';
5692  for (int i = 0; i < length; i++) {
5693  if (i != 0) *(write_cursor++) = ',';
5694  String* str = String::cast(array->get(i));
5695  String::FlatContent content = str->GetFlatContent();
5696  ASSERT(content.IsFlat());
5697  if (content.IsTwoByte()) {
5698  write_cursor = WriteQuoteJsonString<Char, uc16>(isolate,
5699  write_cursor,
5700  content.ToUC16Vector());
5701  } else {
5702  write_cursor = WriteQuoteJsonString<Char, char>(isolate,
5703  write_cursor,
5704  content.ToAsciiVector());
5705  }
5706  }
5707  *(write_cursor++) = ']';
5708 
5709  int final_length = static_cast<int>(
5710  write_cursor - reinterpret_cast<Char*>(
5711  new_string->address() + SeqString::kHeaderSize));
5712  isolate->heap()->new_space()->
5713  template ShrinkStringAtAllocationBoundary<StringType>(
5714  new_string, final_length);
5715  return new_string;
5716 }
5717 
5718 
5719 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringArray) {
5720  NoHandleAllocation ha;
5721  ASSERT(args.length() == 1);
5722  CONVERT_ARG_CHECKED(JSArray, array, 0);
5723 
5724  if (!array->HasFastObjectElements()) {
5725  return isolate->heap()->undefined_value();
5726  }
5727  FixedArray* elements = FixedArray::cast(array->elements());
5728  int n = elements->length();
5729  bool ascii = true;
5730  int total_length = 0;
5731 
5732  for (int i = 0; i < n; i++) {
5733  Object* elt = elements->get(i);
5734  if (!elt->IsString()) return isolate->heap()->undefined_value();
5735  String* element = String::cast(elt);
5736  if (!element->IsFlat()) return isolate->heap()->undefined_value();
5737  total_length += element->length();
5738  if (ascii && element->IsTwoByteRepresentation()) {
5739  ascii = false;
5740  }
5741  }
5742 
5743  int worst_case_length =
5744  kSpaceForBrackets + n * kSpaceForQuotesAndComma
5745  + total_length * kJsonQuoteWorstCaseBlowup;
5746 
5747  if (worst_case_length > kMaxGuaranteedNewSpaceString) {
5748  return isolate->heap()->undefined_value();
5749  }
5750 
5751  if (ascii) {
5752  return QuoteJsonStringArray<char, SeqAsciiString>(isolate,
5753  elements,
5754  worst_case_length);
5755  } else {
5756  return QuoteJsonStringArray<uc16, SeqTwoByteString>(isolate,
5757  elements,
5758  worst_case_length);
5759  }
5760 }
5761 
5762 
5763 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) {
5764  NoHandleAllocation ha;
5765 
5766  CONVERT_ARG_CHECKED(String, s, 0);
5767  CONVERT_SMI_ARG_CHECKED(radix, 1);
5768 
5769  s->TryFlatten();
5770 
5771  RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
5772  double value = StringToInt(isolate->unicode_cache(), s, radix);
5773  return isolate->heap()->NumberFromDouble(value);
5774 }
5775 
5776 
5777 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) {
5778  NoHandleAllocation ha;
5779  CONVERT_ARG_CHECKED(String, str, 0);
5780 
5781  // ECMA-262 section 15.1.2.3, empty string is NaN
5782  double value = StringToDouble(isolate->unicode_cache(),
5784 
5785  // Create a number object from the value.
5786  return isolate->heap()->NumberFromDouble(value);
5787 }
5788 
5789 
5790 template <class Converter>
5791 MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
5792  Isolate* isolate,
5793  String* s,
5794  int length,
5795  int input_string_length,
5797  // We try this twice, once with the assumption that the result is no longer
5798  // than the input and, if that assumption breaks, again with the exact
5799  // length. This may not be pretty, but it is nicer than what was here before
5800  // and I hereby claim my vaffel-is.
5801  //
5802  // Allocate the resulting string.
5803  //
5804  // NOTE: This assumes that the upper/lower case of an ASCII
5805  // character is also ASCII. This is currently the case, but it
5806  // might break in the future if we implement more context and locale
5807  // dependent upper/lower conversions.
5808  Object* o;
5809  { MaybeObject* maybe_o = s->IsAsciiRepresentation()
5810  ? isolate->heap()->AllocateRawAsciiString(length)
5811  : isolate->heap()->AllocateRawTwoByteString(length);
5812  if (!maybe_o->ToObject(&o)) return maybe_o;
5813  }
5814  String* result = String::cast(o);
5815  bool has_changed_character = false;
5816 
5817  // Convert all characters to upper case, assuming that they will fit
5818  // in the buffer
5819  Access<StringInputBuffer> buffer(
5820  isolate->runtime_state()->string_input_buffer());
5821  buffer->Reset(s);
5822  unibrow::uchar chars[Converter::kMaxWidth];
5823  // We can assume that the string is not empty
5824  uc32 current = buffer->GetNext();
5825  for (int i = 0; i < length;) {
5826  bool has_next = buffer->has_more();
5827  uc32 next = has_next ? buffer->GetNext() : 0;
5828  int char_length = mapping->get(current, next, chars);
5829  if (char_length == 0) {
5830  // The case conversion of this character is the character itself.
5831  result->Set(i, current);
5832  i++;
5833  } else if (char_length == 1) {
5834  // Common case: converting the letter resulted in one character.
5835  ASSERT(static_cast<uc32>(chars[0]) != current);
5836  result->Set(i, chars[0]);
5837  has_changed_character = true;
5838  i++;
5839  } else if (length == input_string_length) {
5840  // We've assumed that the result would be as long as the
5841  // input but here is a character that converts to several
5842  // characters. No matter, we calculate the exact length
5843  // of the result and try the whole thing again.
5844  //
5845  // Note that this leaves room for optimization. We could just
5846  // memcpy what we already have to the result string. Also,
5847  // the result string is the last object allocated we could
5848  // "realloc" it and probably, in the vast majority of cases,
5849  // extend the existing string to be able to hold the full
5850  // result.
5851  int next_length = 0;
5852  if (has_next) {
5853  next_length = mapping->get(next, 0, chars);
5854  if (next_length == 0) next_length = 1;
5855  }
5856  int current_length = i + char_length + next_length;
5857  while (buffer->has_more()) {
5858  current = buffer->GetNext();
5859  // NOTE: we use 0 as the next character here because, while
5860  // the next character may affect what a character converts to,
5861  // it does not in any case affect the length of what it convert
5862  // to.
5863  int char_length = mapping->get(current, 0, chars);
5864  if (char_length == 0) char_length = 1;
5865  current_length += char_length;
5866  if (current_length > Smi::kMaxValue) {
5867  isolate->context()->mark_out_of_memory();
5869  }
5870  }
5871  // Try again with the real length.
5872  return Smi::FromInt(current_length);
5873  } else {
5874  for (int j = 0; j < char_length; j++) {
5875  result->Set(i, chars[j]);
5876  i++;
5877  }
5878  has_changed_character = true;
5879  }
5880  current = next;
5881  }
5882  if (has_changed_character) {
5883  return result;
5884  } else {
5885  // If we didn't actually change anything in doing the conversion
5886  // we simple return the result and let the converted string
5887  // become garbage; there is no reason to keep two identical strings
5888  // alive.
5889  return s;
5890  }
5891 }
5892 
5893 
5894 namespace {
5895 
5896 static const uintptr_t kOneInEveryByte = kUintptrAllBitsSet / 0xFF;
5897 
5898 
5899 // Given a word and two range boundaries returns a word with high bit
5900 // set in every byte iff the corresponding input byte was strictly in
5901 // the range (m, n). All the other bits in the result are cleared.
5902 // This function is only useful when it can be inlined and the
5903 // boundaries are statically known.
5904 // Requires: all bytes in the input word and the boundaries must be
5905 // ASCII (less than 0x7F).
5906 static inline uintptr_t AsciiRangeMask(uintptr_t w, char m, char n) {
5907  // Every byte in an ASCII string is less than or equal to 0x7F.
5908  ASSERT((w & (kOneInEveryByte * 0x7F)) == w);
5909  // Use strict inequalities since in edge cases the function could be
5910  // further simplified.
5911  ASSERT(0 < m && m < n && n < 0x7F);
5912  // Has high bit set in every w byte less than n.
5913  uintptr_t tmp1 = kOneInEveryByte * (0x7F + n) - w;
5914  // Has high bit set in every w byte greater than m.
5915  uintptr_t tmp2 = w + kOneInEveryByte * (0x7F - m);
5916  return (tmp1 & tmp2 & (kOneInEveryByte * 0x80));
5917 }
5918 
5919 
5920 enum AsciiCaseConversion {
5921  ASCII_TO_LOWER,
5922  ASCII_TO_UPPER
5923 };
5924 
5925 
5926 template <AsciiCaseConversion dir>
5927 struct FastAsciiConverter {
5928  static bool Convert(char* dst, char* src, int length) {
5929 #ifdef DEBUG
5930  char* saved_dst = dst;
5931  char* saved_src = src;
5932 #endif
5933  // We rely on the distance between upper and lower case letters
5934  // being a known power of 2.
5935  ASSERT('a' - 'A' == (1 << 5));
5936  // Boundaries for the range of input characters than require conversion.
5937  const char lo = (dir == ASCII_TO_LOWER) ? 'A' - 1 : 'a' - 1;
5938  const char hi = (dir == ASCII_TO_LOWER) ? 'Z' + 1 : 'z' + 1;
5939  bool changed = false;
5940  char* const limit = src + length;
5941 #ifdef V8_HOST_CAN_READ_UNALIGNED
5942  // Process the prefix of the input that requires no conversion one
5943  // (machine) word at a time.
5944  while (src <= limit - sizeof(uintptr_t)) {
5945  uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
5946  if (AsciiRangeMask(w, lo, hi) != 0) {
5947  changed = true;
5948  break;
5949  }
5950  *reinterpret_cast<uintptr_t*>(dst) = w;
5951  src += sizeof(uintptr_t);
5952  dst += sizeof(uintptr_t);
5953  }
5954  // Process the remainder of the input performing conversion when
5955  // required one word at a time.
5956  while (src <= limit - sizeof(uintptr_t)) {
5957  uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
5958  uintptr_t m = AsciiRangeMask(w, lo, hi);
5959  // The mask has high (7th) bit set in every byte that needs
5960  // conversion and we know that the distance between cases is
5961  // 1 << 5.
5962  *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2);
5963  src += sizeof(uintptr_t);
5964  dst += sizeof(uintptr_t);
5965  }
5966 #endif
5967  // Process the last few bytes of the input (or the whole input if
5968  // unaligned access is not supported).
5969  while (src < limit) {
5970  char c = *src;
5971  if (lo < c && c < hi) {
5972  c ^= (1 << 5);
5973  changed = true;
5974  }
5975  *dst = c;
5976  ++src;
5977  ++dst;
5978  }
5979 #ifdef DEBUG
5980  CheckConvert(saved_dst, saved_src, length, changed);
5981 #endif
5982  return changed;
5983  }
5984 
5985 #ifdef DEBUG
5986  static void CheckConvert(char* dst, char* src, int length, bool changed) {
5987  bool expected_changed = false;
5988  for (int i = 0; i < length; i++) {
5989  if (dst[i] == src[i]) continue;
5990  expected_changed = true;
5991  if (dir == ASCII_TO_LOWER) {
5992  ASSERT('A' <= src[i] && src[i] <= 'Z');
5993  ASSERT(dst[i] == src[i] + ('a' - 'A'));
5994  } else {
5995  ASSERT(dir == ASCII_TO_UPPER);
5996  ASSERT('a' <= src[i] && src[i] <= 'z');
5997  ASSERT(dst[i] == src[i] - ('a' - 'A'));
5998  }
5999  }
6000  ASSERT(expected_changed == changed);
6001  }
6002 #endif
6003 };
6004 
6005 
6006 struct ToLowerTraits {
6007  typedef unibrow::ToLowercase UnibrowConverter;
6008 
6009  typedef FastAsciiConverter<ASCII_TO_LOWER> AsciiConverter;
6010 };
6011 
6012 
6013 struct ToUpperTraits {
6014  typedef unibrow::ToUppercase UnibrowConverter;
6015 
6016  typedef FastAsciiConverter<ASCII_TO_UPPER> AsciiConverter;
6017 };
6018 
6019 } // namespace
6020 
6021 
6022 template <typename ConvertTraits>
6023 MUST_USE_RESULT static MaybeObject* ConvertCase(
6024  Arguments args,
6025  Isolate* isolate,
6027  NoHandleAllocation ha;
6028  CONVERT_ARG_CHECKED(String, s, 0);
6029  s = s->TryFlattenGetString();
6030 
6031  const int length = s->length();
6032  // Assume that the string is not empty; we need this assumption later
6033  if (length == 0) return s;
6034 
6035  // Simpler handling of ASCII strings.
6036  //
6037  // NOTE: This assumes that the upper/lower case of an ASCII
6038  // character is also ASCII. This is currently the case, but it
6039  // might break in the future if we implement more context and locale
6040  // dependent upper/lower conversions.
6041  if (s->IsSeqAsciiString()) {
6042  Object* o;
6043  { MaybeObject* maybe_o = isolate->heap()->AllocateRawAsciiString(length);
6044  if (!maybe_o->ToObject(&o)) return maybe_o;
6045  }
6046  SeqAsciiString* result = SeqAsciiString::cast(o);
6047  bool has_changed_character = ConvertTraits::AsciiConverter::Convert(
6048  result->GetChars(), SeqAsciiString::cast(s)->GetChars(), length);
6049  return has_changed_character ? result : s;
6050  }
6051 
6052  Object* answer;
6053  { MaybeObject* maybe_answer =
6054  ConvertCaseHelper(isolate, s, length, length, mapping);
6055  if (!maybe_answer->ToObject(&answer)) return maybe_answer;
6056  }
6057  if (answer->IsSmi()) {
6058  // Retry with correct length.
6059  { MaybeObject* maybe_answer =
6060  ConvertCaseHelper(isolate,
6061  s, Smi::cast(answer)->value(), length, mapping);
6062  if (!maybe_answer->ToObject(&answer)) return maybe_answer;
6063  }
6064  }
6065  return answer;
6066 }
6067 
6068 
6069 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) {
6070  return ConvertCase<ToLowerTraits>(
6071  args, isolate, isolate->runtime_state()->to_lower_mapping());
6072 }
6073 
6074 
6075 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToUpperCase) {
6076  return ConvertCase<ToUpperTraits>(
6077  args, isolate, isolate->runtime_state()->to_upper_mapping());
6078 }
6079 
6080 
6081 static inline bool IsTrimWhiteSpace(unibrow::uchar c) {
6082  return unibrow::WhiteSpace::Is(c) || c == 0x200b || c == 0xfeff;
6083 }
6084 
6085 
6086 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringTrim) {
6087  NoHandleAllocation ha;
6088  ASSERT(args.length() == 3);
6089 
6090  CONVERT_ARG_CHECKED(String, s, 0);
6091  CONVERT_BOOLEAN_ARG_CHECKED(trimLeft, 1);
6092  CONVERT_BOOLEAN_ARG_CHECKED(trimRight, 2);
6093 
6094  s->TryFlatten();
6095  int length = s->length();
6096 
6097  int left = 0;
6098  if (trimLeft) {
6099  while (left < length && IsTrimWhiteSpace(s->Get(left))) {
6100  left++;
6101  }
6102  }
6103 
6104  int right = length;
6105  if (trimRight) {
6106  while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) {
6107  right--;
6108  }
6109  }
6110  return s->SubString(left, right);
6111 }
6112 
6113 
6114 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
6115  ASSERT(args.length() == 3);
6116  HandleScope handle_scope(isolate);
6117  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
6118  CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
6119  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]);
6120 
6121  int subject_length = subject->length();
6122  int pattern_length = pattern->length();
6123  RUNTIME_ASSERT(pattern_length > 0);
6124 
6125  if (limit == 0xffffffffu) {
6127  isolate->heap(),
6128  *subject,
6129  *pattern,
6131  if (*cached_answer != Smi::FromInt(0)) {
6132  // The cache FixedArray is a COW-array and can therefore be reused.
6133  Handle<JSArray> result =
6134  isolate->factory()->NewJSArrayWithElements(
6135  Handle<FixedArray>::cast(cached_answer));
6136  return *result;
6137  }
6138  }
6139 
6140  // The limit can be very large (0xffffffffu), but since the pattern
6141  // isn't empty, we can never create more parts than ~half the length
6142  // of the subject.
6143 
6144  if (!subject->IsFlat()) FlattenString(subject);
6145 
6146  static const int kMaxInitialListCapacity = 16;
6147 
6148  Zone* zone = isolate->runtime_zone();
6149  ZoneScope scope(zone, DELETE_ON_EXIT);
6150 
6151  // Find (up to limit) indices of separator and end-of-string in subject
6152  int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit);
6153  ZoneList<int> indices(initial_capacity, zone);
6154  if (!pattern->IsFlat()) FlattenString(pattern);
6155 
6156  FindStringIndicesDispatch(isolate, *subject, *pattern, &indices, limit, zone);
6157 
6158  if (static_cast<uint32_t>(indices.length()) < limit) {
6159  indices.Add(subject_length, zone);
6160  }
6161 
6162  // The list indices now contains the end of each part to create.
6163 
6164  // Create JSArray of substrings separated by separator.
6165  int part_count = indices.length();
6166 
6167  Handle<JSArray> result = isolate->factory()->NewJSArray(part_count);
6168  MaybeObject* maybe_result = result->EnsureCanContainHeapObjectElements();
6169  if (maybe_result->IsFailure()) return maybe_result;
6170  result->set_length(Smi::FromInt(part_count));
6171 
6172  ASSERT(result->HasFastObjectElements());
6173 
6174  if (part_count == 1 && indices.at(0) == subject_length) {
6175  FixedArray::cast(result->elements())->set(0, *subject);
6176  return *result;
6177  }
6178 
6179  Handle<FixedArray> elements(FixedArray::cast(result->elements()));
6180  int part_start = 0;
6181  for (int i = 0; i < part_count; i++) {
6182  HandleScope local_loop_handle;
6183  int part_end = indices.at(i);
6184  Handle<String> substring =
6185  isolate->factory()->NewProperSubString(subject, part_start, part_end);
6186  elements->set(i, *substring);
6187  part_start = part_end + pattern_length;
6188  }
6189 
6190  if (limit == 0xffffffffu) {
6191  if (result->HasFastObjectElements()) {
6192  RegExpResultsCache::Enter(isolate->heap(),
6193  *subject,
6194  *pattern,
6195  *elements,
6197  }
6198  }
6199 
6200  return *result;
6201 }
6202 
6203 
6204 // Copies ASCII characters to the given fixed array looking up
6205 // one-char strings in the cache. Gives up on the first char that is
6206 // not in the cache and fills the remainder with smi zeros. Returns
6207 // the length of the successfully copied prefix.
6208 static int CopyCachedAsciiCharsToArray(Heap* heap,
6209  const char* chars,
6210  FixedArray* elements,
6211  int length) {
6212  AssertNoAllocation no_gc;
6213  FixedArray* ascii_cache = heap->single_character_string_cache();
6214  Object* undefined = heap->undefined_value();
6215  int i;
6216  WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
6217  for (i = 0; i < length; ++i) {
6218  Object* value = ascii_cache->get(chars[i]);
6219  if (value == undefined) break;
6220  elements->set(i, value, mode);
6221  }
6222  if (i < length) {
6223  ASSERT(Smi::FromInt(0) == 0);
6224  memset(elements->data_start() + i, 0, kPointerSize * (length - i));
6225  }
6226 #ifdef DEBUG
6227  for (int j = 0; j < length; ++j) {
6228  Object* element = elements->get(j);
6229  ASSERT(element == Smi::FromInt(0) ||
6230  (element->IsString() && String::cast(element)->LooksValid()));
6231  }
6232 #endif
6233  return i;
6234 }
6235 
6236 
6237 // Converts a String to JSArray.
6238 // For example, "foo" => ["f", "o", "o"].
6239 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToArray) {
6240  HandleScope scope(isolate);
6241  ASSERT(args.length() == 2);
6243  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
6244 
6245  s = FlattenGetString(s);
6246  const int length = static_cast<int>(Min<uint32_t>(s->length(), limit));
6247 
6248  Handle<FixedArray> elements;
6249  int position = 0;
6250  if (s->IsFlat() && s->IsAsciiRepresentation()) {
6251  // Try using cached chars where possible.
6252  Object* obj;
6253  { MaybeObject* maybe_obj =
6254  isolate->heap()->AllocateUninitializedFixedArray(length);
6255  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
6256  }
6257  elements = Handle<FixedArray>(FixedArray::cast(obj), isolate);
6258  String::FlatContent content = s->GetFlatContent();
6259  if (content.IsAscii()) {
6260  Vector<const char> chars = content.ToAsciiVector();
6261  // Note, this will initialize all elements (not only the prefix)
6262  // to prevent GC from seeing partially initialized array.
6263  position = CopyCachedAsciiCharsToArray(isolate->heap(),
6264  chars.start(),
6265  *elements,
6266  length);
6267  } else {
6268  MemsetPointer(elements->data_start(),
6269  isolate->heap()->undefined_value(),
6270  length);
6271  }
6272  } else {
6273  elements = isolate->factory()->NewFixedArray(length);
6274  }
6275  for (int i = position; i < length; ++i) {
6277  elements->set(i, *str);
6278  }
6279 
6280 #ifdef DEBUG
6281  for (int i = 0; i < length; ++i) {
6282  ASSERT(String::cast(elements->get(i))->length() == 1);
6283  }
6284 #endif
6285 
6286  return *isolate->factory()->NewJSArrayWithElements(elements);
6287 }
6288 
6289 
6290 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStringWrapper) {
6291  NoHandleAllocation ha;
6292  ASSERT(args.length() == 1);
6293  CONVERT_ARG_CHECKED(String, value, 0);
6294  return value->ToObject();
6295 }
6296 
6297 
6300  int char_length = runtime_state->to_upper_mapping()->get(ch, 0, chars);
6301  return char_length == 0;
6302 }
6303 
6304 
6305 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToString) {
6306  NoHandleAllocation ha;
6307  ASSERT(args.length() == 1);
6308 
6309  Object* number = args[0];
6310  RUNTIME_ASSERT(number->IsNumber());
6311 
6312  return isolate->heap()->NumberToString(number);
6313 }
6314 
6315 
6316 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToStringSkipCache) {
6317  NoHandleAllocation ha;
6318  ASSERT(args.length() == 1);
6319 
6320  Object* number = args[0];
6321  RUNTIME_ASSERT(number->IsNumber());
6322 
6323  return isolate->heap()->NumberToString(number, false);
6324 }
6325 
6326 
6327 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToInteger) {
6328  NoHandleAllocation ha;
6329  ASSERT(args.length() == 1);
6330 
6331  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6332 
6333  // We do not include 0 so that we don't have to treat +0 / -0 cases.
6334  if (number > 0 && number <= Smi::kMaxValue) {
6335  return Smi::FromInt(static_cast<int>(number));
6336  }
6337  return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
6338 }
6339 
6340 
6341 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToIntegerMapMinusZero) {
6342  NoHandleAllocation ha;
6343  ASSERT(args.length() == 1);
6344 
6345  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6346 
6347  // We do not include 0 so that we don't have to treat +0 / -0 cases.
6348  if (number > 0 && number <= Smi::kMaxValue) {
6349  return Smi::FromInt(static_cast<int>(number));
6350  }
6351 
6352  double double_value = DoubleToInteger(number);
6353  // Map both -0 and +0 to +0.
6354  if (double_value == 0) double_value = 0;
6355 
6356  return isolate->heap()->NumberFromDouble(double_value);
6357 }
6358 
6359 
6360 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSUint32) {
6361  NoHandleAllocation ha;
6362  ASSERT(args.length() == 1);
6363 
6364  CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]);
6365  return isolate->heap()->NumberFromUint32(number);
6366 }
6367 
6368 
6369 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSInt32) {
6370  NoHandleAllocation ha;
6371  ASSERT(args.length() == 1);
6372 
6373  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6374 
6375  // We do not include 0 so that we don't have to treat +0 / -0 cases.
6376  if (number > 0 && number <= Smi::kMaxValue) {
6377  return Smi::FromInt(static_cast<int>(number));
6378  }
6379  return isolate->heap()->NumberFromInt32(DoubleToInt32(number));
6380 }
6381 
6382 
6383 // Converts a Number to a Smi, if possible. Returns NaN if the number is not
6384 // a small integer.
6385 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToSmi) {
6386  NoHandleAllocation ha;
6387  ASSERT(args.length() == 1);
6388 
6389  Object* obj = args[0];
6390  if (obj->IsSmi()) {
6391  return obj;
6392  }
6393  if (obj->IsHeapNumber()) {
6394  double value = HeapNumber::cast(obj)->value();
6395  int int_value = FastD2I(value);
6396  if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
6397  return Smi::FromInt(int_value);
6398  }
6399  }
6400  return isolate->heap()->nan_value();
6401 }
6402 
6403 
6404 RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateHeapNumber) {
6405  NoHandleAllocation ha;
6406  ASSERT(args.length() == 0);
6407  return isolate->heap()->AllocateHeapNumber(0);
6408 }
6409 
6410 
6411 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAdd) {
6412  NoHandleAllocation ha;
6413  ASSERT(args.length() == 2);
6414 
6417  return isolate->heap()->NumberFromDouble(x + y);
6418 }
6419 
6420 
6421 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSub) {
6422  NoHandleAllocation ha;
6423  ASSERT(args.length() == 2);
6424 
6427  return isolate->heap()->NumberFromDouble(x - y);
6428 }
6429 
6430 
6431 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMul) {
6432  NoHandleAllocation ha;
6433  ASSERT(args.length() == 2);
6434 
6437  return isolate->heap()->NumberFromDouble(x * y);
6438 }
6439 
6440 
6441 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberUnaryMinus) {
6442  NoHandleAllocation ha;
6443  ASSERT(args.length() == 1);
6444 
6446  return isolate->heap()->NumberFromDouble(-x);
6447 }
6448 
6449 
6450 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAlloc) {
6451  NoHandleAllocation ha;
6452  ASSERT(args.length() == 0);
6453 
6454  return isolate->heap()->NumberFromDouble(9876543210.0);
6455 }
6456 
6457 
6458 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberDiv) {
6459  NoHandleAllocation ha;
6460  ASSERT(args.length() == 2);
6461 
6464  return isolate->heap()->NumberFromDouble(x / y);
6465 }
6466 
6467 
6468 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMod) {
6469  NoHandleAllocation ha;
6470  ASSERT(args.length() == 2);
6471 
6474 
6475  x = modulo(x, y);
6476  // NumberFromDouble may return a Smi instead of a Number object
6477  return isolate->heap()->NumberFromDouble(x);
6478 }
6479 
6480 
6481 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringAdd) {
6482  NoHandleAllocation ha;
6483  ASSERT(args.length() == 2);
6484  CONVERT_ARG_CHECKED(String, str1, 0);
6485  CONVERT_ARG_CHECKED(String, str2, 1);
6486  isolate->counters()->string_add_runtime()->Increment();
6487  return isolate->heap()->AllocateConsString(str1, str2);
6488 }
6489 
6490 
6491 template <typename sinkchar>
6492 static inline void StringBuilderConcatHelper(String* special,
6493  sinkchar* sink,
6494  FixedArray* fixed_array,
6495  int array_length) {
6496  int position = 0;
6497  for (int i = 0; i < array_length; i++) {
6498  Object* element = fixed_array->get(i);
6499  if (element->IsSmi()) {
6500  // Smi encoding of position and length.
6501  int encoded_slice = Smi::cast(element)->value();
6502  int pos;
6503  int len;
6504  if (encoded_slice > 0) {
6505  // Position and length encoded in one smi.
6506  pos = StringBuilderSubstringPosition::decode(encoded_slice);
6507  len = StringBuilderSubstringLength::decode(encoded_slice);
6508  } else {
6509  // Position and length encoded in two smis.
6510  Object* obj = fixed_array->get(++i);
6511  ASSERT(obj->IsSmi());
6512  pos = Smi::cast(obj)->value();
6513  len = -encoded_slice;
6514  }
6515  String::WriteToFlat(special,
6516  sink + position,
6517  pos,
6518  pos + len);
6519  position += len;
6520  } else {
6521  String* string = String::cast(element);
6522  int element_length = string->length();
6523  String::WriteToFlat(string, sink + position, 0, element_length);
6524  position += element_length;
6525  }
6526  }
6527 }
6528 
6529 
6530 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
6531  NoHandleAllocation ha;
6532  ASSERT(args.length() == 3);
6533  CONVERT_ARG_CHECKED(JSArray, array, 0);
6534  if (!args[1]->IsSmi()) {
6535  isolate->context()->mark_out_of_memory();
6537  }
6538  int array_length = args.smi_at(1);
6539  CONVERT_ARG_CHECKED(String, special, 2);
6540 
6541  // This assumption is used by the slice encoding in one or two smis.
6543 
6544  MaybeObject* maybe_result = array->EnsureCanContainHeapObjectElements();
6545  if (maybe_result->IsFailure()) return maybe_result;
6546 
6547  int special_length = special->length();
6548  if (!array->HasFastObjectElements()) {
6549  return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6550  }
6551  FixedArray* fixed_array = FixedArray::cast(array->elements());
6552  if (fixed_array->length() < array_length) {
6553  array_length = fixed_array->length();
6554  }
6555 
6556  if (array_length == 0) {
6557  return isolate->heap()->empty_string();
6558  } else if (array_length == 1) {
6559  Object* first = fixed_array->get(0);
6560  if (first->IsString()) return first;
6561  }
6562 
6563  bool ascii = special->HasOnlyAsciiChars();
6564  int position = 0;
6565  for (int i = 0; i < array_length; i++) {
6566  int increment = 0;
6567  Object* elt = fixed_array->get(i);
6568  if (elt->IsSmi()) {
6569  // Smi encoding of position and length.
6570  int smi_value = Smi::cast(elt)->value();
6571  int pos;
6572  int len;
6573  if (smi_value > 0) {
6574  // Position and length encoded in one smi.
6575  pos = StringBuilderSubstringPosition::decode(smi_value);
6576  len = StringBuilderSubstringLength::decode(smi_value);
6577  } else {
6578  // Position and length encoded in two smis.
6579  len = -smi_value;
6580  // Get the position and check that it is a positive smi.
6581  i++;
6582  if (i >= array_length) {
6583  return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6584  }
6585  Object* next_smi = fixed_array->get(i);
6586  if (!next_smi->IsSmi()) {
6587  return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6588  }
6589  pos = Smi::cast(next_smi)->value();
6590  if (pos < 0) {
6591  return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6592  }
6593  }
6594  ASSERT(pos >= 0);
6595  ASSERT(len >= 0);
6596  if (pos > special_length || len > special_length - pos) {
6597  return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6598  }
6599  increment = len;
6600  } else if (elt->IsString()) {
6601  String* element = String::cast(elt);
6602  int element_length = element->length();
6603  increment = element_length;
6604  if (ascii && !element->HasOnlyAsciiChars()) {
6605  ascii = false;
6606  }
6607  } else {
6608  ASSERT(!elt->IsTheHole());
6609  return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6610  }
6611  if (increment > String::kMaxLength - position) {
6612  isolate->context()->mark_out_of_memory();
6614  }
6615  position += increment;
6616  }
6617 
6618  int length = position;
6619  Object* object;
6620 
6621  if (ascii) {
6622  { MaybeObject* maybe_object =
6623  isolate->heap()->AllocateRawAsciiString(length);
6624  if (!maybe_object->ToObject(&object)) return maybe_object;
6625  }
6626  SeqAsciiString* answer = SeqAsciiString::cast(object);
6627  StringBuilderConcatHelper(special,
6628  answer->GetChars(),
6629  fixed_array,
6630  array_length);
6631  return answer;
6632  } else {
6633  { MaybeObject* maybe_object =
6634  isolate->heap()->AllocateRawTwoByteString(length);
6635  if (!maybe_object->ToObject(&object)) return maybe_object;
6636  }
6637  SeqTwoByteString* answer = SeqTwoByteString::cast(object);
6638  StringBuilderConcatHelper(special,
6639  answer->GetChars(),
6640  fixed_array,
6641  array_length);
6642  return answer;
6643  }
6644 }
6645 
6646 
6647 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
6648  NoHandleAllocation ha;
6649  ASSERT(args.length() == 3);
6650  CONVERT_ARG_CHECKED(JSArray, array, 0);
6651  if (!args[1]->IsSmi()) {
6652  isolate->context()->mark_out_of_memory();
6654  }
6655  int array_length = args.smi_at(1);
6656  CONVERT_ARG_CHECKED(String, separator, 2);
6657 
6658  if (!array->HasFastObjectElements()) {
6659  return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6660  }
6661  FixedArray* fixed_array = FixedArray::cast(array->elements());
6662  if (fixed_array->length() < array_length) {
6663  array_length = fixed_array->length();
6664  }
6665 
6666  if (array_length == 0) {
6667  return isolate->heap()->empty_string();
6668  } else if (array_length == 1) {
6669  Object* first = fixed_array->get(0);
6670  if (first->IsString()) return first;
6671  }
6672 
6673  int separator_length = separator->length();
6674  int max_nof_separators =
6675  (String::kMaxLength + separator_length - 1) / separator_length;
6676  if (max_nof_separators < (array_length - 1)) {
6677  isolate->context()->mark_out_of_memory();
6679  }
6680  int length = (array_length - 1) * separator_length;
6681  for (int i = 0; i < array_length; i++) {
6682  Object* element_obj = fixed_array->get(i);
6683  if (!element_obj->IsString()) {
6684  // TODO(1161): handle this case.
6685  return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6686  }
6687  String* element = String::cast(element_obj);
6688  int increment = element->length();
6689  if (increment > String::kMaxLength - length) {
6690  isolate->context()->mark_out_of_memory();
6692  }
6693  length += increment;
6694  }
6695 
6696  Object* object;
6697  { MaybeObject* maybe_object =
6698  isolate->heap()->AllocateRawTwoByteString(length);
6699  if (!maybe_object->ToObject(&object)) return maybe_object;
6700  }
6701  SeqTwoByteString* answer = SeqTwoByteString::cast(object);
6702 
6703  uc16* sink = answer->GetChars();
6704 #ifdef DEBUG
6705  uc16* end = sink + length;
6706 #endif
6707 
6708  String* first = String::cast(fixed_array->get(0));
6709  int first_length = first->length();
6710  String::WriteToFlat(first, sink, 0, first_length);
6711  sink += first_length;
6712 
6713  for (int i = 1; i < array_length; i++) {
6714  ASSERT(sink + separator_length <= end);
6715  String::WriteToFlat(separator, sink, 0, separator_length);
6716  sink += separator_length;
6717 
6718  String* element = String::cast(fixed_array->get(i));
6719  int element_length = element->length();
6720  ASSERT(sink + element_length <= end);
6721  String::WriteToFlat(element, sink, 0, element_length);
6722  sink += element_length;
6723  }
6724  ASSERT(sink == end);
6725 
6726  ASSERT(!answer->HasOnlyAsciiChars()); // Use %_FastAsciiArrayJoin instead.
6727  return answer;
6728 }
6729 
6730 template <typename Char>
6731 static void JoinSparseArrayWithSeparator(FixedArray* elements,
6732  int elements_length,
6733  uint32_t array_length,
6734  String* separator,
6735  Vector<Char> buffer) {
6736  int previous_separator_position = 0;
6737  int separator_length = separator->length();
6738  int cursor = 0;
6739  for (int i = 0; i < elements_length; i += 2) {
6740  int position = NumberToInt32(elements->get(i));
6741  String* string = String::cast(elements->get(i + 1));
6742  int string_length = string->length();
6743  if (string->length() > 0) {
6744  while (previous_separator_position < position) {
6745  String::WriteToFlat<Char>(separator, &buffer[cursor],
6746  0, separator_length);
6747  cursor += separator_length;
6748  previous_separator_position++;
6749  }
6750  String::WriteToFlat<Char>(string, &buffer[cursor],
6751  0, string_length);
6752  cursor += string->length();
6753  }
6754  }
6755  if (separator_length > 0) {
6756  // Array length must be representable as a signed 32-bit number,
6757  // otherwise the total string length would have been too large.
6758  ASSERT(array_length <= 0x7fffffff); // Is int32_t.
6759  int last_array_index = static_cast<int>(array_length - 1);
6760  while (previous_separator_position < last_array_index) {
6761  String::WriteToFlat<Char>(separator, &buffer[cursor],
6762  0, separator_length);
6763  cursor += separator_length;
6764  previous_separator_position++;
6765  }
6766  }
6767  ASSERT(cursor <= buffer.length());
6768 }
6769 
6770 
6771 RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) {
6772  NoHandleAllocation ha;
6773  ASSERT(args.length() == 3);
6774  CONVERT_ARG_CHECKED(JSArray, elements_array, 0);
6775  RUNTIME_ASSERT(elements_array->HasFastSmiOrObjectElements());
6776  CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]);
6777  CONVERT_ARG_CHECKED(String, separator, 2);
6778  // elements_array is fast-mode JSarray of alternating positions
6779  // (increasing order) and strings.
6780  // array_length is length of original array (used to add separators);
6781  // separator is string to put between elements. Assumed to be non-empty.
6782 
6783  // Find total length of join result.
6784  int string_length = 0;
6785  bool is_ascii = separator->IsAsciiRepresentation();
6786  int max_string_length;
6787  if (is_ascii) {
6788  max_string_length = SeqAsciiString::kMaxLength;
6789  } else {
6790  max_string_length = SeqTwoByteString::kMaxLength;
6791  }
6792  bool overflow = false;
6793  CONVERT_NUMBER_CHECKED(int, elements_length,
6794  Int32, elements_array->length());
6795  RUNTIME_ASSERT((elements_length & 1) == 0); // Even length.
6796  FixedArray* elements = FixedArray::cast(elements_array->elements());
6797  for (int i = 0; i < elements_length; i += 2) {
6798  RUNTIME_ASSERT(elements->get(i)->IsNumber());
6799  RUNTIME_ASSERT(elements->get(i + 1)->IsString());
6800  String* string = String::cast(elements->get(i + 1));
6801  int length = string->length();
6802  if (is_ascii && !string->IsAsciiRepresentation()) {
6803  is_ascii = false;
6804  max_string_length = SeqTwoByteString::kMaxLength;
6805  }
6806  if (length > max_string_length ||
6807  max_string_length - length < string_length) {
6808  overflow = true;
6809  break;
6810  }
6811  string_length += length;
6812  }
6813  int separator_length = separator->length();
6814  if (!overflow && separator_length > 0) {
6815  if (array_length <= 0x7fffffffu) {
6816  int separator_count = static_cast<int>(array_length) - 1;
6817  int remaining_length = max_string_length - string_length;
6818  if ((remaining_length / separator_length) >= separator_count) {
6819  string_length += separator_length * (array_length - 1);
6820  } else {
6821  // Not room for the separators within the maximal string length.
6822  overflow = true;
6823  }
6824  } else {
6825  // Nonempty separator and at least 2^31-1 separators necessary
6826  // means that the string is too large to create.
6827  STATIC_ASSERT(String::kMaxLength < 0x7fffffff);
6828  overflow = true;
6829  }
6830  }
6831  if (overflow) {
6832  // Throw OutOfMemory exception for creating too large a string.
6833  V8::FatalProcessOutOfMemory("Array join result too large.");
6834  }
6835 
6836  if (is_ascii) {
6837  MaybeObject* result_allocation =
6838  isolate->heap()->AllocateRawAsciiString(string_length);
6839  if (result_allocation->IsFailure()) return result_allocation;
6840  SeqAsciiString* result_string =
6841  SeqAsciiString::cast(result_allocation->ToObjectUnchecked());
6842  JoinSparseArrayWithSeparator<char>(elements,
6843  elements_length,
6844  array_length,
6845  separator,
6846  Vector<char>(result_string->GetChars(),
6847  string_length));
6848  return result_string;
6849  } else {
6850  MaybeObject* result_allocation =
6851  isolate->heap()->AllocateRawTwoByteString(string_length);
6852  if (result_allocation->IsFailure()) return result_allocation;
6853  SeqTwoByteString* result_string =
6854  SeqTwoByteString::cast(result_allocation->ToObjectUnchecked());
6855  JoinSparseArrayWithSeparator<uc16>(elements,
6856  elements_length,
6857  array_length,
6858  separator,
6859  Vector<uc16>(result_string->GetChars(),
6860  string_length));
6861  return result_string;
6862  }
6863 }
6864 
6865 
6866 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberOr) {
6867  NoHandleAllocation ha;
6868  ASSERT(args.length() == 2);
6869 
6870  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
6871  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
6872  return isolate->heap()->NumberFromInt32(x | y);
6873 }
6874 
6875 
6876 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAnd) {
6877  NoHandleAllocation ha;
6878  ASSERT(args.length() == 2);
6879 
6880  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
6881  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
6882  return isolate->heap()->NumberFromInt32(x & y);
6883 }
6884 
6885 
6886 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberXor) {
6887  NoHandleAllocation ha;
6888  ASSERT(args.length() == 2);
6889 
6890  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
6891  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
6892  return isolate->heap()->NumberFromInt32(x ^ y);
6893 }
6894 
6895 
6896 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberNot) {
6897  NoHandleAllocation ha;
6898  ASSERT(args.length() == 1);
6899 
6900  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
6901  return isolate->heap()->NumberFromInt32(~x);
6902 }
6903 
6904 
6905 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShl) {
6906  NoHandleAllocation ha;
6907  ASSERT(args.length() == 2);
6908 
6909  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
6910  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
6911  return isolate->heap()->NumberFromInt32(x << (y & 0x1f));
6912 }
6913 
6914 
6915 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShr) {
6916  NoHandleAllocation ha;
6917  ASSERT(args.length() == 2);
6918 
6919  CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
6920  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
6921  return isolate->heap()->NumberFromUint32(x >> (y & 0x1f));
6922 }
6923 
6924 
6925 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSar) {
6926  NoHandleAllocation ha;
6927  ASSERT(args.length() == 2);
6928 
6929  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
6930  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
6931  return isolate->heap()->NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f));
6932 }
6933 
6934 
6935 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberEquals) {
6936  NoHandleAllocation ha;
6937  ASSERT(args.length() == 2);
6938 
6941  if (isnan(x)) return Smi::FromInt(NOT_EQUAL);
6942  if (isnan(y)) return Smi::FromInt(NOT_EQUAL);
6943  if (x == y) return Smi::FromInt(EQUAL);
6944  Object* result;
6945  if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
6946  result = Smi::FromInt(EQUAL);
6947  } else {
6948  result = Smi::FromInt(NOT_EQUAL);
6949  }
6950  return result;
6951 }
6952 
6953 
6954 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) {
6955  NoHandleAllocation ha;
6956  ASSERT(args.length() == 2);
6957 
6958  CONVERT_ARG_CHECKED(String, x, 0);
6959  CONVERT_ARG_CHECKED(String, y, 1);
6960 
6961  bool not_equal = !x->Equals(y);
6962  // This is slightly convoluted because the value that signifies
6963  // equality is 0 and inequality is 1 so we have to negate the result
6964  // from String::Equals.
6965  ASSERT(not_equal == 0 || not_equal == 1);
6966  STATIC_CHECK(EQUAL == 0);
6967  STATIC_CHECK(NOT_EQUAL == 1);
6968  return Smi::FromInt(not_equal);
6969 }
6970 
6971 
6972 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberCompare) {
6973  NoHandleAllocation ha;
6974  ASSERT(args.length() == 3);
6975 
6978  if (isnan(x) || isnan(y)) return args[2];
6979  if (x == y) return Smi::FromInt(EQUAL);
6980  if (isless(x, y)) return Smi::FromInt(LESS);
6981  return Smi::FromInt(GREATER);
6982 }
6983 
6984 
6985 // Compare two Smis as if they were converted to strings and then
6986 // compared lexicographically.
6987 RUNTIME_FUNCTION(MaybeObject*, Runtime_SmiLexicographicCompare) {
6988  NoHandleAllocation ha;
6989  ASSERT(args.length() == 2);
6990  CONVERT_SMI_ARG_CHECKED(x_value, 0);
6991  CONVERT_SMI_ARG_CHECKED(y_value, 1);
6992 
6993  // If the integers are equal so are the string representations.
6994  if (x_value == y_value) return Smi::FromInt(EQUAL);
6995 
6996  // If one of the integers is zero the normal integer order is the
6997  // same as the lexicographic order of the string representations.
6998  if (x_value == 0 || y_value == 0)
6999  return Smi::FromInt(x_value < y_value ? LESS : GREATER);
7000 
7001  // If only one of the integers is negative the negative number is
7002  // smallest because the char code of '-' is less than the char code
7003  // of any digit. Otherwise, we make both values positive.
7004 
7005  // Use unsigned values otherwise the logic is incorrect for -MIN_INT on
7006  // architectures using 32-bit Smis.
7007  uint32_t x_scaled = x_value;
7008  uint32_t y_scaled = y_value;
7009  if (x_value < 0 || y_value < 0) {
7010  if (y_value >= 0) return Smi::FromInt(LESS);
7011  if (x_value >= 0) return Smi::FromInt(GREATER);
7012  x_scaled = -x_value;
7013  y_scaled = -y_value;
7014  }
7015 
7016  static const uint32_t kPowersOf10[] = {
7017  1, 10, 100, 1000, 10*1000, 100*1000,
7018  1000*1000, 10*1000*1000, 100*1000*1000,
7019  1000*1000*1000
7020  };
7021 
7022  // If the integers have the same number of decimal digits they can be
7023  // compared directly as the numeric order is the same as the
7024  // lexicographic order. If one integer has fewer digits, it is scaled
7025  // by some power of 10 to have the same number of digits as the longer
7026  // integer. If the scaled integers are equal it means the shorter
7027  // integer comes first in the lexicographic order.
7028 
7029  // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
7030  int x_log2 = IntegerLog2(x_scaled);
7031  int x_log10 = ((x_log2 + 1) * 1233) >> 12;
7032  x_log10 -= x_scaled < kPowersOf10[x_log10];
7033 
7034  int y_log2 = IntegerLog2(y_scaled);
7035  int y_log10 = ((y_log2 + 1) * 1233) >> 12;
7036  y_log10 -= y_scaled < kPowersOf10[y_log10];
7037 
7038  int tie = EQUAL;
7039 
7040  if (x_log10 < y_log10) {
7041  // X has fewer digits. We would like to simply scale up X but that
7042  // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would
7043  // be scaled up to 9_000_000_000. So we scale up by the next
7044  // smallest power and scale down Y to drop one digit. It is OK to
7045  // drop one digit from the longer integer since the final digit is
7046  // past the length of the shorter integer.
7047  x_scaled *= kPowersOf10[y_log10 - x_log10 - 1];
7048  y_scaled /= 10;
7049  tie = LESS;
7050  } else if (y_log10 < x_log10) {
7051  y_scaled *= kPowersOf10[x_log10 - y_log10 - 1];
7052  x_scaled /= 10;
7053  tie = GREATER;
7054  }
7055 
7056  if (x_scaled < y_scaled) return Smi::FromInt(LESS);
7057  if (x_scaled > y_scaled) return Smi::FromInt(GREATER);
7058  return Smi::FromInt(tie);
7059 }
7060 
7061 
7062 static Object* StringInputBufferCompare(RuntimeState* state,
7063  String* x,
7064  String* y) {
7065  StringInputBuffer& bufx = *state->string_input_buffer_compare_bufx();
7066  StringInputBuffer& bufy = *state->string_input_buffer_compare_bufy();
7067  bufx.Reset(x);
7068  bufy.Reset(y);
7069  while (bufx.has_more() && bufy.has_more()) {
7070  int d = bufx.GetNext() - bufy.GetNext();
7071  if (d < 0) return Smi::FromInt(LESS);
7072  else if (d > 0) return Smi::FromInt(GREATER);
7073  }
7074 
7075  // x is (non-trivial) prefix of y:
7076  if (bufy.has_more()) return Smi::FromInt(LESS);
7077  // y is prefix of x:
7078  return Smi::FromInt(bufx.has_more() ? GREATER : EQUAL);
7079 }
7080 
7081 
7082 static Object* FlatStringCompare(String* x, String* y) {
7083  ASSERT(x->IsFlat());
7084  ASSERT(y->IsFlat());
7085  Object* equal_prefix_result = Smi::FromInt(EQUAL);
7086  int prefix_length = x->length();
7087  if (y->length() < prefix_length) {
7088  prefix_length = y->length();
7089  equal_prefix_result = Smi::FromInt(GREATER);
7090  } else if (y->length() > prefix_length) {
7091  equal_prefix_result = Smi::FromInt(LESS);
7092  }
7093  int r;
7094  String::FlatContent x_content = x->GetFlatContent();
7095  String::FlatContent y_content = y->GetFlatContent();
7096  if (x_content.IsAscii()) {
7097  Vector<const char> x_chars = x_content.ToAsciiVector();
7098  if (y_content.IsAscii()) {
7099  Vector<const char> y_chars = y_content.ToAsciiVector();
7100  r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7101  } else {
7102  Vector<const uc16> y_chars = y_content.ToUC16Vector();
7103  r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7104  }
7105  } else {
7106  Vector<const uc16> x_chars = x_content.ToUC16Vector();
7107  if (y_content.IsAscii()) {
7108  Vector<const char> y_chars = y_content.ToAsciiVector();
7109  r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7110  } else {
7111  Vector<const uc16> y_chars = y_content.ToUC16Vector();
7112  r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7113  }
7114  }
7115  Object* result;
7116  if (r == 0) {
7117  result = equal_prefix_result;
7118  } else {
7119  result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
7120  }
7121  ASSERT(result ==
7122  StringInputBufferCompare(Isolate::Current()->runtime_state(), x, y));
7123  return result;
7124 }
7125 
7126 
7127 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCompare) {
7128  NoHandleAllocation ha;
7129  ASSERT(args.length() == 2);
7130 
7131  CONVERT_ARG_CHECKED(String, x, 0);
7132  CONVERT_ARG_CHECKED(String, y, 1);
7133 
7134  isolate->counters()->string_compare_runtime()->Increment();
7135 
7136  // A few fast case tests before we flatten.
7137  if (x == y) return Smi::FromInt(EQUAL);
7138  if (y->length() == 0) {
7139  if (x->length() == 0) return Smi::FromInt(EQUAL);
7140  return Smi::FromInt(GREATER);
7141  } else if (x->length() == 0) {
7142  return Smi::FromInt(LESS);
7143  }
7144 
7145  int d = x->Get(0) - y->Get(0);
7146  if (d < 0) return Smi::FromInt(LESS);
7147  else if (d > 0) return Smi::FromInt(GREATER);
7148 
7149  Object* obj;
7150  { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(x);
7151  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7152  }
7153  { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(y);
7154  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7155  }
7156 
7157  return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
7158  : StringInputBufferCompare(isolate->runtime_state(), x, y);
7159 }
7160 
7161 
7162 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_acos) {
7163  NoHandleAllocation ha;
7164  ASSERT(args.length() == 1);
7165  isolate->counters()->math_acos()->Increment();
7166 
7168  return isolate->transcendental_cache()->Get(TranscendentalCache::ACOS, x);
7169 }
7170 
7171 
7172 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_asin) {
7173  NoHandleAllocation ha;
7174  ASSERT(args.length() == 1);
7175  isolate->counters()->math_asin()->Increment();
7176 
7178  return isolate->transcendental_cache()->Get(TranscendentalCache::ASIN, x);
7179 }
7180 
7181 
7182 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan) {
7183  NoHandleAllocation ha;
7184  ASSERT(args.length() == 1);
7185  isolate->counters()->math_atan()->Increment();
7186 
7188  return isolate->transcendental_cache()->Get(TranscendentalCache::ATAN, x);
7189 }
7190 
7191 
7192 static const double kPiDividedBy4 = 0.78539816339744830962;
7193 
7194 
7195 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan2) {
7196  NoHandleAllocation ha;
7197  ASSERT(args.length() == 2);
7198  isolate->counters()->math_atan2()->Increment();
7199 
7202  double result;
7203  if (isinf(x) && isinf(y)) {
7204  // Make sure that the result in case of two infinite arguments
7205  // is a multiple of Pi / 4. The sign of the result is determined
7206  // by the first argument (x) and the sign of the second argument
7207  // determines the multiplier: one or three.
7208  int multiplier = (x < 0) ? -1 : 1;
7209  if (y < 0) multiplier *= 3;
7210  result = multiplier * kPiDividedBy4;
7211  } else {
7212  result = atan2(x, y);
7213  }
7214  return isolate->heap()->AllocateHeapNumber(result);
7215 }
7216 
7217 
7218 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_ceil) {
7219  NoHandleAllocation ha;
7220  ASSERT(args.length() == 1);
7221  isolate->counters()->math_ceil()->Increment();
7222 
7224  return isolate->heap()->NumberFromDouble(ceiling(x));
7225 }
7226 
7227 
7228 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_cos) {
7229  NoHandleAllocation ha;
7230  ASSERT(args.length() == 1);
7231  isolate->counters()->math_cos()->Increment();
7232 
7234  return isolate->transcendental_cache()->Get(TranscendentalCache::COS, x);
7235 }
7236 
7237 
7238 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_exp) {
7239  NoHandleAllocation ha;
7240  ASSERT(args.length() == 1);
7241  isolate->counters()->math_exp()->Increment();
7242 
7244  return isolate->transcendental_cache()->Get(TranscendentalCache::EXP, x);
7245 }
7246 
7247 
7248 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_floor) {
7249  NoHandleAllocation ha;
7250  ASSERT(args.length() == 1);
7251  isolate->counters()->math_floor()->Increment();
7252 
7254  return isolate->heap()->NumberFromDouble(floor(x));
7255 }
7256 
7257 
7258 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_log) {
7259  NoHandleAllocation ha;
7260  ASSERT(args.length() == 1);
7261  isolate->counters()->math_log()->Increment();
7262 
7264  return isolate->transcendental_cache()->Get(TranscendentalCache::LOG, x);
7265 }
7266 
7267 // Slow version of Math.pow. We check for fast paths for special cases.
7268 // Used if SSE2/VFP3 is not available.
7269 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow) {
7270  NoHandleAllocation ha;
7271  ASSERT(args.length() == 2);
7272  isolate->counters()->math_pow()->Increment();
7273 
7275 
7276  // If the second argument is a smi, it is much faster to call the
7277  // custom powi() function than the generic pow().
7278  if (args[1]->IsSmi()) {
7279  int y = args.smi_at(1);
7280  return isolate->heap()->NumberFromDouble(power_double_int(x, y));
7281  }
7282 
7284  int y_int = static_cast<int>(y);
7285  double result;
7286  if (y == y_int) {
7287  result = power_double_int(x, y_int); // Returns 1 if exponent is 0.
7288  } else if (y == 0.5) {
7289  result = (isinf(x)) ? V8_INFINITY
7290  : fast_sqrt(x + 0.0); // Convert -0 to +0.
7291  } else if (y == -0.5) {
7292  result = (isinf(x)) ? 0
7293  : 1.0 / fast_sqrt(x + 0.0); // Convert -0 to +0.
7294  } else {
7295  result = power_double_double(x, y);
7296  }
7297  if (isnan(result)) return isolate->heap()->nan_value();
7298  return isolate->heap()->AllocateHeapNumber(result);
7299 }
7300 
7301 // Fast version of Math.pow if we know that y is not an integer and y is not
7302 // -0.5 or 0.5. Used as slow case from full codegen.
7303 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow_cfunction) {
7304  NoHandleAllocation ha;
7305  ASSERT(args.length() == 2);
7306  isolate->counters()->math_pow()->Increment();
7307 
7310  if (y == 0) {
7311  return Smi::FromInt(1);
7312  } else {
7313  double result = power_double_double(x, y);
7314  if (isnan(result)) return isolate->heap()->nan_value();
7315  return isolate->heap()->AllocateHeapNumber(result);
7316  }
7317 }
7318 
7319 
7320 RUNTIME_FUNCTION(MaybeObject*, Runtime_RoundNumber) {
7321  NoHandleAllocation ha;
7322  ASSERT(args.length() == 1);
7323  isolate->counters()->math_round()->Increment();
7324 
7325  if (!args[0]->IsHeapNumber()) {
7326  // Must be smi. Return the argument unchanged for all the other types
7327  // to make fuzz-natives test happy.
7328  return args[0];
7329  }
7330 
7331  HeapNumber* number = reinterpret_cast<HeapNumber*>(args[0]);
7332 
7333  double value = number->value();
7334  int exponent = number->get_exponent();
7335  int sign = number->get_sign();
7336 
7337  if (exponent < -1) {
7338  // Number in range ]-0.5..0.5[. These always round to +/-zero.
7339  if (sign) return isolate->heap()->minus_zero_value();
7340  return Smi::FromInt(0);
7341  }
7342 
7343  // We compare with kSmiValueSize - 2 because (2^30 - 0.1) has exponent 29 and
7344  // should be rounded to 2^30, which is not smi (for 31-bit smis, similar
7345  // argument holds for 32-bit smis).
7346  if (!sign && exponent < kSmiValueSize - 2) {
7347  return Smi::FromInt(static_cast<int>(value + 0.5));
7348  }
7349 
7350  // If the magnitude is big enough, there's no place for fraction part. If we
7351  // try to add 0.5 to this number, 1.0 will be added instead.
7352  if (exponent >= 52) {
7353  return number;
7354  }
7355 
7356  if (sign && value >= -0.5) return isolate->heap()->minus_zero_value();
7357 
7358  // Do not call NumberFromDouble() to avoid extra checks.
7359  return isolate->heap()->AllocateHeapNumber(floor(value + 0.5));
7360 }
7361 
7362 
7363 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sin) {
7364  NoHandleAllocation ha;
7365  ASSERT(args.length() == 1);
7366  isolate->counters()->math_sin()->Increment();
7367 
7369  return isolate->transcendental_cache()->Get(TranscendentalCache::SIN, x);
7370 }
7371 
7372 
7373 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sqrt) {
7374  NoHandleAllocation ha;
7375  ASSERT(args.length() == 1);
7376  isolate->counters()->math_sqrt()->Increment();
7377 
7379  return isolate->heap()->AllocateHeapNumber(fast_sqrt(x));
7380 }
7381 
7382 
7383 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_tan) {
7384  NoHandleAllocation ha;
7385  ASSERT(args.length() == 1);
7386  isolate->counters()->math_tan()->Increment();
7387 
7389  return isolate->transcendental_cache()->Get(TranscendentalCache::TAN, x);
7390 }
7391 
7392 
7393 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateMakeDay) {
7394  NoHandleAllocation ha;
7395  ASSERT(args.length() == 2);
7396 
7397  CONVERT_SMI_ARG_CHECKED(year, 0);
7398  CONVERT_SMI_ARG_CHECKED(month, 1);
7399 
7400  return Smi::FromInt(isolate->date_cache()->DaysFromYearMonth(year, month));
7401 }
7402 
7403 
7404 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateSetValue) {
7405  HandleScope scope(isolate);
7406  ASSERT(args.length() == 3);
7407 
7409  CONVERT_DOUBLE_ARG_CHECKED(time, 1);
7410  CONVERT_SMI_ARG_CHECKED(is_utc, 2);
7411 
7412  DateCache* date_cache = isolate->date_cache();
7413 
7414  Object* value = NULL;
7415  bool is_value_nan = false;
7416  if (isnan(time)) {
7417  value = isolate->heap()->nan_value();
7418  is_value_nan = true;
7419  } else if (!is_utc &&
7422  value = isolate->heap()->nan_value();
7423  is_value_nan = true;
7424  } else {
7425  time = is_utc ? time : date_cache->ToUTC(static_cast<int64_t>(time));
7426  if (time < -DateCache::kMaxTimeInMs ||
7427  time > DateCache::kMaxTimeInMs) {
7428  value = isolate->heap()->nan_value();
7429  is_value_nan = true;
7430  } else {
7431  MaybeObject* maybe_result =
7432  isolate->heap()->AllocateHeapNumber(DoubleToInteger(time));
7433  if (!maybe_result->ToObject(&value)) return maybe_result;
7434  }
7435  }
7436  date->SetValue(value, is_value_nan);
7437  return value;
7438 }
7439 
7440 
7441 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewArgumentsFast) {
7442  HandleScope scope(isolate);
7443  ASSERT(args.length() == 3);
7444 
7445  Handle<JSFunction> callee = args.at<JSFunction>(0);
7446  Object** parameters = reinterpret_cast<Object**>(args[1]);
7447  const int argument_count = Smi::cast(args[2])->value();
7448 
7449  Handle<JSObject> result =
7450  isolate->factory()->NewArgumentsObject(callee, argument_count);
7451  // Allocate the elements if needed.
7452  int parameter_count = callee->shared()->formal_parameter_count();
7453  if (argument_count > 0) {
7454  if (parameter_count > 0) {
7455  int mapped_count = Min(argument_count, parameter_count);
7456  Handle<FixedArray> parameter_map =
7457  isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
7458  parameter_map->set_map(
7459  isolate->heap()->non_strict_arguments_elements_map());
7460 
7461  Handle<Map> old_map(result->map());
7462  Handle<Map> new_map = isolate->factory()->CopyMap(old_map);
7463  new_map->set_elements_kind(NON_STRICT_ARGUMENTS_ELEMENTS);
7464 
7465  result->set_map(*new_map);
7466  result->set_elements(*parameter_map);
7467 
7468  // Store the context and the arguments array at the beginning of the
7469  // parameter map.
7470  Handle<Context> context(isolate->context());
7471  Handle<FixedArray> arguments =
7472  isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
7473  parameter_map->set(0, *context);
7474  parameter_map->set(1, *arguments);
7475 
7476  // Loop over the actual parameters backwards.
7477  int index = argument_count - 1;
7478  while (index >= mapped_count) {
7479  // These go directly in the arguments array and have no
7480  // corresponding slot in the parameter map.
7481  arguments->set(index, *(parameters - index - 1));
7482  --index;
7483  }
7484 
7485  Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
7486  while (index >= 0) {
7487  // Detect duplicate names to the right in the parameter list.
7488  Handle<String> name(scope_info->ParameterName(index));
7489  int context_local_count = scope_info->ContextLocalCount();
7490  bool duplicate = false;
7491  for (int j = index + 1; j < parameter_count; ++j) {
7492  if (scope_info->ParameterName(j) == *name) {
7493  duplicate = true;
7494  break;
7495  }
7496  }
7497 
7498  if (duplicate) {
7499  // This goes directly in the arguments array with a hole in the
7500  // parameter map.
7501  arguments->set(index, *(parameters - index - 1));
7502  parameter_map->set_the_hole(index + 2);
7503  } else {
7504  // The context index goes in the parameter map with a hole in the
7505  // arguments array.
7506  int context_index = -1;
7507  for (int j = 0; j < context_local_count; ++j) {
7508  if (scope_info->ContextLocalName(j) == *name) {
7509  context_index = j;
7510  break;
7511  }
7512  }
7513  ASSERT(context_index >= 0);
7514  arguments->set_the_hole(index);
7515  parameter_map->set(index + 2, Smi::FromInt(
7516  Context::MIN_CONTEXT_SLOTS + context_index));
7517  }
7518 
7519  --index;
7520  }
7521  } else {
7522  // If there is no aliasing, the arguments object elements are not
7523  // special in any way.
7524  Handle<FixedArray> elements =
7525  isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
7526  result->set_elements(*elements);
7527  for (int i = 0; i < argument_count; ++i) {
7528  elements->set(i, *(parameters - i - 1));
7529  }
7530  }
7531  }
7532  return *result;
7533 }
7534 
7535 
7536 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStrictArgumentsFast) {
7537  NoHandleAllocation ha;
7538  ASSERT(args.length() == 3);
7539 
7540  JSFunction* callee = JSFunction::cast(args[0]);
7541  Object** parameters = reinterpret_cast<Object**>(args[1]);
7542  const int length = args.smi_at(2);
7543 
7544  Object* result;
7545  { MaybeObject* maybe_result =
7546  isolate->heap()->AllocateArgumentsObject(callee, length);
7547  if (!maybe_result->ToObject(&result)) return maybe_result;
7548  }
7549  // Allocate the elements if needed.
7550  if (length > 0) {
7551  // Allocate the fixed array.
7552  Object* obj;
7553  { MaybeObject* maybe_obj = isolate->heap()->AllocateRawFixedArray(length);
7554  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7555  }
7556 
7557  AssertNoAllocation no_gc;
7558  FixedArray* array = reinterpret_cast<FixedArray*>(obj);
7559  array->set_map_no_write_barrier(isolate->heap()->fixed_array_map());
7560  array->set_length(length);
7561 
7562  WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
7563  for (int i = 0; i < length; i++) {
7564  array->set(i, *--parameters, mode);
7565  }
7566  JSObject::cast(result)->set_elements(FixedArray::cast(obj));
7567  }
7568  return result;
7569 }
7570 
7571 
7572 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewClosure) {
7573  HandleScope scope(isolate);
7574  ASSERT(args.length() == 3);
7575  CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
7577  CONVERT_BOOLEAN_ARG_CHECKED(pretenure, 2);
7578 
7579  // The caller ensures that we pretenure closures that are assigned
7580  // directly to properties.
7581  PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
7582  Handle<JSFunction> result =
7583  isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
7584  context,
7585  pretenure_flag);
7586  return *result;
7587 }
7588 
7589 
7590 // Find the arguments of the JavaScript function invocation that called
7591 // into C++ code. Collect these in a newly allocated array of handles (possibly
7592 // prefixed by a number of empty handles).
7593 static SmartArrayPointer<Handle<Object> > GetCallerArguments(
7594  int prefix_argc,
7595  int* total_argc) {
7596  // Find frame containing arguments passed to the caller.
7598  JavaScriptFrame* frame = it.frame();
7599  List<JSFunction*> functions(2);
7600  frame->GetFunctions(&functions);
7601  if (functions.length() > 1) {
7602  int inlined_jsframe_index = functions.length() - 1;
7603  JSFunction* inlined_function = functions[inlined_jsframe_index];
7604  Vector<SlotRef> args_slots =
7605  SlotRef::ComputeSlotMappingForArguments(
7606  frame,
7607  inlined_jsframe_index,
7608  inlined_function->shared()->formal_parameter_count());
7609 
7610  int args_count = args_slots.length();
7611 
7612  *total_argc = prefix_argc + args_count;
7613  SmartArrayPointer<Handle<Object> > param_data(
7614  NewArray<Handle<Object> >(*total_argc));
7615  for (int i = 0; i < args_count; i++) {
7616  Handle<Object> val = args_slots[i].GetValue();
7617  param_data[prefix_argc + i] = val;
7618  }
7619 
7620  args_slots.Dispose();
7621 
7622  return param_data;
7623  } else {
7624  it.AdvanceToArgumentsFrame();
7625  frame = it.frame();
7626  int args_count = frame->ComputeParametersCount();
7627 
7628  *total_argc = prefix_argc + args_count;
7629  SmartArrayPointer<Handle<Object> > param_data(
7630  NewArray<Handle<Object> >(*total_argc));
7631  for (int i = 0; i < args_count; i++) {
7632  Handle<Object> val = Handle<Object>(frame->GetParameter(i));
7633  param_data[prefix_argc + i] = val;
7634  }
7635  return param_data;
7636  }
7637 }
7638 
7639 
7640 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionBindArguments) {
7641  HandleScope scope(isolate);
7642  ASSERT(args.length() == 4);
7643  CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0);
7644  RUNTIME_ASSERT(args[3]->IsNumber());
7645  Handle<Object> bindee = args.at<Object>(1);
7646 
7647  // TODO(lrn): Create bound function in C++ code from premade shared info.
7648  bound_function->shared()->set_bound(true);
7649  // Get all arguments of calling function (Function.prototype.bind).
7650  int argc = 0;
7651  SmartArrayPointer<Handle<Object> > arguments = GetCallerArguments(0, &argc);
7652  // Don't count the this-arg.
7653  if (argc > 0) {
7654  ASSERT(*arguments[0] == args[2]);
7655  argc--;
7656  } else {
7657  ASSERT(args[2]->IsUndefined());
7658  }
7659  // Initialize array of bindings (function, this, and any existing arguments
7660  // if the function was already bound).
7661  Handle<FixedArray> new_bindings;
7662  int i;
7663  if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) {
7664  Handle<FixedArray> old_bindings(
7665  JSFunction::cast(*bindee)->function_bindings());
7666  new_bindings =
7667  isolate->factory()->NewFixedArray(old_bindings->length() + argc);
7668  bindee = Handle<Object>(old_bindings->get(JSFunction::kBoundFunctionIndex));
7669  i = 0;
7670  for (int n = old_bindings->length(); i < n; i++) {
7671  new_bindings->set(i, old_bindings->get(i));
7672  }
7673  } else {
7674  int array_size = JSFunction::kBoundArgumentsStartIndex + argc;
7675  new_bindings = isolate->factory()->NewFixedArray(array_size);
7676  new_bindings->set(JSFunction::kBoundFunctionIndex, *bindee);
7677  new_bindings->set(JSFunction::kBoundThisIndex, args[2]);
7678  i = 2;
7679  }
7680  // Copy arguments, skipping the first which is "this_arg".
7681  for (int j = 0; j < argc; j++, i++) {
7682  new_bindings->set(i, *arguments[j + 1]);
7683  }
7684  new_bindings->set_map_no_write_barrier(
7685  isolate->heap()->fixed_cow_array_map());
7686  bound_function->set_function_bindings(*new_bindings);
7687 
7688  // Update length.
7689  Handle<String> length_symbol = isolate->factory()->length_symbol();
7690  Handle<Object> new_length(args.at<Object>(3));
7691  PropertyAttributes attr =
7693  ForceSetProperty(bound_function, length_symbol, new_length, attr);
7694  return *bound_function;
7695 }
7696 
7697 
7698 RUNTIME_FUNCTION(MaybeObject*, Runtime_BoundFunctionGetBindings) {
7699  HandleScope handles(isolate);
7700  ASSERT(args.length() == 1);
7701  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0);
7702  if (callable->IsJSFunction()) {
7703  Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
7704  if (function->shared()->bound()) {
7705  Handle<FixedArray> bindings(function->function_bindings());
7706  ASSERT(bindings->map() == isolate->heap()->fixed_cow_array_map());
7707  return *isolate->factory()->NewJSArrayWithElements(bindings);
7708  }
7709  }
7710  return isolate->heap()->undefined_value();
7711 }
7712 
7713 
7714 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObjectFromBound) {
7715  HandleScope scope(isolate);
7716  ASSERT(args.length() == 1);
7717  // First argument is a function to use as a constructor.
7718  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
7719  RUNTIME_ASSERT(function->shared()->bound());
7720 
7721  // The argument is a bound function. Extract its bound arguments
7722  // and callable.
7723  Handle<FixedArray> bound_args =
7724  Handle<FixedArray>(FixedArray::cast(function->function_bindings()));
7725  int bound_argc = bound_args->length() - JSFunction::kBoundArgumentsStartIndex;
7726  Handle<Object> bound_function(
7728  ASSERT(!bound_function->IsJSFunction() ||
7729  !Handle<JSFunction>::cast(bound_function)->shared()->bound());
7730 
7731  int total_argc = 0;
7732  SmartArrayPointer<Handle<Object> > param_data =
7733  GetCallerArguments(bound_argc, &total_argc);
7734  for (int i = 0; i < bound_argc; i++) {
7735  param_data[i] = Handle<Object>(bound_args->get(
7737  }
7738 
7739  if (!bound_function->IsJSFunction()) {
7740  bool exception_thrown;
7741  bound_function = Execution::TryGetConstructorDelegate(bound_function,
7742  &exception_thrown);
7743  if (exception_thrown) return Failure::Exception();
7744  }
7745  ASSERT(bound_function->IsJSFunction());
7746 
7747  bool exception = false;
7748  Handle<Object> result =
7749  Execution::New(Handle<JSFunction>::cast(bound_function),
7750  total_argc, *param_data, &exception);
7751  if (exception) {
7752  return Failure::Exception();
7753  }
7754  ASSERT(!result.is_null());
7755  return *result;
7756 }
7757 
7758 
7759 static void TrySettingInlineConstructStub(Isolate* isolate,
7760  Handle<JSFunction> function) {
7761  Handle<Object> prototype = isolate->factory()->null_value();
7762  if (function->has_instance_prototype()) {
7763  prototype = Handle<Object>(function->instance_prototype(), isolate);
7764  }
7765  if (function->shared()->CanGenerateInlineConstructor(*prototype)) {
7766  ConstructStubCompiler compiler(isolate);
7767  Handle<Code> code = compiler.CompileConstructStub(function);
7768  function->shared()->set_construct_stub(*code);
7769  }
7770 }
7771 
7772 
7773 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObject) {
7774  HandleScope scope(isolate);
7775  ASSERT(args.length() == 1);
7776 
7777  Handle<Object> constructor = args.at<Object>(0);
7778 
7779  // If the constructor isn't a proper function we throw a type error.
7780  if (!constructor->IsJSFunction()) {
7781  Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
7782  Handle<Object> type_error =
7783  isolate->factory()->NewTypeError("not_constructor", arguments);
7784  return isolate->Throw(*type_error);
7785  }
7786 
7787  Handle<JSFunction> function = Handle<JSFunction>::cast(constructor);
7788 
7789  // If function should not have prototype, construction is not allowed. In this
7790  // case generated code bailouts here, since function has no initial_map.
7791  if (!function->should_have_prototype() && !function->shared()->bound()) {
7792  Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
7793  Handle<Object> type_error =
7794  isolate->factory()->NewTypeError("not_constructor", arguments);
7795  return isolate->Throw(*type_error);
7796  }
7797 
7798 #ifdef ENABLE_DEBUGGER_SUPPORT
7799  Debug* debug = isolate->debug();
7800  // Handle stepping into constructors if step into is active.
7801  if (debug->StepInActive()) {
7802  debug->HandleStepIn(function, Handle<Object>::null(), 0, true);
7803  }
7804 #endif
7805 
7806  if (function->has_initial_map()) {
7807  if (function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
7808  // The 'Function' function ignores the receiver object when
7809  // called using 'new' and creates a new JSFunction object that
7810  // is returned. The receiver object is only used for error
7811  // reporting if an error occurs when constructing the new
7812  // JSFunction. FACTORY->NewJSObject() should not be used to
7813  // allocate JSFunctions since it does not properly initialize
7814  // the shared part of the function. Since the receiver is
7815  // ignored anyway, we use the global object as the receiver
7816  // instead of a new JSFunction object. This way, errors are
7817  // reported the same way whether or not 'Function' is called
7818  // using 'new'.
7819  return isolate->context()->global_object();
7820  }
7821  }
7822 
7823  // The function should be compiled for the optimization hints to be
7824  // available.
7826 
7827  Handle<SharedFunctionInfo> shared(function->shared(), isolate);
7828  if (!function->has_initial_map() &&
7829  shared->IsInobjectSlackTrackingInProgress()) {
7830  // The tracking is already in progress for another function. We can only
7831  // track one initial_map at a time, so we force the completion before the
7832  // function is called as a constructor for the first time.
7833  shared->CompleteInobjectSlackTracking();
7834  }
7835 
7836  bool first_allocation = !shared->live_objects_may_exist();
7837  Handle<JSObject> result = isolate->factory()->NewJSObject(function);
7838  RETURN_IF_EMPTY_HANDLE(isolate, result);
7839  // Delay setting the stub if inobject slack tracking is in progress.
7840  if (first_allocation && !shared->IsInobjectSlackTrackingInProgress()) {
7841  TrySettingInlineConstructStub(isolate, function);
7842  }
7843 
7844  isolate->counters()->constructed_objects()->Increment();
7845  isolate->counters()->constructed_objects_runtime()->Increment();
7846 
7847  return *result;
7848 }
7849 
7850 
7851 RUNTIME_FUNCTION(MaybeObject*, Runtime_FinalizeInstanceSize) {
7852  HandleScope scope(isolate);
7853  ASSERT(args.length() == 1);
7854 
7855  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
7856  function->shared()->CompleteInobjectSlackTracking();
7857  TrySettingInlineConstructStub(isolate, function);
7858 
7859  return isolate->heap()->undefined_value();
7860 }
7861 
7862 
7863 RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyCompile) {
7864  HandleScope scope(isolate);
7865  ASSERT(args.length() == 1);
7866 
7867  Handle<JSFunction> function = args.at<JSFunction>(0);
7868 #ifdef DEBUG
7869  if (FLAG_trace_lazy && !function->shared()->is_compiled()) {
7870  PrintF("[lazy: ");
7871  function->PrintName();
7872  PrintF("]\n");
7873  }
7874 #endif
7875 
7876  // Compile the target function.
7877  ASSERT(!function->is_compiled());
7878  if (!JSFunction::CompileLazy(function, KEEP_EXCEPTION)) {
7879  return Failure::Exception();
7880  }
7881 
7882  // All done. Return the compiled code.
7883  ASSERT(function->is_compiled());
7884  return function->code();
7885 }
7886 
7887 
7888 RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyRecompile) {
7889  HandleScope scope(isolate);
7890  ASSERT(args.length() == 1);
7891  Handle<JSFunction> function = args.at<JSFunction>(0);
7892 
7893  // If the function is not compiled ignore the lazy
7894  // recompilation. This can happen if the debugger is activated and
7895  // the function is returned to the not compiled state.
7896  if (!function->shared()->is_compiled()) {
7897  function->ReplaceCode(function->shared()->code());
7898  return function->code();
7899  }
7900 
7901  // If the function is not optimizable or debugger is active continue using the
7902  // code from the full compiler.
7903  if (!FLAG_crankshaft ||
7904  !function->shared()->code()->optimizable() ||
7905  isolate->DebuggerHasBreakPoints()) {
7906  if (FLAG_trace_opt) {
7907  PrintF("[failed to optimize ");
7908  function->PrintName();
7909  PrintF(": is code optimizable: %s, is debugger enabled: %s]\n",
7910  function->shared()->code()->optimizable() ? "T" : "F",
7911  isolate->DebuggerHasBreakPoints() ? "T" : "F");
7912  }
7913  function->ReplaceCode(function->shared()->code());
7914  return function->code();
7915  }
7916  function->shared()->code()->set_profiler_ticks(0);
7917  if (JSFunction::CompileOptimized(function,
7918  BailoutId::None(),
7919  CLEAR_EXCEPTION)) {
7920  return function->code();
7921  }
7922  if (FLAG_trace_opt) {
7923  PrintF("[failed to optimize ");
7924  function->PrintName();
7925  PrintF(": optimized compilation failed]\n");
7926  }
7927  function->ReplaceCode(function->shared()->code());
7928  return function->code();
7929 }
7930 
7931 
7932 RUNTIME_FUNCTION(MaybeObject*, Runtime_ParallelRecompile) {
7933  HandleScope handle_scope(isolate);
7934  ASSERT(FLAG_parallel_recompilation);
7936  return *isolate->factory()->undefined_value();
7937 }
7938 
7939 
7941  public:
7942  explicit ActivationsFinder(JSFunction* function)
7943  : function_(function), has_activations_(false) {}
7944 
7945  void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
7946  if (has_activations_) return;
7947 
7948  for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
7949  JavaScriptFrame* frame = it.frame();
7950  if (frame->is_optimized() && frame->function() == function_) {
7951  has_activations_ = true;
7952  return;
7953  }
7954  }
7955  }
7956 
7957  bool has_activations() { return has_activations_; }
7958 
7959  private:
7960  JSFunction* function_;
7961  bool has_activations_;
7962 };
7963 
7964 
7965 RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyDeoptimized) {
7966  HandleScope scope(isolate);
7967  ASSERT(args.length() == 1);
7968  RUNTIME_ASSERT(args[0]->IsSmi());
7970  static_cast<Deoptimizer::BailoutType>(args.smi_at(0));
7971  Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
7972  ASSERT(isolate->heap()->IsAllocationAllowed());
7973  JavaScriptFrameIterator it(isolate);
7974 
7975  // Make sure to materialize objects before causing any allocation.
7976  deoptimizer->MaterializeHeapObjects(&it);
7977  delete deoptimizer;
7978 
7979  JavaScriptFrame* frame = it.frame();
7980  RUNTIME_ASSERT(frame->function()->IsJSFunction());
7981  Handle<JSFunction> function(JSFunction::cast(frame->function()), isolate);
7982  RUNTIME_ASSERT(type != Deoptimizer::EAGER || function->IsOptimized());
7983 
7984  // Avoid doing too much work when running with --always-opt and keep
7985  // the optimized code around.
7986  if (FLAG_always_opt || type == Deoptimizer::LAZY) {
7987  return isolate->heap()->undefined_value();
7988  }
7989 
7990  // Find other optimized activations of the function or functions that
7991  // share the same optimized code.
7992  bool has_other_activations = false;
7993  while (!it.done()) {
7994  JavaScriptFrame* frame = it.frame();
7995  JSFunction* other_function = JSFunction::cast(frame->function());
7996  if (frame->is_optimized() && other_function->code() == function->code()) {
7997  has_other_activations = true;
7998  break;
7999  }
8000  it.Advance();
8001  }
8002 
8003  if (!has_other_activations) {
8004  ActivationsFinder activations_finder(*function);
8005  isolate->thread_manager()->IterateArchivedThreads(&activations_finder);
8006  has_other_activations = activations_finder.has_activations();
8007  }
8008 
8009  if (!has_other_activations) {
8010  if (FLAG_trace_deopt) {
8011  PrintF("[removing optimized code for: ");
8012  function->PrintName();
8013  PrintF("]\n");
8014  }
8015  function->ReplaceCode(function->shared()->code());
8016  } else {
8018  }
8019  // Flush optimized code cache for this function.
8020  function->shared()->ClearOptimizedCodeMap();
8021 
8022  return isolate->heap()->undefined_value();
8023 }
8024 
8025 
8026 RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyOSR) {
8027  Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8028  delete deoptimizer;
8029  return isolate->heap()->undefined_value();
8030 }
8031 
8032 
8033 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeoptimizeFunction) {
8034  HandleScope scope(isolate);
8035  ASSERT(args.length() == 1);
8036  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8037  if (!function->IsOptimized()) return isolate->heap()->undefined_value();
8038 
8040 
8041  return isolate->heap()->undefined_value();
8042 }
8043 
8044 
8045 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearFunctionTypeFeedback) {
8046  HandleScope scope(isolate);
8047  ASSERT(args.length() == 1);
8048  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8049  Code* unoptimized = function->shared()->code();
8050  if (unoptimized->kind() == Code::FUNCTION) {
8051  unoptimized->ClearInlineCaches();
8052  unoptimized->ClearTypeFeedbackCells(isolate->heap());
8053  }
8054  return isolate->heap()->undefined_value();
8055 }
8056 
8057 
8058 RUNTIME_FUNCTION(MaybeObject*, Runtime_RunningInSimulator) {
8059 #if defined(USE_SIMULATOR)
8060  return isolate->heap()->true_value();
8061 #else
8062  return isolate->heap()->false_value();
8063 #endif
8064 }
8065 
8066 
8067 RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) {
8068  HandleScope scope(isolate);
8069  RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
8070  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8071 
8072  if (!function->IsOptimizable()) return isolate->heap()->undefined_value();
8073  function->MarkForLazyRecompilation();
8074 
8075  Code* unoptimized = function->shared()->code();
8076  if (args.length() == 2 &&
8077  unoptimized->kind() == Code::FUNCTION) {
8079  CHECK(type->IsEqualTo(CStrVector("osr")));
8080  isolate->runtime_profiler()->AttemptOnStackReplacement(*function);
8083  }
8084 
8085  return isolate->heap()->undefined_value();
8086 }
8087 
8088 
8089 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) {
8090  HandleScope scope(isolate);
8091  ASSERT(args.length() == 1);
8092  // The least significant bit (after untagging) indicates whether the
8093  // function is currently optimized, regardless of reason.
8094  if (!V8::UseCrankshaft()) {
8095  return Smi::FromInt(4); // 4 == "never".
8096  }
8097  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8098  if (FLAG_parallel_recompilation) {
8099  if (function->IsMarkedForLazyRecompilation()) {
8100  return Smi::FromInt(5);
8101  }
8102  }
8103  if (FLAG_always_opt) {
8104  // We may have always opt, but that is more best-effort than a real
8105  // promise, so we still say "no" if it is not optimized.
8106  return function->IsOptimized() ? Smi::FromInt(3) // 3 == "always".
8107  : Smi::FromInt(2); // 2 == "no".
8108  }
8109  return function->IsOptimized() ? Smi::FromInt(1) // 1 == "yes".
8110  : Smi::FromInt(2); // 2 == "no".
8111 }
8112 
8113 
8114 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationCount) {
8115  HandleScope scope(isolate);
8116  ASSERT(args.length() == 1);
8117  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8118  return Smi::FromInt(function->shared()->opt_count());
8119 }
8120 
8121 
8122 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
8123  HandleScope scope(isolate);
8124  ASSERT(args.length() == 1);
8125  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8126 
8127  // We're not prepared to handle a function with arguments object.
8128  ASSERT(!function->shared()->uses_arguments());
8129 
8130  // We have hit a back edge in an unoptimized frame for a function that was
8131  // selected for on-stack replacement. Find the unoptimized code object.
8132  Handle<Code> unoptimized(function->shared()->code(), isolate);
8133  // Keep track of whether we've succeeded in optimizing.
8134  bool succeeded = unoptimized->optimizable();
8135  if (succeeded) {
8136  // If we are trying to do OSR when there are already optimized
8137  // activations of the function, it means (a) the function is directly or
8138  // indirectly recursive and (b) an optimized invocation has been
8139  // deoptimized so that we are currently in an unoptimized activation.
8140  // Check for optimized activations of this function.
8141  JavaScriptFrameIterator it(isolate);
8142  while (succeeded && !it.done()) {
8143  JavaScriptFrame* frame = it.frame();
8144  succeeded = !frame->is_optimized() || frame->function() != *function;
8145  it.Advance();
8146  }
8147  }
8148 
8149  BailoutId ast_id = BailoutId::None();
8150  if (succeeded) {
8151  // The top JS function is this one, the PC is somewhere in the
8152  // unoptimized code.
8153  JavaScriptFrameIterator it(isolate);
8154  JavaScriptFrame* frame = it.frame();
8155  ASSERT(frame->function() == *function);
8156  ASSERT(frame->LookupCode() == *unoptimized);
8157  ASSERT(unoptimized->contains(frame->pc()));
8158 
8159  // Use linear search of the unoptimized code's stack check table to find
8160  // the AST id matching the PC.
8161  Address start = unoptimized->instruction_start();
8162  unsigned target_pc_offset = static_cast<unsigned>(frame->pc() - start);
8163  Address table_cursor = start + unoptimized->stack_check_table_offset();
8164  uint32_t table_length = Memory::uint32_at(table_cursor);
8165  table_cursor += kIntSize;
8166  for (unsigned i = 0; i < table_length; ++i) {
8167  // Table entries are (AST id, pc offset) pairs.
8168  uint32_t pc_offset = Memory::uint32_at(table_cursor + kIntSize);
8169  if (pc_offset == target_pc_offset) {
8170  ast_id = BailoutId(static_cast<int>(Memory::uint32_at(table_cursor)));
8171  break;
8172  }
8173  table_cursor += 2 * kIntSize;
8174  }
8175  ASSERT(!ast_id.IsNone());
8176  if (FLAG_trace_osr) {
8177  PrintF("[replacing on-stack at AST id %d in ", ast_id.ToInt());
8178  function->PrintName();
8179  PrintF("]\n");
8180  }
8181 
8182  // Try to compile the optimized code. A true return value from
8183  // CompileOptimized means that compilation succeeded, not necessarily
8184  // that optimization succeeded.
8185  if (JSFunction::CompileOptimized(function, ast_id, CLEAR_EXCEPTION) &&
8186  function->IsOptimized()) {
8188  function->code()->deoptimization_data());
8189  if (data->OsrPcOffset()->value() >= 0) {
8190  if (FLAG_trace_osr) {
8191  PrintF("[on-stack replacement offset %d in optimized code]\n",
8192  data->OsrPcOffset()->value());
8193  }
8194  ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id);
8195  } else {
8196  // We may never generate the desired OSR entry if we emit an
8197  // early deoptimize.
8198  succeeded = false;
8199  }
8200  } else {
8201  succeeded = false;
8202  }
8203  }
8204 
8205  // Revert to the original stack checks in the original unoptimized code.
8206  if (FLAG_trace_osr) {
8207  PrintF("[restoring original stack checks in ");
8208  function->PrintName();
8209  PrintF("]\n");
8210  }
8211  Handle<Code> check_code;
8212  if (FLAG_count_based_interrupts) {
8213  InterruptStub interrupt_stub;
8214  check_code = interrupt_stub.GetCode();
8215  } else // NOLINT
8216  { // NOLINT
8217  StackCheckStub check_stub;
8218  check_code = check_stub.GetCode();
8219  }
8220  Handle<Code> replacement_code = isolate->builtins()->OnStackReplacement();
8221  Deoptimizer::RevertStackCheckCode(*unoptimized,
8222  *check_code,
8223  *replacement_code);
8224 
8225  // Allow OSR only at nesting level zero again.
8226  unoptimized->set_allow_osr_at_loop_nesting_level(0);
8227 
8228  // If the optimization attempt succeeded, return the AST id tagged as a
8229  // smi. This tells the builtin that we need to translate the unoptimized
8230  // frame to an optimized one.
8231  if (succeeded) {
8232  ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION);
8233  return Smi::FromInt(ast_id.ToInt());
8234  } else {
8235  if (function->IsMarkedForLazyRecompilation()) {
8236  function->ReplaceCode(function->shared()->code());
8237  }
8238  return Smi::FromInt(-1);
8239  }
8240 }
8241 
8242 
8243 RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckIsBootstrapping) {
8244  RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8245  return isolate->heap()->undefined_value();
8246 }
8247 
8248 
8249 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetRootNaN) {
8250  RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8251  return isolate->heap()->nan_value();
8252 }
8253 
8254 
8255 RUNTIME_FUNCTION(MaybeObject*, Runtime_Call) {
8256  HandleScope scope(isolate);
8257  ASSERT(args.length() >= 2);
8258  int argc = args.length() - 2;
8259  CONVERT_ARG_CHECKED(JSReceiver, fun, argc + 1);
8260  Object* receiver = args[0];
8261 
8262  // If there are too many arguments, allocate argv via malloc.
8263  const int argv_small_size = 10;
8264  Handle<Object> argv_small_buffer[argv_small_size];
8265  SmartArrayPointer<Handle<Object> > argv_large_buffer;
8266  Handle<Object>* argv = argv_small_buffer;
8267  if (argc > argv_small_size) {
8268  argv = new Handle<Object>[argc];
8269  if (argv == NULL) return isolate->StackOverflow();
8270  argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8271  }
8272 
8273  for (int i = 0; i < argc; ++i) {
8274  MaybeObject* maybe = args[1 + i];
8275  Object* object;
8276  if (!maybe->To<Object>(&object)) return maybe;
8277  argv[i] = Handle<Object>(object);
8278  }
8279 
8280  bool threw;
8281  Handle<JSReceiver> hfun(fun);
8282  Handle<Object> hreceiver(receiver);
8283  Handle<Object> result =
8284  Execution::Call(hfun, hreceiver, argc, argv, &threw, true);
8285 
8286  if (threw) return Failure::Exception();
8287  return *result;
8288 }
8289 
8290 
8291 RUNTIME_FUNCTION(MaybeObject*, Runtime_Apply) {
8292  HandleScope scope(isolate);
8293  ASSERT(args.length() == 5);
8295  Handle<Object> receiver = args.at<Object>(1);
8296  CONVERT_ARG_HANDLE_CHECKED(JSObject, arguments, 2);
8297  CONVERT_SMI_ARG_CHECKED(offset, 3);
8298  CONVERT_SMI_ARG_CHECKED(argc, 4);
8299  ASSERT(offset >= 0);
8300  ASSERT(argc >= 0);
8301 
8302  // If there are too many arguments, allocate argv via malloc.
8303  const int argv_small_size = 10;
8304  Handle<Object> argv_small_buffer[argv_small_size];
8305  SmartArrayPointer<Handle<Object> > argv_large_buffer;
8306  Handle<Object>* argv = argv_small_buffer;
8307  if (argc > argv_small_size) {
8308  argv = new Handle<Object>[argc];
8309  if (argv == NULL) return isolate->StackOverflow();
8310  argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8311  }
8312 
8313  for (int i = 0; i < argc; ++i) {
8314  argv[i] = Object::GetElement(arguments, offset + i);
8315  }
8316 
8317  bool threw;
8318  Handle<Object> result =
8319  Execution::Call(fun, receiver, argc, argv, &threw, true);
8320 
8321  if (threw) return Failure::Exception();
8322  return *result;
8323 }
8324 
8325 
8326 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionDelegate) {
8327  HandleScope scope(isolate);
8328  ASSERT(args.length() == 1);
8329  RUNTIME_ASSERT(!args[0]->IsJSFunction());
8330  return *Execution::GetFunctionDelegate(args.at<Object>(0));
8331 }
8332 
8333 
8334 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) {
8335  HandleScope scope(isolate);
8336  ASSERT(args.length() == 1);
8337  RUNTIME_ASSERT(!args[0]->IsJSFunction());
8338  return *Execution::GetConstructorDelegate(args.at<Object>(0));
8339 }
8340 
8341 
8342 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewGlobalContext) {
8343  NoHandleAllocation ha;
8344  ASSERT(args.length() == 2);
8345 
8346  CONVERT_ARG_CHECKED(JSFunction, function, 0);
8347  CONVERT_ARG_CHECKED(ScopeInfo, scope_info, 1);
8348  Context* result;
8349  MaybeObject* maybe_result =
8350  isolate->heap()->AllocateGlobalContext(function, scope_info);
8351  if (!maybe_result->To(&result)) return maybe_result;
8352 
8353  ASSERT(function->context() == isolate->context());
8354  ASSERT(function->context()->global_object() == result->global_object());
8355  isolate->set_context(result);
8356  result->global_object()->set_global_context(result);
8357 
8358  return result; // non-failure
8359 }
8360 
8361 
8362 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewFunctionContext) {
8363  NoHandleAllocation ha;
8364  ASSERT(args.length() == 1);
8365 
8366  CONVERT_ARG_CHECKED(JSFunction, function, 0);
8367  int length = function->shared()->scope_info()->ContextLength();
8368  Context* result;
8369  MaybeObject* maybe_result =
8370  isolate->heap()->AllocateFunctionContext(length, function);
8371  if (!maybe_result->To(&result)) return maybe_result;
8372 
8373  isolate->set_context(result);
8374 
8375  return result; // non-failure
8376 }
8377 
8378 
8379 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushWithContext) {
8380  NoHandleAllocation ha;
8381  ASSERT(args.length() == 2);
8382  JSObject* extension_object;
8383  if (args[0]->IsJSObject()) {
8384  extension_object = JSObject::cast(args[0]);
8385  } else {
8386  // Convert the object to a proper JavaScript object.
8387  MaybeObject* maybe_js_object = args[0]->ToObject();
8388  if (!maybe_js_object->To(&extension_object)) {
8389  if (Failure::cast(maybe_js_object)->IsInternalError()) {
8390  HandleScope scope(isolate);
8391  Handle<Object> handle = args.at<Object>(0);
8392  Handle<Object> result =
8393  isolate->factory()->NewTypeError("with_expression",
8394  HandleVector(&handle, 1));
8395  return isolate->Throw(*result);
8396  } else {
8397  return maybe_js_object;
8398  }
8399  }
8400  }
8401 
8402  JSFunction* function;
8403  if (args[1]->IsSmi()) {
8404  // A smi sentinel indicates a context nested inside global code rather
8405  // than some function. There is a canonical empty function that can be
8406  // gotten from the native context.
8407  function = isolate->context()->native_context()->closure();
8408  } else {
8409  function = JSFunction::cast(args[1]);
8410  }
8411 
8412  Context* context;
8413  MaybeObject* maybe_context =
8414  isolate->heap()->AllocateWithContext(function,
8415  isolate->context(),
8416  extension_object);
8417  if (!maybe_context->To(&context)) return maybe_context;
8418  isolate->set_context(context);
8419  return context;
8420 }
8421 
8422 
8423 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushCatchContext) {
8424  NoHandleAllocation ha;
8425  ASSERT(args.length() == 3);
8426  String* name = String::cast(args[0]);
8427  Object* thrown_object = args[1];
8428  JSFunction* function;
8429  if (args[2]->IsSmi()) {
8430  // A smi sentinel indicates a context nested inside global code rather
8431  // than some function. There is a canonical empty function that can be
8432  // gotten from the native context.
8433  function = isolate->context()->native_context()->closure();
8434  } else {
8435  function = JSFunction::cast(args[2]);
8436  }
8437  Context* context;
8438  MaybeObject* maybe_context =
8439  isolate->heap()->AllocateCatchContext(function,
8440  isolate->context(),
8441  name,
8442  thrown_object);
8443  if (!maybe_context->To(&context)) return maybe_context;
8444  isolate->set_context(context);
8445  return context;
8446 }
8447 
8448 
8449 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushBlockContext) {
8450  NoHandleAllocation ha;
8451  ASSERT(args.length() == 2);
8452  ScopeInfo* scope_info = ScopeInfo::cast(args[0]);
8453  JSFunction* function;
8454  if (args[1]->IsSmi()) {
8455  // A smi sentinel indicates a context nested inside global code rather
8456  // than some function. There is a canonical empty function that can be
8457  // gotten from the native context.
8458  function = isolate->context()->native_context()->closure();
8459  } else {
8460  function = JSFunction::cast(args[1]);
8461  }
8462  Context* context;
8463  MaybeObject* maybe_context =
8464  isolate->heap()->AllocateBlockContext(function,
8465  isolate->context(),
8466  scope_info);
8467  if (!maybe_context->To(&context)) return maybe_context;
8468  isolate->set_context(context);
8469  return context;
8470 }
8471 
8472 
8473 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSModule) {
8474  ASSERT(args.length() == 1);
8475  Object* obj = args[0];
8476  return isolate->heap()->ToBoolean(obj->IsJSModule());
8477 }
8478 
8479 
8480 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushModuleContext) {
8481  NoHandleAllocation ha;
8482  ASSERT(args.length() == 1);
8483  CONVERT_ARG_HANDLE_CHECKED(JSModule, instance, 0);
8484 
8485  Context* context = Context::cast(instance->context());
8486  Context* previous = isolate->context();
8487  ASSERT(context->IsModuleContext());
8488  // Initialize the context links.
8489  context->set_previous(previous);
8490  context->set_closure(previous->closure());
8491  context->set_global_object(previous->global_object());
8492  isolate->set_context(context);
8493 
8494  return context;
8495 }
8496 
8497 
8498 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteContextSlot) {
8499  HandleScope scope(isolate);
8500  ASSERT(args.length() == 2);
8501 
8502  CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
8504 
8505  int index;
8506  PropertyAttributes attributes;
8508  BindingFlags binding_flags;
8509  Handle<Object> holder = context->Lookup(name,
8510  flags,
8511  &index,
8512  &attributes,
8513  &binding_flags);
8514 
8515  // If the slot was not found the result is true.
8516  if (holder.is_null()) {
8517  return isolate->heap()->true_value();
8518  }
8519 
8520  // If the slot was found in a context, it should be DONT_DELETE.
8521  if (holder->IsContext()) {
8522  return isolate->heap()->false_value();
8523  }
8524 
8525  // The slot was found in a JSObject, either a context extension object,
8526  // the global object, or the subject of a with. Try to delete it
8527  // (respecting DONT_DELETE).
8528  Handle<JSObject> object = Handle<JSObject>::cast(holder);
8529  return object->DeleteProperty(*name, JSReceiver::NORMAL_DELETION);
8530 }
8531 
8532 
8533 // A mechanism to return a pair of Object pointers in registers (if possible).
8534 // How this is achieved is calling convention-dependent.
8535 // All currently supported x86 compiles uses calling conventions that are cdecl
8536 // variants where a 64-bit value is returned in two 32-bit registers
8537 // (edx:eax on ia32, r1:r0 on ARM).
8538 // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax.
8539 // In Win64 calling convention, a struct of two pointers is returned in memory,
8540 // allocated by the caller, and passed as a pointer in a hidden first parameter.
8541 #ifdef V8_HOST_ARCH_64_BIT
8542 struct ObjectPair {
8543  MaybeObject* x;
8544  MaybeObject* y;
8545 };
8546 
8547 static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
8548  ObjectPair result = {x, y};
8549  // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
8550  // In Win64 they are assigned to a hidden first argument.
8551  return result;
8552 }
8553 #else
8554 typedef uint64_t ObjectPair;
8555 static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
8556  return reinterpret_cast<uint32_t>(x) |
8557  (reinterpret_cast<ObjectPair>(y) << 32);
8558 }
8559 #endif
8560 
8561 
8562 static inline MaybeObject* Unhole(Heap* heap,
8563  MaybeObject* x,
8564  PropertyAttributes attributes) {
8565  ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
8566  USE(attributes);
8567  return x->IsTheHole() ? heap->undefined_value() : x;
8568 }
8569 
8570 
8571 static Object* ComputeReceiverForNonGlobal(Isolate* isolate,
8572  JSObject* holder) {
8573  ASSERT(!holder->IsGlobalObject());
8574  Context* top = isolate->context();
8575  // Get the context extension function.
8576  JSFunction* context_extension_function =
8577  top->native_context()->context_extension_function();
8578  // If the holder isn't a context extension object, we just return it
8579  // as the receiver. This allows arguments objects to be used as
8580  // receivers, but only if they are put in the context scope chain
8581  // explicitly via a with-statement.
8582  Object* constructor = holder->map()->constructor();
8583  if (constructor != context_extension_function) return holder;
8584  // Fall back to using the global object as the implicit receiver if
8585  // the property turns out to be a local variable allocated in a
8586  // context extension object - introduced via eval. Implicit global
8587  // receivers are indicated with the hole value.
8588  return isolate->heap()->the_hole_value();
8589 }
8590 
8591 
8592 static ObjectPair LoadContextSlotHelper(Arguments args,
8593  Isolate* isolate,
8594  bool throw_error) {
8595  HandleScope scope(isolate);
8596  ASSERT_EQ(2, args.length());
8597 
8598  if (!args[0]->IsContext() || !args[1]->IsString()) {
8599  return MakePair(isolate->ThrowIllegalOperation(), NULL);
8600  }
8601  Handle<Context> context = args.at<Context>(0);
8602  Handle<String> name = args.at<String>(1);
8603 
8604  int index;
8605  PropertyAttributes attributes;
8607  BindingFlags binding_flags;
8608  Handle<Object> holder = context->Lookup(name,
8609  flags,
8610  &index,
8611  &attributes,
8612  &binding_flags);
8613 
8614  // If the index is non-negative, the slot has been found in a context.
8615  if (index >= 0) {
8616  ASSERT(holder->IsContext());
8617  // If the "property" we were looking for is a local variable, the
8618  // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
8619  //
8620  // Use the hole as the receiver to signal that the receiver is implicit
8621  // and that the global receiver should be used (as distinguished from an
8622  // explicit receiver that happens to be a global object).
8623  Handle<Object> receiver = isolate->factory()->the_hole_value();
8624  Object* value = Context::cast(*holder)->get(index);
8625  // Check for uninitialized bindings.
8626  switch (binding_flags) {
8629  if (value->IsTheHole()) {
8630  Handle<Object> reference_error =
8631  isolate->factory()->NewReferenceError("not_defined",
8632  HandleVector(&name, 1));
8633  return MakePair(isolate->Throw(*reference_error), NULL);
8634  }
8635  // FALLTHROUGH
8639  ASSERT(!value->IsTheHole());
8640  return MakePair(value, *receiver);
8642  return MakePair(Unhole(isolate->heap(), value, attributes), *receiver);
8643  case MISSING_BINDING:
8644  UNREACHABLE();
8645  return MakePair(NULL, NULL);
8646  }
8647  }
8648 
8649  // Otherwise, if the slot was found the holder is a context extension
8650  // object, subject of a with, or a global object. We read the named
8651  // property from it.
8652  if (!holder.is_null()) {
8653  Handle<JSObject> object = Handle<JSObject>::cast(holder);
8654  ASSERT(object->HasProperty(*name));
8655  // GetProperty below can cause GC.
8656  Handle<Object> receiver_handle(object->IsGlobalObject()
8657  ? GlobalObject::cast(*object)->global_receiver()
8658  : ComputeReceiverForNonGlobal(isolate, *object));
8659 
8660  // No need to unhole the value here. This is taken care of by the
8661  // GetProperty function.
8662  MaybeObject* value = object->GetProperty(*name);
8663  return MakePair(value, *receiver_handle);
8664  }
8665 
8666  if (throw_error) {
8667  // The property doesn't exist - throw exception.
8668  Handle<Object> reference_error =
8669  isolate->factory()->NewReferenceError("not_defined",
8670  HandleVector(&name, 1));
8671  return MakePair(isolate->Throw(*reference_error), NULL);
8672  } else {
8673  // The property doesn't exist - return undefined.
8674  return MakePair(isolate->heap()->undefined_value(),
8675  isolate->heap()->undefined_value());
8676  }
8677 }
8678 
8679 
8680 RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlot) {
8681  return LoadContextSlotHelper(args, isolate, true);
8682 }
8683 
8684 
8685 RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlotNoReferenceError) {
8686  return LoadContextSlotHelper(args, isolate, false);
8687 }
8688 
8689 
8690 RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreContextSlot) {
8691  HandleScope scope(isolate);
8692  ASSERT(args.length() == 4);
8693 
8694  Handle<Object> value(args[0], isolate);
8695  CONVERT_ARG_HANDLE_CHECKED(Context, context, 1);
8697  CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
8698  StrictModeFlag strict_mode = (language_mode == CLASSIC_MODE)
8700 
8701  int index;
8702  PropertyAttributes attributes;
8704  BindingFlags binding_flags;
8705  Handle<Object> holder = context->Lookup(name,
8706  flags,
8707  &index,
8708  &attributes,
8709  &binding_flags);
8710 
8711  if (index >= 0) {
8712  // The property was found in a context slot.
8713  Handle<Context> context = Handle<Context>::cast(holder);
8714  if (binding_flags == MUTABLE_CHECK_INITIALIZED &&
8715  context->get(index)->IsTheHole()) {
8716  Handle<Object> error =
8717  isolate->factory()->NewReferenceError("not_defined",
8718  HandleVector(&name, 1));
8719  return isolate->Throw(*error);
8720  }
8721  // Ignore if read_only variable.
8722  if ((attributes & READ_ONLY) == 0) {
8723  // Context is a fixed array and set cannot fail.
8724  context->set(index, *value);
8725  } else if (strict_mode == kStrictMode) {
8726  // Setting read only property in strict mode.
8727  Handle<Object> error =
8728  isolate->factory()->NewTypeError("strict_cannot_assign",
8729  HandleVector(&name, 1));
8730  return isolate->Throw(*error);
8731  }
8732  return *value;
8733  }
8734 
8735  // Slow case: The property is not in a context slot. It is either in a
8736  // context extension object, a property of the subject of a with, or a
8737  // property of the global object.
8738  Handle<JSObject> object;
8739 
8740  if (!holder.is_null()) {
8741  // The property exists on the holder.
8742  object = Handle<JSObject>::cast(holder);
8743  } else {
8744  // The property was not found.
8745  ASSERT(attributes == ABSENT);
8746 
8747  if (strict_mode == kStrictMode) {
8748  // Throw in strict mode (assignment to undefined variable).
8749  Handle<Object> error =
8750  isolate->factory()->NewReferenceError(
8751  "not_defined", HandleVector(&name, 1));
8752  return isolate->Throw(*error);
8753  }
8754  // In non-strict mode, the property is added to the global object.
8755  attributes = NONE;
8756  object = Handle<JSObject>(isolate->context()->global_object());
8757  }
8758 
8759  // Set the property if it's not read only or doesn't yet exist.
8760  if ((attributes & READ_ONLY) == 0 ||
8761  (object->GetLocalPropertyAttribute(*name) == ABSENT)) {
8763  isolate,
8764  JSReceiver::SetProperty(object, name, value, NONE, strict_mode));
8765  } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) {
8766  // Setting read only property in strict mode.
8767  Handle<Object> error =
8768  isolate->factory()->NewTypeError(
8769  "strict_cannot_assign", HandleVector(&name, 1));
8770  return isolate->Throw(*error);
8771  }
8772  return *value;
8773 }
8774 
8775 
8776 RUNTIME_FUNCTION(MaybeObject*, Runtime_Throw) {
8777  HandleScope scope(isolate);
8778  ASSERT(args.length() == 1);
8779 
8780  return isolate->Throw(args[0]);
8781 }
8782 
8783 
8784 RUNTIME_FUNCTION(MaybeObject*, Runtime_ReThrow) {
8785  HandleScope scope(isolate);
8786  ASSERT(args.length() == 1);
8787 
8788  return isolate->ReThrow(args[0]);
8789 }
8790 
8791 
8792 RUNTIME_FUNCTION(MaybeObject*, Runtime_PromoteScheduledException) {
8793  ASSERT_EQ(0, args.length());
8794  return isolate->PromoteScheduledException();
8795 }
8796 
8797 
8798 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowReferenceError) {
8799  HandleScope scope(isolate);
8800  ASSERT(args.length() == 1);
8801 
8802  Handle<Object> name(args[0], isolate);
8803  Handle<Object> reference_error =
8804  isolate->factory()->NewReferenceError("not_defined",
8805  HandleVector(&name, 1));
8806  return isolate->Throw(*reference_error);
8807 }
8808 
8809 
8810 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowNotDateError) {
8811  HandleScope scope(isolate);
8812  ASSERT(args.length() == 0);
8813  return isolate->Throw(*isolate->factory()->NewTypeError(
8814  "not_date_object", HandleVector<Object>(NULL, 0)));
8815 }
8816 
8817 
8818 
8819 RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) {
8820  ASSERT(args.length() == 0);
8821 
8822  // First check if this is a real stack overflow.
8823  if (isolate->stack_guard()->IsStackOverflow()) {
8824  NoHandleAllocation na;
8825  return isolate->StackOverflow();
8826  }
8827 
8828  return Execution::HandleStackGuardInterrupt(isolate);
8829 }
8830 
8831 
8832 RUNTIME_FUNCTION(MaybeObject*, Runtime_Interrupt) {
8833  ASSERT(args.length() == 0);
8834  return Execution::HandleStackGuardInterrupt(isolate);
8835 }
8836 
8837 
8838 static int StackSize() {
8839  int n = 0;
8840  for (JavaScriptFrameIterator it; !it.done(); it.Advance()) n++;
8841  return n;
8842 }
8843 
8844 
8845 static void PrintTransition(Object* result) {
8846  // indentation
8847  { const int nmax = 80;
8848  int n = StackSize();
8849  if (n <= nmax)
8850  PrintF("%4d:%*s", n, n, "");
8851  else
8852  PrintF("%4d:%*s", n, nmax, "...");
8853  }
8854 
8855  if (result == NULL) {
8856  JavaScriptFrame::PrintTop(stdout, true, false);
8857  PrintF(" {\n");
8858  } else {
8859  // function result
8860  PrintF("} -> ");
8861  result->ShortPrint();
8862  PrintF("\n");
8863  }
8864 }
8865 
8866 
8867 RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceEnter) {
8868  ASSERT(args.length() == 0);
8869  NoHandleAllocation ha;
8870  PrintTransition(NULL);
8871  return isolate->heap()->undefined_value();
8872 }
8873 
8874 
8875 RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceExit) {
8876  NoHandleAllocation ha;
8877  PrintTransition(args[0]);
8878  return args[0]; // return TOS
8879 }
8880 
8881 
8882 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrint) {
8883  NoHandleAllocation ha;
8884  ASSERT(args.length() == 1);
8885 
8886 #ifdef DEBUG
8887  if (args[0]->IsString()) {
8888  // If we have a string, assume it's a code "marker"
8889  // and print some interesting cpu debugging info.
8890  JavaScriptFrameIterator it(isolate);
8891  JavaScriptFrame* frame = it.frame();
8892  PrintF("fp = %p, sp = %p, caller_sp = %p: ",
8893  frame->fp(), frame->sp(), frame->caller_sp());
8894  } else {
8895  PrintF("DebugPrint: ");
8896  }
8897  args[0]->Print();
8898  if (args[0]->IsHeapObject()) {
8899  PrintF("\n");
8900  HeapObject::cast(args[0])->map()->Print();
8901  }
8902 #else
8903  // ShortPrint is available in release mode. Print is not.
8904  args[0]->ShortPrint();
8905 #endif
8906  PrintF("\n");
8907  Flush();
8908 
8909  return args[0]; // return TOS
8910 }
8911 
8912 
8913 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugTrace) {
8914  ASSERT(args.length() == 0);
8915  NoHandleAllocation ha;
8916  isolate->PrintStack();
8917  return isolate->heap()->undefined_value();
8918 }
8919 
8920 
8921 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateCurrentTime) {
8922  NoHandleAllocation ha;
8923  ASSERT(args.length() == 0);
8924 
8925  // According to ECMA-262, section 15.9.1, page 117, the precision of
8926  // the number in a Date object representing a particular instant in
8927  // time is milliseconds. Therefore, we floor the result of getting
8928  // the OS time.
8929  double millis = floor(OS::TimeCurrentMillis());
8930  return isolate->heap()->NumberFromDouble(millis);
8931 }
8932 
8933 
8934 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateParseString) {
8935  HandleScope scope(isolate);
8936  ASSERT(args.length() == 2);
8937 
8939  FlattenString(str);
8940 
8941  CONVERT_ARG_HANDLE_CHECKED(JSArray, output, 1);
8942 
8943  MaybeObject* maybe_result_array =
8944  output->EnsureCanContainHeapObjectElements();
8945  if (maybe_result_array->IsFailure()) return maybe_result_array;
8946  RUNTIME_ASSERT(output->HasFastObjectElements());
8947 
8948  AssertNoAllocation no_allocation;
8949 
8950  FixedArray* output_array = FixedArray::cast(output->elements());
8951  RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
8952  bool result;
8953  String::FlatContent str_content = str->GetFlatContent();
8954  if (str_content.IsAscii()) {
8955  result = DateParser::Parse(str_content.ToAsciiVector(),
8956  output_array,
8957  isolate->unicode_cache());
8958  } else {
8959  ASSERT(str_content.IsTwoByte());
8960  result = DateParser::Parse(str_content.ToUC16Vector(),
8961  output_array,
8962  isolate->unicode_cache());
8963  }
8964 
8965  if (result) {
8966  return *output;
8967  } else {
8968  return isolate->heap()->null_value();
8969  }
8970 }
8971 
8972 
8973 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateLocalTimezone) {
8974  NoHandleAllocation ha;
8975  ASSERT(args.length() == 1);
8976 
8978  int64_t time = isolate->date_cache()->EquivalentTime(static_cast<int64_t>(x));
8979  const char* zone = OS::LocalTimezone(static_cast<double>(time));
8980  return isolate->heap()->AllocateStringFromUtf8(CStrVector(zone));
8981 }
8982 
8983 
8984 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateToUTC) {
8985  NoHandleAllocation ha;
8986  ASSERT(args.length() == 1);
8987 
8989  int64_t time = isolate->date_cache()->ToUTC(static_cast<int64_t>(x));
8990 
8991  return isolate->heap()->NumberFromDouble(static_cast<double>(time));
8992 }
8993 
8994 
8995 RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalReceiver) {
8996  ASSERT(args.length() == 1);
8997  Object* global = args[0];
8998  if (!global->IsJSGlobalObject()) return isolate->heap()->null_value();
8999  return JSGlobalObject::cast(global)->global_receiver();
9000 }
9001 
9002 
9003 RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) {
9004  HandleScope scope(isolate);
9005  ASSERT_EQ(1, args.length());
9006  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9007 
9008  Zone* zone = isolate->runtime_zone();
9009  source = Handle<String>(source->TryFlattenGetString());
9010  // Optimized fast case where we only have ASCII characters.
9011  Handle<Object> result;
9012  if (source->IsSeqAsciiString()) {
9013  result = JsonParser<true>::Parse(source, zone);
9014  } else {
9015  result = JsonParser<false>::Parse(source, zone);
9016  }
9017  if (result.is_null()) {
9018  // Syntax error or stack overflow in scanner.
9019  ASSERT(isolate->has_pending_exception());
9020  return Failure::Exception();
9021  }
9022  return *result;
9023 }
9024 
9025 
9027  Handle<Context> context) {
9028  ASSERT(context->allow_code_gen_from_strings()->IsFalse());
9029  // Check with callback if set.
9031  isolate->allow_code_gen_callback();
9032  if (callback == NULL) {
9033  // No callback set and code generation disallowed.
9034  return false;
9035  } else {
9036  // Callback set. Let it decide if code generation is allowed.
9037  VMState state(isolate, EXTERNAL);
9038  return callback(v8::Utils::ToLocal(context));
9039  }
9040 }
9041 
9042 
9043 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
9044  HandleScope scope(isolate);
9045  ASSERT_EQ(1, args.length());
9046  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9047 
9048  // Extract native context.
9049  Handle<Context> context(isolate->context()->native_context());
9050 
9051  // Check if native context allows code generation from
9052  // strings. Throw an exception if it doesn't.
9053  if (context->allow_code_gen_from_strings()->IsFalse() &&
9054  !CodeGenerationFromStringsAllowed(isolate, context)) {
9055  Handle<Object> error_message =
9056  context->ErrorMessageForCodeGenerationFromStrings();
9057  return isolate->Throw(*isolate->factory()->NewEvalError(
9058  "code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
9059  }
9060 
9061  // Compile source string in the native context.
9063  source, context, true, CLASSIC_MODE, RelocInfo::kNoPosition);
9064  if (shared.is_null()) return Failure::Exception();
9065  Handle<JSFunction> fun =
9066  isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
9067  context,
9068  NOT_TENURED);
9069  return *fun;
9070 }
9071 
9072 
9073 static ObjectPair CompileGlobalEval(Isolate* isolate,
9074  Handle<String> source,
9075  Handle<Object> receiver,
9076  LanguageMode language_mode,
9077  int scope_position) {
9078  Handle<Context> context = Handle<Context>(isolate->context());
9079  Handle<Context> native_context = Handle<Context>(context->native_context());
9080 
9081  // Check if native context allows code generation from
9082  // strings. Throw an exception if it doesn't.
9083  if (native_context->allow_code_gen_from_strings()->IsFalse() &&
9084  !CodeGenerationFromStringsAllowed(isolate, native_context)) {
9085  Handle<Object> error_message =
9086  native_context->ErrorMessageForCodeGenerationFromStrings();
9087  isolate->Throw(*isolate->factory()->NewEvalError(
9088  "code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
9089  return MakePair(Failure::Exception(), NULL);
9090  }
9091 
9092  // Deal with a normal eval call with a string argument. Compile it
9093  // and return the compiled function bound in the local context.
9094  Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
9095  source,
9096  Handle<Context>(isolate->context()),
9097  context->IsNativeContext(),
9098  language_mode,
9099  scope_position);
9100  if (shared.is_null()) return MakePair(Failure::Exception(), NULL);
9101  Handle<JSFunction> compiled =
9102  isolate->factory()->NewFunctionFromSharedFunctionInfo(
9103  shared, context, NOT_TENURED);
9104  return MakePair(*compiled, *receiver);
9105 }
9106 
9107 
9108 RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
9109  ASSERT(args.length() == 5);
9110 
9111  HandleScope scope(isolate);
9112  Handle<Object> callee = args.at<Object>(0);
9113 
9114  // If "eval" didn't refer to the original GlobalEval, it's not a
9115  // direct call to eval.
9116  // (And even if it is, but the first argument isn't a string, just let
9117  // execution default to an indirect call to eval, which will also return
9118  // the first argument without doing anything).
9119  if (*callee != isolate->native_context()->global_eval_fun() ||
9120  !args[1]->IsString()) {
9121  return MakePair(*callee, isolate->heap()->the_hole_value());
9122  }
9123 
9124  CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
9125  ASSERT(args[4]->IsSmi());
9126  return CompileGlobalEval(isolate,
9127  args.at<String>(1),
9128  args.at<Object>(2),
9129  language_mode,
9130  args.smi_at(4));
9131 }
9132 
9133 
9134 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNewFunctionAttributes) {
9135  // This utility adjusts the property attributes for newly created Function
9136  // object ("new Function(...)") by changing the map.
9137  // All it does is changing the prototype property to enumerable
9138  // as specified in ECMA262, 15.3.5.2.
9139  HandleScope scope(isolate);
9140  ASSERT(args.length() == 1);
9142 
9143  Handle<Map> map = func->shared()->is_classic_mode()
9144  ? isolate->function_instance_map()
9145  : isolate->strict_mode_function_instance_map();
9146 
9147  ASSERT(func->map()->instance_type() == map->instance_type());
9148  ASSERT(func->map()->instance_size() == map->instance_size());
9149  func->set_map(*map);
9150  return *func;
9151 }
9152 
9153 
9154 RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInNewSpace) {
9155  // Allocate a block of memory in NewSpace (filled with a filler).
9156  // Use as fallback for allocation in generated code when NewSpace
9157  // is full.
9158  ASSERT(args.length() == 1);
9159  CONVERT_ARG_HANDLE_CHECKED(Smi, size_smi, 0);
9160  int size = size_smi->value();
9162  RUNTIME_ASSERT(size > 0);
9163  Heap* heap = isolate->heap();
9164  const int kMinFreeNewSpaceAfterGC = heap->InitialSemiSpaceSize() * 3/4;
9165  RUNTIME_ASSERT(size <= kMinFreeNewSpaceAfterGC);
9166  Object* allocation;
9167  { MaybeObject* maybe_allocation = heap->new_space()->AllocateRaw(size);
9168  if (maybe_allocation->ToObject(&allocation)) {
9169  heap->CreateFillerObjectAt(HeapObject::cast(allocation)->address(), size);
9170  }
9171  return maybe_allocation;
9172  }
9173 }
9174 
9175 
9176 // Push an object unto an array of objects if it is not already in the
9177 // array. Returns true if the element was pushed on the stack and
9178 // false otherwise.
9179 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) {
9180  ASSERT(args.length() == 2);
9181  CONVERT_ARG_CHECKED(JSArray, array, 0);
9182  CONVERT_ARG_CHECKED(JSObject, element, 1);
9183  RUNTIME_ASSERT(array->HasFastSmiOrObjectElements());
9184  int length = Smi::cast(array->length())->value();
9185  FixedArray* elements = FixedArray::cast(array->elements());
9186  for (int i = 0; i < length; i++) {
9187  if (elements->get(i) == element) return isolate->heap()->false_value();
9188  }
9189  Object* obj;
9190  // Strict not needed. Used for cycle detection in Array join implementation.
9191  { MaybeObject* maybe_obj =
9192  array->SetFastElement(length, element, kNonStrictMode, true);
9193  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9194  }
9195  return isolate->heap()->true_value();
9196 }
9197 
9198 
9211  public:
9213  Handle<FixedArray> storage,
9214  bool fast_elements) :
9215  isolate_(isolate),
9216  storage_(Handle<FixedArray>::cast(
9217  isolate->global_handles()->Create(*storage))),
9218  index_offset_(0u),
9219  fast_elements_(fast_elements) { }
9220 
9222  clear_storage();
9223  }
9224 
9225  void visit(uint32_t i, Handle<Object> elm) {
9226  if (i >= JSObject::kMaxElementCount - index_offset_) return;
9227  uint32_t index = index_offset_ + i;
9228 
9229  if (fast_elements_) {
9230  if (index < static_cast<uint32_t>(storage_->length())) {
9231  storage_->set(index, *elm);
9232  return;
9233  }
9234  // Our initial estimate of length was foiled, possibly by
9235  // getters on the arrays increasing the length of later arrays
9236  // during iteration.
9237  // This shouldn't happen in anything but pathological cases.
9238  SetDictionaryMode(index);
9239  // Fall-through to dictionary mode.
9240  }
9241  ASSERT(!fast_elements_);
9243  SeededNumberDictionary::cast(*storage_));
9245  isolate_->factory()->DictionaryAtNumberPut(dict, index, elm);
9246  if (!result.is_identical_to(dict)) {
9247  // Dictionary needed to grow.
9248  clear_storage();
9249  set_storage(*result);
9250  }
9251 }
9252 
9253  void increase_index_offset(uint32_t delta) {
9254  if (JSObject::kMaxElementCount - index_offset_ < delta) {
9255  index_offset_ = JSObject::kMaxElementCount;
9256  } else {
9257  index_offset_ += delta;
9258  }
9259  }
9260 
9262  Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
9263  Handle<Object> length =
9264  isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
9265  Handle<Map> map;
9266  if (fast_elements_) {
9267  map = isolate_->factory()->GetElementsTransitionMap(array,
9269  } else {
9270  map = isolate_->factory()->GetElementsTransitionMap(array,
9272  }
9273  array->set_map(*map);
9274  array->set_length(*length);
9275  array->set_elements(*storage_);
9276  return array;
9277  }
9278 
9279  private:
9280  // Convert storage to dictionary mode.
9281  void SetDictionaryMode(uint32_t index) {
9282  ASSERT(fast_elements_);
9283  Handle<FixedArray> current_storage(*storage_);
9284  Handle<SeededNumberDictionary> slow_storage(
9285  isolate_->factory()->NewSeededNumberDictionary(
9286  current_storage->length()));
9287  uint32_t current_length = static_cast<uint32_t>(current_storage->length());
9288  for (uint32_t i = 0; i < current_length; i++) {
9289  HandleScope loop_scope;
9290  Handle<Object> element(current_storage->get(i));
9291  if (!element->IsTheHole()) {
9292  Handle<SeededNumberDictionary> new_storage =
9293  isolate_->factory()->DictionaryAtNumberPut(slow_storage, i, element);
9294  if (!new_storage.is_identical_to(slow_storage)) {
9295  slow_storage = loop_scope.CloseAndEscape(new_storage);
9296  }
9297  }
9298  }
9299  clear_storage();
9300  set_storage(*slow_storage);
9301  fast_elements_ = false;
9302  }
9303 
9304  inline void clear_storage() {
9305  isolate_->global_handles()->Destroy(
9306  Handle<Object>::cast(storage_).location());
9307  }
9308 
9309  inline void set_storage(FixedArray* storage) {
9310  storage_ = Handle<FixedArray>::cast(
9311  isolate_->global_handles()->Create(storage));
9312  }
9313 
9314  Isolate* isolate_;
9315  Handle<FixedArray> storage_; // Always a global handle.
9316  // Index after last seen index. Always less than or equal to
9317  // JSObject::kMaxElementCount.
9318  uint32_t index_offset_;
9319  bool fast_elements_;
9320 };
9321 
9322 
9323 static uint32_t EstimateElementCount(Handle<JSArray> array) {
9324  uint32_t length = static_cast<uint32_t>(array->length()->Number());
9325  int element_count = 0;
9326  switch (array->GetElementsKind()) {
9327  case FAST_SMI_ELEMENTS:
9329  case FAST_ELEMENTS:
9330  case FAST_HOLEY_ELEMENTS: {
9331  // Fast elements can't have lengths that are not representable by
9332  // a 32-bit signed integer.
9333  ASSERT(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
9334  int fast_length = static_cast<int>(length);
9335  Handle<FixedArray> elements(FixedArray::cast(array->elements()));
9336  for (int i = 0; i < fast_length; i++) {
9337  if (!elements->get(i)->IsTheHole()) element_count++;
9338  }
9339  break;
9340  }
9341  case FAST_DOUBLE_ELEMENTS:
9343  // TODO(1810): Decide if it's worthwhile to implement this.
9344  UNREACHABLE();
9345  break;
9346  case DICTIONARY_ELEMENTS: {
9347  Handle<SeededNumberDictionary> dictionary(
9348  SeededNumberDictionary::cast(array->elements()));
9349  int capacity = dictionary->Capacity();
9350  for (int i = 0; i < capacity; i++) {
9351  Handle<Object> key(dictionary->KeyAt(i));
9352  if (dictionary->IsKey(*key)) {
9353  element_count++;
9354  }
9355  }
9356  break;
9357  }
9363  case EXTERNAL_INT_ELEMENTS:
9368  // External arrays are always dense.
9369  return length;
9370  }
9371  // As an estimate, we assume that the prototype doesn't contain any
9372  // inherited elements.
9373  return element_count;
9374 }
9375 
9376 
9377 
9378 template<class ExternalArrayClass, class ElementType>
9379 static void IterateExternalArrayElements(Isolate* isolate,
9380  Handle<JSObject> receiver,
9381  bool elements_are_ints,
9382  bool elements_are_guaranteed_smis,
9383  ArrayConcatVisitor* visitor) {
9384  Handle<ExternalArrayClass> array(
9385  ExternalArrayClass::cast(receiver->elements()));
9386  uint32_t len = static_cast<uint32_t>(array->length());
9387 
9388  ASSERT(visitor != NULL);
9389  if (elements_are_ints) {
9390  if (elements_are_guaranteed_smis) {
9391  for (uint32_t j = 0; j < len; j++) {
9392  HandleScope loop_scope;
9393  Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get_scalar(j))));
9394  visitor->visit(j, e);
9395  }
9396  } else {
9397  for (uint32_t j = 0; j < len; j++) {
9398  HandleScope loop_scope;
9399  int64_t val = static_cast<int64_t>(array->get_scalar(j));
9400  if (Smi::IsValid(static_cast<intptr_t>(val))) {
9401  Handle<Smi> e(Smi::FromInt(static_cast<int>(val)));
9402  visitor->visit(j, e);
9403  } else {
9404  Handle<Object> e =
9405  isolate->factory()->NewNumber(static_cast<ElementType>(val));
9406  visitor->visit(j, e);
9407  }
9408  }
9409  }
9410  } else {
9411  for (uint32_t j = 0; j < len; j++) {
9412  HandleScope loop_scope(isolate);
9413  Handle<Object> e = isolate->factory()->NewNumber(array->get_scalar(j));
9414  visitor->visit(j, e);
9415  }
9416  }
9417 }
9418 
9419 
9420 // Used for sorting indices in a List<uint32_t>.
9421 static int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
9422  uint32_t a = *ap;
9423  uint32_t b = *bp;
9424  return (a == b) ? 0 : (a < b) ? -1 : 1;
9425 }
9426 
9427 
9428 static void CollectElementIndices(Handle<JSObject> object,
9429  uint32_t range,
9430  List<uint32_t>* indices) {
9431  ElementsKind kind = object->GetElementsKind();
9432  switch (kind) {
9433  case FAST_SMI_ELEMENTS:
9434  case FAST_ELEMENTS:
9436  case FAST_HOLEY_ELEMENTS: {
9437  Handle<FixedArray> elements(FixedArray::cast(object->elements()));
9438  uint32_t length = static_cast<uint32_t>(elements->length());
9439  if (range < length) length = range;
9440  for (uint32_t i = 0; i < length; i++) {
9441  if (!elements->get(i)->IsTheHole()) {
9442  indices->Add(i);
9443  }
9444  }
9445  break;
9446  }
9448  case FAST_DOUBLE_ELEMENTS: {
9449  // TODO(1810): Decide if it's worthwhile to implement this.
9450  UNREACHABLE();
9451  break;
9452  }
9453  case DICTIONARY_ELEMENTS: {
9454  Handle<SeededNumberDictionary> dict(
9455  SeededNumberDictionary::cast(object->elements()));
9456  uint32_t capacity = dict->Capacity();
9457  for (uint32_t j = 0; j < capacity; j++) {
9458  HandleScope loop_scope;
9459  Handle<Object> k(dict->KeyAt(j));
9460  if (dict->IsKey(*k)) {
9461  ASSERT(k->IsNumber());
9462  uint32_t index = static_cast<uint32_t>(k->Number());
9463  if (index < range) {
9464  indices->Add(index);
9465  }
9466  }
9467  }
9468  break;
9469  }
9470  default: {
9471  int dense_elements_length;
9472  switch (kind) {
9473  case EXTERNAL_PIXEL_ELEMENTS: {
9474  dense_elements_length =
9475  ExternalPixelArray::cast(object->elements())->length();
9476  break;
9477  }
9478  case EXTERNAL_BYTE_ELEMENTS: {
9479  dense_elements_length =
9480  ExternalByteArray::cast(object->elements())->length();
9481  break;
9482  }
9484  dense_elements_length =
9485  ExternalUnsignedByteArray::cast(object->elements())->length();
9486  break;
9487  }
9488  case EXTERNAL_SHORT_ELEMENTS: {
9489  dense_elements_length =
9490  ExternalShortArray::cast(object->elements())->length();
9491  break;
9492  }
9494  dense_elements_length =
9495  ExternalUnsignedShortArray::cast(object->elements())->length();
9496  break;
9497  }
9498  case EXTERNAL_INT_ELEMENTS: {
9499  dense_elements_length =
9500  ExternalIntArray::cast(object->elements())->length();
9501  break;
9502  }
9504  dense_elements_length =
9505  ExternalUnsignedIntArray::cast(object->elements())->length();
9506  break;
9507  }
9508  case EXTERNAL_FLOAT_ELEMENTS: {
9509  dense_elements_length =
9510  ExternalFloatArray::cast(object->elements())->length();
9511  break;
9512  }
9513  case EXTERNAL_DOUBLE_ELEMENTS: {
9514  dense_elements_length =
9515  ExternalDoubleArray::cast(object->elements())->length();
9516  break;
9517  }
9518  default:
9519  UNREACHABLE();
9520  dense_elements_length = 0;
9521  break;
9522  }
9523  uint32_t length = static_cast<uint32_t>(dense_elements_length);
9524  if (range <= length) {
9525  length = range;
9526  // We will add all indices, so we might as well clear it first
9527  // and avoid duplicates.
9528  indices->Clear();
9529  }
9530  for (uint32_t i = 0; i < length; i++) {
9531  indices->Add(i);
9532  }
9533  if (length == range) return; // All indices accounted for already.
9534  break;
9535  }
9536  }
9537 
9538  Handle<Object> prototype(object->GetPrototype());
9539  if (prototype->IsJSObject()) {
9540  // The prototype will usually have no inherited element indices,
9541  // but we have to check.
9542  CollectElementIndices(Handle<JSObject>::cast(prototype), range, indices);
9543  }
9544 }
9545 
9546 
9557 static bool IterateElements(Isolate* isolate,
9558  Handle<JSArray> receiver,
9559  ArrayConcatVisitor* visitor) {
9560  uint32_t length = static_cast<uint32_t>(receiver->length()->Number());
9561  switch (receiver->GetElementsKind()) {
9562  case FAST_SMI_ELEMENTS:
9563  case FAST_ELEMENTS:
9565  case FAST_HOLEY_ELEMENTS: {
9566  // Run through the elements FixedArray and use HasElement and GetElement
9567  // to check the prototype for missing elements.
9568  Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
9569  int fast_length = static_cast<int>(length);
9570  ASSERT(fast_length <= elements->length());
9571  for (int j = 0; j < fast_length; j++) {
9572  HandleScope loop_scope(isolate);
9573  Handle<Object> element_value(elements->get(j), isolate);
9574  if (!element_value->IsTheHole()) {
9575  visitor->visit(j, element_value);
9576  } else if (receiver->HasElement(j)) {
9577  // Call GetElement on receiver, not its prototype, or getters won't
9578  // have the correct receiver.
9579  element_value = Object::GetElement(receiver, j);
9580  RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
9581  visitor->visit(j, element_value);
9582  }
9583  }
9584  break;
9585  }
9587  case FAST_DOUBLE_ELEMENTS: {
9588  // TODO(1810): Decide if it's worthwhile to implement this.
9589  UNREACHABLE();
9590  break;
9591  }
9592  case DICTIONARY_ELEMENTS: {
9593  Handle<SeededNumberDictionary> dict(receiver->element_dictionary());
9594  List<uint32_t> indices(dict->Capacity() / 2);
9595  // Collect all indices in the object and the prototypes less
9596  // than length. This might introduce duplicates in the indices list.
9597  CollectElementIndices(receiver, length, &indices);
9598  indices.Sort(&compareUInt32);
9599  int j = 0;
9600  int n = indices.length();
9601  while (j < n) {
9602  HandleScope loop_scope;
9603  uint32_t index = indices[j];
9604  Handle<Object> element = Object::GetElement(receiver, index);
9605  RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element, false);
9606  visitor->visit(index, element);
9607  // Skip to next different index (i.e., omit duplicates).
9608  do {
9609  j++;
9610  } while (j < n && indices[j] == index);
9611  }
9612  break;
9613  }
9614  case EXTERNAL_PIXEL_ELEMENTS: {
9615  Handle<ExternalPixelArray> pixels(ExternalPixelArray::cast(
9616  receiver->elements()));
9617  for (uint32_t j = 0; j < length; j++) {
9618  Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)));
9619  visitor->visit(j, e);
9620  }
9621  break;
9622  }
9623  case EXTERNAL_BYTE_ELEMENTS: {
9624  IterateExternalArrayElements<ExternalByteArray, int8_t>(
9625  isolate, receiver, true, true, visitor);
9626  break;
9627  }
9629  IterateExternalArrayElements<ExternalUnsignedByteArray, uint8_t>(
9630  isolate, receiver, true, true, visitor);
9631  break;
9632  }
9633  case EXTERNAL_SHORT_ELEMENTS: {
9634  IterateExternalArrayElements<ExternalShortArray, int16_t>(
9635  isolate, receiver, true, true, visitor);
9636  break;
9637  }
9639  IterateExternalArrayElements<ExternalUnsignedShortArray, uint16_t>(
9640  isolate, receiver, true, true, visitor);
9641  break;
9642  }
9643  case EXTERNAL_INT_ELEMENTS: {
9644  IterateExternalArrayElements<ExternalIntArray, int32_t>(
9645  isolate, receiver, true, false, visitor);
9646  break;
9647  }
9649  IterateExternalArrayElements<ExternalUnsignedIntArray, uint32_t>(
9650  isolate, receiver, true, false, visitor);
9651  break;
9652  }
9653  case EXTERNAL_FLOAT_ELEMENTS: {
9654  IterateExternalArrayElements<ExternalFloatArray, float>(
9655  isolate, receiver, false, false, visitor);
9656  break;
9657  }
9658  case EXTERNAL_DOUBLE_ELEMENTS: {
9659  IterateExternalArrayElements<ExternalDoubleArray, double>(
9660  isolate, receiver, false, false, visitor);
9661  break;
9662  }
9663  default:
9664  UNREACHABLE();
9665  break;
9666  }
9667  visitor->increase_index_offset(length);
9668  return true;
9669 }
9670 
9671 
9678 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) {
9679  ASSERT(args.length() == 1);
9680  HandleScope handle_scope(isolate);
9681 
9682  CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 0);
9683  int argument_count = static_cast<int>(arguments->length()->Number());
9684  RUNTIME_ASSERT(arguments->HasFastObjectElements());
9685  Handle<FixedArray> elements(FixedArray::cast(arguments->elements()));
9686 
9687  // Pass 1: estimate the length and number of elements of the result.
9688  // The actual length can be larger if any of the arguments have getters
9689  // that mutate other arguments (but will otherwise be precise).
9690  // The number of elements is precise if there are no inherited elements.
9691 
9692  uint32_t estimate_result_length = 0;
9693  uint32_t estimate_nof_elements = 0;
9694  {
9695  for (int i = 0; i < argument_count; i++) {
9696  HandleScope loop_scope;
9697  Handle<Object> obj(elements->get(i));
9698  uint32_t length_estimate;
9699  uint32_t element_estimate;
9700  if (obj->IsJSArray()) {
9702  // TODO(1810): Find out if it's worthwhile to properly support
9703  // arbitrary ElementsKinds. For now, pessimistically transition to
9704  // FAST_*_ELEMENTS.
9705  if (array->HasFastDoubleElements()) {
9706  ElementsKind to_kind = FAST_ELEMENTS;
9707  if (array->HasFastHoleyElements()) {
9708  to_kind = FAST_HOLEY_ELEMENTS;
9709  }
9710  array = Handle<JSArray>::cast(
9711  JSObject::TransitionElementsKind(array, to_kind));
9712  }
9713  length_estimate =
9714  static_cast<uint32_t>(array->length()->Number());
9715  element_estimate =
9716  EstimateElementCount(array);
9717  } else {
9718  length_estimate = 1;
9719  element_estimate = 1;
9720  }
9721  // Avoid overflows by capping at kMaxElementCount.
9722  if (JSObject::kMaxElementCount - estimate_result_length <
9723  length_estimate) {
9724  estimate_result_length = JSObject::kMaxElementCount;
9725  } else {
9726  estimate_result_length += length_estimate;
9727  }
9728  if (JSObject::kMaxElementCount - estimate_nof_elements <
9729  element_estimate) {
9730  estimate_nof_elements = JSObject::kMaxElementCount;
9731  } else {
9732  estimate_nof_elements += element_estimate;
9733  }
9734  }
9735  }
9736 
9737  // If estimated number of elements is more than half of length, a
9738  // fixed array (fast case) is more time and space-efficient than a
9739  // dictionary.
9740  bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length;
9741 
9742  Handle<FixedArray> storage;
9743  if (fast_case) {
9744  // The backing storage array must have non-existing elements to
9745  // preserve holes across concat operations.
9746  storage = isolate->factory()->NewFixedArrayWithHoles(
9747  estimate_result_length);
9748  } else {
9749  // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
9750  uint32_t at_least_space_for = estimate_nof_elements +
9751  (estimate_nof_elements >> 2);
9752  storage = Handle<FixedArray>::cast(
9753  isolate->factory()->NewSeededNumberDictionary(at_least_space_for));
9754  }
9755 
9756  ArrayConcatVisitor visitor(isolate, storage, fast_case);
9757 
9758  for (int i = 0; i < argument_count; i++) {
9759  Handle<Object> obj(elements->get(i));
9760  if (obj->IsJSArray()) {
9762  if (!IterateElements(isolate, array, &visitor)) {
9763  return Failure::Exception();
9764  }
9765  } else {
9766  visitor.visit(0, obj);
9767  visitor.increase_index_offset(1);
9768  }
9769  }
9770 
9771  return *visitor.ToArray();
9772 }
9773 
9774 
9775 // This will not allocate (flatten the string), but it may run
9776 // very slowly for very deeply nested ConsStrings. For debugging use only.
9777 RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalPrint) {
9778  NoHandleAllocation ha;
9779  ASSERT(args.length() == 1);
9780 
9781  CONVERT_ARG_CHECKED(String, string, 0);
9782  StringInputBuffer buffer(string);
9783  while (buffer.has_more()) {
9784  uint16_t character = buffer.GetNext();
9785  PrintF("%c", character);
9786  }
9787  return string;
9788 }
9789 
9790 // Moves all own elements of an object, that are below a limit, to positions
9791 // starting at zero. All undefined values are placed after non-undefined values,
9792 // and are followed by non-existing element. Does not change the length
9793 // property.
9794 // Returns the number of non-undefined elements collected.
9795 RUNTIME_FUNCTION(MaybeObject*, Runtime_RemoveArrayHoles) {
9796  ASSERT(args.length() == 2);
9797  CONVERT_ARG_CHECKED(JSObject, object, 0);
9798  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
9799  return object->PrepareElementsForSort(limit);
9800 }
9801 
9802 
9803 // Move contents of argument 0 (an array) to argument 1 (an array)
9804 RUNTIME_FUNCTION(MaybeObject*, Runtime_MoveArrayContents) {
9805  ASSERT(args.length() == 2);
9806  CONVERT_ARG_CHECKED(JSArray, from, 0);
9807  CONVERT_ARG_CHECKED(JSArray, to, 1);
9808  from->ValidateElements();
9809  to->ValidateElements();
9810  FixedArrayBase* new_elements = from->elements();
9811  ElementsKind from_kind = from->GetElementsKind();
9812  MaybeObject* maybe_new_map;
9813  maybe_new_map = to->GetElementsTransitionMap(isolate, from_kind);
9814  Object* new_map;
9815  if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
9816  to->set_map_and_elements(Map::cast(new_map), new_elements);
9817  to->set_length(from->length());
9818  Object* obj;
9819  { MaybeObject* maybe_obj = from->ResetElements();
9820  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9821  }
9822  from->set_length(Smi::FromInt(0));
9823  to->ValidateElements();
9824  return to;
9825 }
9826 
9827 
9828 // How many elements does this object/array have?
9829 RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) {
9830  ASSERT(args.length() == 1);
9831  CONVERT_ARG_CHECKED(JSObject, object, 0);
9832  HeapObject* elements = object->elements();
9833  if (elements->IsDictionary()) {
9834  int result = SeededNumberDictionary::cast(elements)->NumberOfElements();
9835  return Smi::FromInt(result);
9836  } else if (object->IsJSArray()) {
9837  return JSArray::cast(object)->length();
9838  } else {
9839  return Smi::FromInt(FixedArray::cast(elements)->length());
9840  }
9841 }
9842 
9843 
9844 // Returns an array that tells you where in the [0, length) interval an array
9845 // might have elements. Can either return keys (positive integers) or
9846 // intervals (pair of a negative integer (-start-1) followed by a
9847 // positive (length)) or undefined values.
9848 // Intervals can span over some keys that are not in the object.
9849 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
9850  ASSERT(args.length() == 2);
9851  HandleScope scope(isolate);
9853  CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
9854  if (array->elements()->IsDictionary()) {
9855  // Create an array and get all the keys into it, then remove all the
9856  // keys that are not integers in the range 0 to length-1.
9857  bool threw = false;
9858  Handle<FixedArray> keys =
9859  GetKeysInFixedArrayFor(array, INCLUDE_PROTOS, &threw);
9860  if (threw) return Failure::Exception();
9861 
9862  int keys_length = keys->length();
9863  for (int i = 0; i < keys_length; i++) {
9864  Object* key = keys->get(i);
9865  uint32_t index = 0;
9866  if (!key->ToArrayIndex(&index) || index >= length) {
9867  // Zap invalid keys.
9868  keys->set_undefined(i);
9869  }
9870  }
9871  return *isolate->factory()->NewJSArrayWithElements(keys);
9872  } else {
9873  ASSERT(array->HasFastSmiOrObjectElements() ||
9874  array->HasFastDoubleElements());
9875  Handle<FixedArray> single_interval = isolate->factory()->NewFixedArray(2);
9876  // -1 means start of array.
9877  single_interval->set(0, Smi::FromInt(-1));
9878  FixedArrayBase* elements = FixedArrayBase::cast(array->elements());
9879  uint32_t actual_length =
9880  static_cast<uint32_t>(elements->length());
9881  uint32_t min_length = actual_length < length ? actual_length : length;
9882  Handle<Object> length_object =
9883  isolate->factory()->NewNumber(static_cast<double>(min_length));
9884  single_interval->set(1, *length_object);
9885  return *isolate->factory()->NewJSArrayWithElements(single_interval);
9886  }
9887 }
9888 
9889 
9890 RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) {
9891  ASSERT(args.length() == 3);
9892  CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
9893  CONVERT_ARG_CHECKED(String, name, 1);
9896  if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
9897  return JSObject::cast(receiver)->LookupAccessor(name, component);
9898 }
9899 
9900 
9901 #ifdef ENABLE_DEBUGGER_SUPPORT
9902 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugBreak) {
9903  ASSERT(args.length() == 0);
9904  return Execution::DebugBreakHelper();
9905 }
9906 
9907 
9908 // Helper functions for wrapping and unwrapping stack frame ids.
9909 static Smi* WrapFrameId(StackFrame::Id id) {
9910  ASSERT(IsAligned(OffsetFrom(id), static_cast<intptr_t>(4)));
9911  return Smi::FromInt(id >> 2);
9912 }
9913 
9914 
9915 static StackFrame::Id UnwrapFrameId(int wrapped) {
9916  return static_cast<StackFrame::Id>(wrapped << 2);
9917 }
9918 
9919 
9920 // Adds a JavaScript function as a debug event listener.
9921 // args[0]: debug event listener function to set or null or undefined for
9922 // clearing the event listener function
9923 // args[1]: object supplied during callback
9924 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDebugEventListener) {
9925  ASSERT(args.length() == 2);
9926  RUNTIME_ASSERT(args[0]->IsJSFunction() ||
9927  args[0]->IsUndefined() ||
9928  args[0]->IsNull());
9929  Handle<Object> callback = args.at<Object>(0);
9930  Handle<Object> data = args.at<Object>(1);
9931  isolate->debugger()->SetEventListener(callback, data);
9932 
9933  return isolate->heap()->undefined_value();
9934 }
9935 
9936 
9937 RUNTIME_FUNCTION(MaybeObject*, Runtime_Break) {
9938  ASSERT(args.length() == 0);
9939  isolate->stack_guard()->DebugBreak();
9940  return isolate->heap()->undefined_value();
9941 }
9942 
9943 
9944 static MaybeObject* DebugLookupResultValue(Heap* heap,
9945  Object* receiver,
9946  String* name,
9947  LookupResult* result,
9948  bool* caught_exception) {
9949  Object* value;
9950  switch (result->type()) {
9951  case NORMAL:
9952  value = result->holder()->GetNormalizedProperty(result);
9953  if (value->IsTheHole()) {
9954  return heap->undefined_value();
9955  }
9956  return value;
9957  case FIELD:
9958  value =
9960  result->holder())->FastPropertyAt(result->GetFieldIndex());
9961  if (value->IsTheHole()) {
9962  return heap->undefined_value();
9963  }
9964  return value;
9965  case CONSTANT_FUNCTION:
9966  return result->GetConstantFunction();
9967  case CALLBACKS: {
9968  Object* structure = result->GetCallbackObject();
9969  if (structure->IsForeign() || structure->IsAccessorInfo()) {
9970  MaybeObject* maybe_value = result->holder()->GetPropertyWithCallback(
9971  receiver, structure, name);
9972  if (!maybe_value->ToObject(&value)) {
9973  if (maybe_value->IsRetryAfterGC()) return maybe_value;
9974  ASSERT(maybe_value->IsException());
9975  maybe_value = heap->isolate()->pending_exception();
9976  heap->isolate()->clear_pending_exception();
9977  if (caught_exception != NULL) {
9978  *caught_exception = true;
9979  }
9980  return maybe_value;
9981  }
9982  return value;
9983  } else {
9984  return heap->undefined_value();
9985  }
9986  }
9987  case INTERCEPTOR:
9988  case TRANSITION:
9989  return heap->undefined_value();
9990  case HANDLER:
9991  case NONEXISTENT:
9992  UNREACHABLE();
9993  return heap->undefined_value();
9994  }
9995  UNREACHABLE(); // keep the compiler happy
9996  return heap->undefined_value();
9997 }
9998 
9999 
10000 // Get debugger related details for an object property.
10001 // args[0]: object holding property
10002 // args[1]: name of the property
10003 //
10004 // The array returned contains the following information:
10005 // 0: Property value
10006 // 1: Property details
10007 // 2: Property value is exception
10008 // 3: Getter function if defined
10009 // 4: Setter function if defined
10010 // Items 2-4 are only filled if the property has either a getter or a setter
10011 // defined through __defineGetter__ and/or __defineSetter__.
10012 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) {
10013  HandleScope scope(isolate);
10014 
10015  ASSERT(args.length() == 2);
10016 
10017  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10018  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
10019 
10020  // Make sure to set the current context to the context before the debugger was
10021  // entered (if the debugger is entered). The reason for switching context here
10022  // is that for some property lookups (accessors and interceptors) callbacks
10023  // into the embedding application can occour, and the embedding application
10024  // could have the assumption that its own native context is the current
10025  // context and not some internal debugger context.
10026  SaveContext save(isolate);
10027  if (isolate->debug()->InDebugger()) {
10028  isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
10029  }
10030 
10031  // Skip the global proxy as it has no properties and always delegates to the
10032  // real global object.
10033  if (obj->IsJSGlobalProxy()) {
10034  obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
10035  }
10036 
10037 
10038  // Check if the name is trivially convertible to an index and get the element
10039  // if so.
10040  uint32_t index;
10041  if (name->AsArrayIndex(&index)) {
10042  Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
10043  Object* element_or_char;
10044  { MaybeObject* maybe_element_or_char =
10045  Runtime::GetElementOrCharAt(isolate, obj, index);
10046  if (!maybe_element_or_char->ToObject(&element_or_char)) {
10047  return maybe_element_or_char;
10048  }
10049  }
10050  details->set(0, element_or_char);
10051  details->set(1, PropertyDetails(NONE, NORMAL).AsSmi());
10052  return *isolate->factory()->NewJSArrayWithElements(details);
10053  }
10054 
10055  // Find the number of objects making up this.
10056  int length = LocalPrototypeChainLength(*obj);
10057 
10058  // Try local lookup on each of the objects.
10059  Handle<JSObject> jsproto = obj;
10060  for (int i = 0; i < length; i++) {
10061  LookupResult result(isolate);
10062  jsproto->LocalLookup(*name, &result);
10063  if (result.IsFound()) {
10064  // LookupResult is not GC safe as it holds raw object pointers.
10065  // GC can happen later in this code so put the required fields into
10066  // local variables using handles when required for later use.
10067  Handle<Object> result_callback_obj;
10068  if (result.IsPropertyCallbacks()) {
10069  result_callback_obj = Handle<Object>(result.GetCallbackObject(),
10070  isolate);
10071  }
10072  Smi* property_details = result.GetPropertyDetails().AsSmi();
10073  // DebugLookupResultValue can cause GC so details from LookupResult needs
10074  // to be copied to handles before this.
10075  bool caught_exception = false;
10076  Object* raw_value;
10077  { MaybeObject* maybe_raw_value =
10078  DebugLookupResultValue(isolate->heap(), *obj, *name,
10079  &result, &caught_exception);
10080  if (!maybe_raw_value->ToObject(&raw_value)) return maybe_raw_value;
10081  }
10082  Handle<Object> value(raw_value, isolate);
10083 
10084  // If the callback object is a fixed array then it contains JavaScript
10085  // getter and/or setter.
10086  bool hasJavaScriptAccessors = result.IsPropertyCallbacks() &&
10087  result_callback_obj->IsAccessorPair();
10088  Handle<FixedArray> details =
10089  isolate->factory()->NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
10090  details->set(0, *value);
10091  details->set(1, property_details);
10092  if (hasJavaScriptAccessors) {
10093  AccessorPair* accessors = AccessorPair::cast(*result_callback_obj);
10094  details->set(2, isolate->heap()->ToBoolean(caught_exception));
10095  details->set(3, accessors->GetComponent(ACCESSOR_GETTER));
10096  details->set(4, accessors->GetComponent(ACCESSOR_SETTER));
10097  }
10098 
10099  return *isolate->factory()->NewJSArrayWithElements(details);
10100  }
10101  if (i < length - 1) {
10102  jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
10103  }
10104  }
10105 
10106  return isolate->heap()->undefined_value();
10107 }
10108 
10109 
10110 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetProperty) {
10111  HandleScope scope(isolate);
10112 
10113  ASSERT(args.length() == 2);
10114 
10115  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10116  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
10117 
10118  LookupResult result(isolate);
10119  obj->Lookup(*name, &result);
10120  if (result.IsFound()) {
10121  return DebugLookupResultValue(isolate->heap(), *obj, *name, &result, NULL);
10122  }
10123  return isolate->heap()->undefined_value();
10124 }
10125 
10126 
10127 // Return the property type calculated from the property details.
10128 // args[0]: smi with property details.
10129 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyTypeFromDetails) {
10130  ASSERT(args.length() == 1);
10132  return Smi::FromInt(static_cast<int>(details.type()));
10133 }
10134 
10135 
10136 // Return the property attribute calculated from the property details.
10137 // args[0]: smi with property details.
10138 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyAttributesFromDetails) {
10139  ASSERT(args.length() == 1);
10141  return Smi::FromInt(static_cast<int>(details.attributes()));
10142 }
10143 
10144 
10145 // Return the property insertion index calculated from the property details.
10146 // args[0]: smi with property details.
10147 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyIndexFromDetails) {
10148  ASSERT(args.length() == 1);
10150  // TODO(verwaest): Depends on the type of details.
10151  return Smi::FromInt(details.dictionary_index());
10152 }
10153 
10154 
10155 // Return property value from named interceptor.
10156 // args[0]: object
10157 // args[1]: property name
10158 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugNamedInterceptorPropertyValue) {
10159  HandleScope scope(isolate);
10160  ASSERT(args.length() == 2);
10161  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10162  RUNTIME_ASSERT(obj->HasNamedInterceptor());
10163  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
10164 
10165  PropertyAttributes attributes;
10166  return obj->GetPropertyWithInterceptor(*obj, *name, &attributes);
10167 }
10168 
10169 
10170 // Return element value from indexed interceptor.
10171 // args[0]: object
10172 // args[1]: index
10173 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugIndexedInterceptorElementValue) {
10174  HandleScope scope(isolate);
10175  ASSERT(args.length() == 2);
10176  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10177  RUNTIME_ASSERT(obj->HasIndexedInterceptor());
10178  CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
10179 
10180  return obj->GetElementWithInterceptor(*obj, index);
10181 }
10182 
10183 
10184 RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckExecutionState) {
10185  ASSERT(args.length() >= 1);
10186  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
10187  // Check that the break id is valid.
10188  if (isolate->debug()->break_id() == 0 ||
10189  break_id != isolate->debug()->break_id()) {
10190  return isolate->Throw(
10191  isolate->heap()->illegal_execution_state_symbol());
10192  }
10193 
10194  return isolate->heap()->true_value();
10195 }
10196 
10197 
10198 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) {
10199  HandleScope scope(isolate);
10200  ASSERT(args.length() == 1);
10201 
10202  // Check arguments.
10203  Object* result;
10204  { MaybeObject* maybe_result = Runtime_CheckExecutionState(
10205  RUNTIME_ARGUMENTS(isolate, args));
10206  if (!maybe_result->ToObject(&result)) return maybe_result;
10207  }
10208 
10209  // Count all frames which are relevant to debugging stack trace.
10210  int n = 0;
10211  StackFrame::Id id = isolate->debug()->break_frame_id();
10212  if (id == StackFrame::NO_ID) {
10213  // If there is no JavaScript stack frame count is 0.
10214  return Smi::FromInt(0);
10215  }
10216 
10217  for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) {
10218  n += it.frame()->GetInlineCount();
10219  }
10220  return Smi::FromInt(n);
10221 }
10222 
10223 
10224 class FrameInspector {
10225  public:
10226  FrameInspector(JavaScriptFrame* frame,
10227  int inlined_jsframe_index,
10228  Isolate* isolate)
10229  : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
10230  // Calculate the deoptimized frame.
10231  if (frame->is_optimized()) {
10232  deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
10233  frame, inlined_jsframe_index, isolate);
10234  }
10235  has_adapted_arguments_ = frame_->has_adapted_arguments();
10236  is_bottommost_ = inlined_jsframe_index == 0;
10237  is_optimized_ = frame_->is_optimized();
10238  }
10239 
10240  ~FrameInspector() {
10241  // Get rid of the calculated deoptimized frame if any.
10242  if (deoptimized_frame_ != NULL) {
10243  Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_,
10244  isolate_);
10245  }
10246  }
10247 
10248  int GetParametersCount() {
10249  return is_optimized_
10250  ? deoptimized_frame_->parameters_count()
10251  : frame_->ComputeParametersCount();
10252  }
10253  int expression_count() { return deoptimized_frame_->expression_count(); }
10254  Object* GetFunction() {
10255  return is_optimized_
10256  ? deoptimized_frame_->GetFunction()
10257  : frame_->function();
10258  }
10259  Object* GetParameter(int index) {
10260  return is_optimized_
10261  ? deoptimized_frame_->GetParameter(index)
10262  : frame_->GetParameter(index);
10263  }
10264  Object* GetExpression(int index) {
10265  return is_optimized_
10266  ? deoptimized_frame_->GetExpression(index)
10267  : frame_->GetExpression(index);
10268  }
10269  int GetSourcePosition() {
10270  return is_optimized_
10271  ? deoptimized_frame_->GetSourcePosition()
10272  : frame_->LookupCode()->SourcePosition(frame_->pc());
10273  }
10274  bool IsConstructor() {
10275  return is_optimized_ && !is_bottommost_
10276  ? deoptimized_frame_->HasConstructStub()
10277  : frame_->IsConstructor();
10278  }
10279 
10280  // To inspect all the provided arguments the frame might need to be
10281  // replaced with the arguments frame.
10282  void SetArgumentsFrame(JavaScriptFrame* frame) {
10283  ASSERT(has_adapted_arguments_);
10284  frame_ = frame;
10285  is_optimized_ = frame_->is_optimized();
10286  ASSERT(!is_optimized_);
10287  }
10288 
10289  private:
10290  JavaScriptFrame* frame_;
10291  DeoptimizedFrameInfo* deoptimized_frame_;
10292  Isolate* isolate_;
10293  bool is_optimized_;
10294  bool is_bottommost_;
10295  bool has_adapted_arguments_;
10296 
10297  DISALLOW_COPY_AND_ASSIGN(FrameInspector);
10298 };
10299 
10300 
10301 static const int kFrameDetailsFrameIdIndex = 0;
10302 static const int kFrameDetailsReceiverIndex = 1;
10303 static const int kFrameDetailsFunctionIndex = 2;
10304 static const int kFrameDetailsArgumentCountIndex = 3;
10305 static const int kFrameDetailsLocalCountIndex = 4;
10306 static const int kFrameDetailsSourcePositionIndex = 5;
10307 static const int kFrameDetailsConstructCallIndex = 6;
10308 static const int kFrameDetailsAtReturnIndex = 7;
10309 static const int kFrameDetailsFlagsIndex = 8;
10310 static const int kFrameDetailsFirstDynamicIndex = 9;
10311 
10312 
10313 static SaveContext* FindSavedContextForFrame(Isolate* isolate,
10314  JavaScriptFrame* frame) {
10315  SaveContext* save = isolate->save_context();
10316  while (save != NULL && !save->IsBelowFrame(frame)) {
10317  save = save->prev();
10318  }
10319  ASSERT(save != NULL);
10320  return save;
10321 }
10322 
10323 
10324 // Return an array with frame details
10325 // args[0]: number: break id
10326 // args[1]: number: frame index
10327 //
10328 // The array returned contains the following information:
10329 // 0: Frame id
10330 // 1: Receiver
10331 // 2: Function
10332 // 3: Argument count
10333 // 4: Local count
10334 // 5: Source position
10335 // 6: Constructor call
10336 // 7: Is at return
10337 // 8: Flags
10338 // Arguments name, value
10339 // Locals name, value
10340 // Return value if any
10341 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
10342  HandleScope scope(isolate);
10343  ASSERT(args.length() == 2);
10344 
10345  // Check arguments.
10346  Object* check;
10347  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
10348  RUNTIME_ARGUMENTS(isolate, args));
10349  if (!maybe_check->ToObject(&check)) return maybe_check;
10350  }
10351  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
10352  Heap* heap = isolate->heap();
10353 
10354  // Find the relevant frame with the requested index.
10355  StackFrame::Id id = isolate->debug()->break_frame_id();
10356  if (id == StackFrame::NO_ID) {
10357  // If there are no JavaScript stack frames return undefined.
10358  return heap->undefined_value();
10359  }
10360 
10361  int count = 0;
10362  JavaScriptFrameIterator it(isolate, id);
10363  for (; !it.done(); it.Advance()) {
10364  if (index < count + it.frame()->GetInlineCount()) break;
10365  count += it.frame()->GetInlineCount();
10366  }
10367  if (it.done()) return heap->undefined_value();
10368 
10369  bool is_optimized = it.frame()->is_optimized();
10370 
10371  int inlined_jsframe_index = 0; // Inlined frame index in optimized frame.
10372  if (is_optimized) {
10373  inlined_jsframe_index =
10374  it.frame()->GetInlineCount() - (index - count) - 1;
10375  }
10376  FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate);
10377 
10378  // Traverse the saved contexts chain to find the active context for the
10379  // selected frame.
10380  SaveContext* save = FindSavedContextForFrame(isolate, it.frame());
10381 
10382  // Get the frame id.
10383  Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate);
10384 
10385  // Find source position in unoptimized code.
10386  int position = frame_inspector.GetSourcePosition();
10387 
10388  // Check for constructor frame.
10389  bool constructor = frame_inspector.IsConstructor();
10390 
10391  // Get scope info and read from it for local variable information.
10392  Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
10393  Handle<SharedFunctionInfo> shared(function->shared());
10394  Handle<ScopeInfo> scope_info(shared->scope_info());
10395  ASSERT(*scope_info != ScopeInfo::Empty());
10396 
10397  // Get the locals names and values into a temporary array.
10398  //
10399  // TODO(1240907): Hide compiler-introduced stack variables
10400  // (e.g. .result)? For users of the debugger, they will probably be
10401  // confusing.
10402  Handle<FixedArray> locals =
10403  isolate->factory()->NewFixedArray(scope_info->LocalCount() * 2);
10404 
10405  // Fill in the values of the locals.
10406  int i = 0;
10407  for (; i < scope_info->StackLocalCount(); ++i) {
10408  // Use the value from the stack.
10409  locals->set(i * 2, scope_info->LocalName(i));
10410  locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
10411  }
10412  if (i < scope_info->LocalCount()) {
10413  // Get the context containing declarations.
10414  Handle<Context> context(
10415  Context::cast(it.frame()->context())->declaration_context());
10416  for (; i < scope_info->LocalCount(); ++i) {
10417  Handle<String> name(scope_info->LocalName(i));
10418  VariableMode mode;
10419  InitializationFlag init_flag;
10420  locals->set(i * 2, *name);
10421  locals->set(i * 2 + 1, context->get(
10422  scope_info->ContextSlotIndex(*name, &mode, &init_flag)));
10423  }
10424  }
10425 
10426  // Check whether this frame is positioned at return. If not top
10427  // frame or if the frame is optimized it cannot be at a return.
10428  bool at_return = false;
10429  if (!is_optimized && index == 0) {
10430  at_return = isolate->debug()->IsBreakAtReturn(it.frame());
10431  }
10432 
10433  // If positioned just before return find the value to be returned and add it
10434  // to the frame information.
10435  Handle<Object> return_value = isolate->factory()->undefined_value();
10436  if (at_return) {
10437  StackFrameIterator it2(isolate);
10438  Address internal_frame_sp = NULL;
10439  while (!it2.done()) {
10440  if (it2.frame()->is_internal()) {
10441  internal_frame_sp = it2.frame()->sp();
10442  } else {
10443  if (it2.frame()->is_java_script()) {
10444  if (it2.frame()->id() == it.frame()->id()) {
10445  // The internal frame just before the JavaScript frame contains the
10446  // value to return on top. A debug break at return will create an
10447  // internal frame to store the return value (eax/rax/r0) before
10448  // entering the debug break exit frame.
10449  if (internal_frame_sp != NULL) {
10450  return_value =
10451  Handle<Object>(Memory::Object_at(internal_frame_sp),
10452  isolate);
10453  break;
10454  }
10455  }
10456  }
10457 
10458  // Indicate that the previous frame was not an internal frame.
10459  internal_frame_sp = NULL;
10460  }
10461  it2.Advance();
10462  }
10463  }
10464 
10465  // Now advance to the arguments adapter frame (if any). It contains all
10466  // the provided parameters whereas the function frame always have the number
10467  // of arguments matching the functions parameters. The rest of the
10468  // information (except for what is collected above) is the same.
10469  if ((inlined_jsframe_index == 0) && it.frame()->has_adapted_arguments()) {
10470  it.AdvanceToArgumentsFrame();
10471  frame_inspector.SetArgumentsFrame(it.frame());
10472  }
10473 
10474  // Find the number of arguments to fill. At least fill the number of
10475  // parameters for the function and fill more if more parameters are provided.
10476  int argument_count = scope_info->ParameterCount();
10477  if (argument_count < frame_inspector.GetParametersCount()) {
10478  argument_count = frame_inspector.GetParametersCount();
10479  }
10480 
10481  // Calculate the size of the result.
10482  int details_size = kFrameDetailsFirstDynamicIndex +
10483  2 * (argument_count + scope_info->LocalCount()) +
10484  (at_return ? 1 : 0);
10485  Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
10486 
10487  // Add the frame id.
10488  details->set(kFrameDetailsFrameIdIndex, *frame_id);
10489 
10490  // Add the function (same as in function frame).
10491  details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
10492 
10493  // Add the arguments count.
10494  details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
10495 
10496  // Add the locals count
10497  details->set(kFrameDetailsLocalCountIndex,
10498  Smi::FromInt(scope_info->LocalCount()));
10499 
10500  // Add the source position.
10501  if (position != RelocInfo::kNoPosition) {
10502  details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
10503  } else {
10504  details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
10505  }
10506 
10507  // Add the constructor information.
10508  details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
10509 
10510  // Add the at return information.
10511  details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
10512 
10513  // Add flags to indicate information on whether this frame is
10514  // bit 0: invoked in the debugger context.
10515  // bit 1: optimized frame.
10516  // bit 2: inlined in optimized frame
10517  int flags = 0;
10518  if (*save->context() == *isolate->debug()->debug_context()) {
10519  flags |= 1 << 0;
10520  }
10521  if (is_optimized) {
10522  flags |= 1 << 1;
10523  flags |= inlined_jsframe_index << 2;
10524  }
10525  details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
10526 
10527  // Fill the dynamic part.
10528  int details_index = kFrameDetailsFirstDynamicIndex;
10529 
10530  // Add arguments name and value.
10531  for (int i = 0; i < argument_count; i++) {
10532  // Name of the argument.
10533  if (i < scope_info->ParameterCount()) {
10534  details->set(details_index++, scope_info->ParameterName(i));
10535  } else {
10536  details->set(details_index++, heap->undefined_value());
10537  }
10538 
10539  // Parameter value.
10540  if (i < frame_inspector.GetParametersCount()) {
10541  // Get the value from the stack.
10542  details->set(details_index++, frame_inspector.GetParameter(i));
10543  } else {
10544  details->set(details_index++, heap->undefined_value());
10545  }
10546  }
10547 
10548  // Add locals name and value from the temporary copy from the function frame.
10549  for (int i = 0; i < scope_info->LocalCount() * 2; i++) {
10550  details->set(details_index++, locals->get(i));
10551  }
10552 
10553  // Add the value being returned.
10554  if (at_return) {
10555  details->set(details_index++, *return_value);
10556  }
10557 
10558  // Add the receiver (same as in function frame).
10559  // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
10560  // THE FRAME ITERATOR TO WRAP THE RECEIVER.
10561  Handle<Object> receiver(it.frame()->receiver(), isolate);
10562  if (!receiver->IsJSObject() &&
10563  shared->is_classic_mode() &&
10564  !shared->native()) {
10565  // If the receiver is not a JSObject and the function is not a
10566  // builtin or strict-mode we have hit an optimization where a
10567  // value object is not converted into a wrapped JS objects. To
10568  // hide this optimization from the debugger, we wrap the receiver
10569  // by creating correct wrapper object based on the calling frame's
10570  // native context.
10571  it.Advance();
10572  Handle<Context> calling_frames_native_context(
10573  Context::cast(Context::cast(it.frame()->context())->native_context()));
10574  receiver =
10575  isolate->factory()->ToObject(receiver, calling_frames_native_context);
10576  }
10577  details->set(kFrameDetailsReceiverIndex, *receiver);
10578 
10579  ASSERT_EQ(details_size, details_index);
10580  return *isolate->factory()->NewJSArrayWithElements(details);
10581 }
10582 
10583 
10584 // Copy all the context locals into an object used to materialize a scope.
10585 static bool CopyContextLocalsToScopeObject(
10586  Isolate* isolate,
10587  Handle<ScopeInfo> scope_info,
10588  Handle<Context> context,
10589  Handle<JSObject> scope_object) {
10590  // Fill all context locals to the context extension.
10591  for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
10592  VariableMode mode;
10593  InitializationFlag init_flag;
10594  int context_index = scope_info->ContextSlotIndex(
10595  scope_info->ContextLocalName(i), &mode, &init_flag);
10596 
10598  isolate,
10599  SetProperty(scope_object,
10600  Handle<String>(scope_info->ContextLocalName(i)),
10601  Handle<Object>(context->get(context_index), isolate),
10602  NONE,
10603  kNonStrictMode),
10604  false);
10605  }
10606 
10607  return true;
10608 }
10609 
10610 
10611 // Create a plain JSObject which materializes the local scope for the specified
10612 // frame.
10613 static Handle<JSObject> MaterializeLocalScopeWithFrameInspector(
10614  Isolate* isolate,
10615  JavaScriptFrame* frame,
10616  FrameInspector* frame_inspector) {
10617  Handle<JSFunction> function(JSFunction::cast(frame_inspector->GetFunction()));
10618  Handle<SharedFunctionInfo> shared(function->shared());
10619  Handle<ScopeInfo> scope_info(shared->scope_info());
10620 
10621  // Allocate and initialize a JSObject with all the arguments, stack locals
10622  // heap locals and extension properties of the debugged function.
10623  Handle<JSObject> local_scope =
10624  isolate->factory()->NewJSObject(isolate->object_function());
10625 
10626  // First fill all parameters.
10627  for (int i = 0; i < scope_info->ParameterCount(); ++i) {
10628  Handle<Object> value(
10629  i < frame_inspector->GetParametersCount() ?
10630  frame_inspector->GetParameter(i) : isolate->heap()->undefined_value());
10631 
10633  isolate,
10634  SetProperty(local_scope,
10635  Handle<String>(scope_info->ParameterName(i)),
10636  value,
10637  NONE,
10638  kNonStrictMode),
10639  Handle<JSObject>());
10640  }
10641 
10642  // Second fill all stack locals.
10643  for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
10645  isolate,
10646  SetProperty(local_scope,
10647  Handle<String>(scope_info->StackLocalName(i)),
10648  Handle<Object>(frame_inspector->GetExpression(i)),
10649  NONE,
10650  kNonStrictMode),
10651  Handle<JSObject>());
10652  }
10653 
10654  if (scope_info->HasContext()) {
10655  // Third fill all context locals.
10656  Handle<Context> frame_context(Context::cast(frame->context()));
10657  Handle<Context> function_context(frame_context->declaration_context());
10658  if (!CopyContextLocalsToScopeObject(
10659  isolate, scope_info, function_context, local_scope)) {
10660  return Handle<JSObject>();
10661  }
10662 
10663  // Finally copy any properties from the function context extension.
10664  // These will be variables introduced by eval.
10665  if (function_context->closure() == *function) {
10666  if (function_context->has_extension() &&
10667  !function_context->IsNativeContext()) {
10668  Handle<JSObject> ext(JSObject::cast(function_context->extension()));
10669  bool threw = false;
10670  Handle<FixedArray> keys =
10671  GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
10672  if (threw) return Handle<JSObject>();
10673 
10674  for (int i = 0; i < keys->length(); i++) {
10675  // Names of variables introduced by eval are strings.
10676  ASSERT(keys->get(i)->IsString());
10677  Handle<String> key(String::cast(keys->get(i)));
10679  isolate,
10680  SetProperty(local_scope,
10681  key,
10682  GetProperty(ext, key),
10683  NONE,
10684  kNonStrictMode),
10685  Handle<JSObject>());
10686  }
10687  }
10688  }
10689  }
10690 
10691  return local_scope;
10692 }
10693 
10694 
10695 static Handle<JSObject> MaterializeLocalScope(
10696  Isolate* isolate,
10697  JavaScriptFrame* frame,
10698  int inlined_jsframe_index) {
10699  FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
10700  return MaterializeLocalScopeWithFrameInspector(isolate,
10701  frame,
10702  &frame_inspector);
10703 }
10704 
10705 
10706 // Create a plain JSObject which materializes the closure content for the
10707 // context.
10708 static Handle<JSObject> MaterializeClosure(Isolate* isolate,
10709  Handle<Context> context) {
10710  ASSERT(context->IsFunctionContext());
10711 
10712  Handle<SharedFunctionInfo> shared(context->closure()->shared());
10713  Handle<ScopeInfo> scope_info(shared->scope_info());
10714 
10715  // Allocate and initialize a JSObject with all the content of this function
10716  // closure.
10717  Handle<JSObject> closure_scope =
10718  isolate->factory()->NewJSObject(isolate->object_function());
10719 
10720  // Fill all context locals to the context extension.
10721  if (!CopyContextLocalsToScopeObject(
10722  isolate, scope_info, context, closure_scope)) {
10723  return Handle<JSObject>();
10724  }
10725 
10726  // Finally copy any properties from the function context extension. This will
10727  // be variables introduced by eval.
10728  if (context->has_extension()) {
10729  Handle<JSObject> ext(JSObject::cast(context->extension()));
10730  bool threw = false;
10731  Handle<FixedArray> keys =
10732  GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
10733  if (threw) return Handle<JSObject>();
10734 
10735  for (int i = 0; i < keys->length(); i++) {
10736  // Names of variables introduced by eval are strings.
10737  ASSERT(keys->get(i)->IsString());
10738  Handle<String> key(String::cast(keys->get(i)));
10740  isolate,
10741  SetProperty(closure_scope,
10742  key,
10743  GetProperty(ext, key),
10744  NONE,
10745  kNonStrictMode),
10746  Handle<JSObject>());
10747  }
10748  }
10749 
10750  return closure_scope;
10751 }
10752 
10753 
10754 // Create a plain JSObject which materializes the scope for the specified
10755 // catch context.
10756 static Handle<JSObject> MaterializeCatchScope(Isolate* isolate,
10757  Handle<Context> context) {
10758  ASSERT(context->IsCatchContext());
10759  Handle<String> name(String::cast(context->extension()));
10760  Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX));
10761  Handle<JSObject> catch_scope =
10762  isolate->factory()->NewJSObject(isolate->object_function());
10764  isolate,
10765  SetProperty(catch_scope, name, thrown_object, NONE, kNonStrictMode),
10766  Handle<JSObject>());
10767  return catch_scope;
10768 }
10769 
10770 
10771 // Create a plain JSObject which materializes the block scope for the specified
10772 // block context.
10773 static Handle<JSObject> MaterializeBlockScope(
10774  Isolate* isolate,
10775  Handle<Context> context) {
10776  ASSERT(context->IsBlockContext());
10777  Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
10778 
10779  // Allocate and initialize a JSObject with all the arguments, stack locals
10780  // heap locals and extension properties of the debugged function.
10781  Handle<JSObject> block_scope =
10782  isolate->factory()->NewJSObject(isolate->object_function());
10783 
10784  // Fill all context locals.
10785  if (!CopyContextLocalsToScopeObject(
10786  isolate, scope_info, context, block_scope)) {
10787  return Handle<JSObject>();
10788  }
10789 
10790  return block_scope;
10791 }
10792 
10793 
10794 // Create a plain JSObject which materializes the module scope for the specified
10795 // module context.
10796 static Handle<JSObject> MaterializeModuleScope(
10797  Isolate* isolate,
10798  Handle<Context> context) {
10799  ASSERT(context->IsModuleContext());
10800  Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
10801 
10802  // Allocate and initialize a JSObject with all the members of the debugged
10803  // module.
10804  Handle<JSObject> module_scope =
10805  isolate->factory()->NewJSObject(isolate->object_function());
10806 
10807  // Fill all context locals.
10808  if (!CopyContextLocalsToScopeObject(
10809  isolate, scope_info, context, module_scope)) {
10810  return Handle<JSObject>();
10811  }
10812 
10813  return module_scope;
10814 }
10815 
10816 
10817 // Iterate over the actual scopes visible from a stack frame or from a closure.
10818 // The iteration proceeds from the innermost visible nested scope outwards.
10819 // All scopes are backed by an actual context except the local scope,
10820 // which is inserted "artificially" in the context chain.
10821 class ScopeIterator {
10822  public:
10823  enum ScopeType {
10824  ScopeTypeGlobal = 0,
10825  ScopeTypeLocal,
10826  ScopeTypeWith,
10827  ScopeTypeClosure,
10828  ScopeTypeCatch,
10829  ScopeTypeBlock,
10830  ScopeTypeModule
10831  };
10832 
10833  ScopeIterator(Isolate* isolate,
10834  JavaScriptFrame* frame,
10835  int inlined_jsframe_index)
10836  : isolate_(isolate),
10837  frame_(frame),
10838  inlined_jsframe_index_(inlined_jsframe_index),
10839  function_(JSFunction::cast(frame->function())),
10840  context_(Context::cast(frame->context())),
10841  nested_scope_chain_(4),
10842  failed_(false) {
10843 
10844  // Catch the case when the debugger stops in an internal function.
10845  Handle<SharedFunctionInfo> shared_info(function_->shared());
10846  Handle<ScopeInfo> scope_info(shared_info->scope_info());
10847  if (shared_info->script() == isolate->heap()->undefined_value()) {
10848  while (context_->closure() == *function_) {
10849  context_ = Handle<Context>(context_->previous(), isolate_);
10850  }
10851  return;
10852  }
10853 
10854  // Get the debug info (create it if it does not exist).
10855  if (!isolate->debug()->EnsureDebugInfo(shared_info, function_)) {
10856  // Return if ensuring debug info failed.
10857  return;
10858  }
10859  Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared_info);
10860 
10861  // Find the break point where execution has stopped.
10862  BreakLocationIterator break_location_iterator(debug_info,
10863  ALL_BREAK_LOCATIONS);
10864  break_location_iterator.FindBreakLocationFromAddress(frame->pc());
10865  if (break_location_iterator.IsExit()) {
10866  // We are within the return sequence. At the momemt it is not possible to
10867  // get a source position which is consistent with the current scope chain.
10868  // Thus all nested with, catch and block contexts are skipped and we only
10869  // provide the function scope.
10870  if (scope_info->HasContext()) {
10871  context_ = Handle<Context>(context_->declaration_context(), isolate_);
10872  } else {
10873  while (context_->closure() == *function_) {
10874  context_ = Handle<Context>(context_->previous(), isolate_);
10875  }
10876  }
10877  if (scope_info->Type() != EVAL_SCOPE) nested_scope_chain_.Add(scope_info);
10878  } else {
10879  // Reparse the code and analyze the scopes.
10880  Handle<Script> script(Script::cast(shared_info->script()));
10881  Scope* scope = NULL;
10882 
10883  // Check whether we are in global, eval or function code.
10884  Handle<ScopeInfo> scope_info(shared_info->scope_info());
10885  if (scope_info->Type() != FUNCTION_SCOPE) {
10886  // Global or eval code.
10887  CompilationInfoWithZone info(script);
10888  if (scope_info->Type() == GLOBAL_SCOPE) {
10889  info.MarkAsGlobal();
10890  } else {
10891  ASSERT(scope_info->Type() == EVAL_SCOPE);
10892  info.MarkAsEval();
10893  info.SetContext(Handle<Context>(function_->context()));
10894  }
10895  if (ParserApi::Parse(&info, kNoParsingFlags) && Scope::Analyze(&info)) {
10896  scope = info.function()->scope();
10897  }
10898  RetrieveScopeChain(scope, shared_info);
10899  } else {
10900  // Function code
10901  CompilationInfoWithZone info(shared_info);
10902  if (ParserApi::Parse(&info, kNoParsingFlags) && Scope::Analyze(&info)) {
10903  scope = info.function()->scope();
10904  }
10905  RetrieveScopeChain(scope, shared_info);
10906  }
10907  }
10908  }
10909 
10910  ScopeIterator(Isolate* isolate,
10911  Handle<JSFunction> function)
10912  : isolate_(isolate),
10913  frame_(NULL),
10914  inlined_jsframe_index_(0),
10915  function_(function),
10916  context_(function->context()),
10917  failed_(false) {
10918  if (function->IsBuiltin()) {
10919  context_ = Handle<Context>();
10920  }
10921  }
10922 
10923  // More scopes?
10924  bool Done() {
10925  ASSERT(!failed_);
10926  return context_.is_null();
10927  }
10928 
10929  bool Failed() { return failed_; }
10930 
10931  // Move to the next scope.
10932  void Next() {
10933  ASSERT(!failed_);
10934  ScopeType scope_type = Type();
10935  if (scope_type == ScopeTypeGlobal) {
10936  // The global scope is always the last in the chain.
10937  ASSERT(context_->IsNativeContext());
10938  context_ = Handle<Context>();
10939  return;
10940  }
10941  if (nested_scope_chain_.is_empty()) {
10942  context_ = Handle<Context>(context_->previous(), isolate_);
10943  } else {
10944  if (nested_scope_chain_.last()->HasContext()) {
10945  ASSERT(context_->previous() != NULL);
10946  context_ = Handle<Context>(context_->previous(), isolate_);
10947  }
10948  nested_scope_chain_.RemoveLast();
10949  }
10950  }
10951 
10952  // Return the type of the current scope.
10953  ScopeType Type() {
10954  ASSERT(!failed_);
10955  if (!nested_scope_chain_.is_empty()) {
10956  Handle<ScopeInfo> scope_info = nested_scope_chain_.last();
10957  switch (scope_info->Type()) {
10958  case FUNCTION_SCOPE:
10959  ASSERT(context_->IsFunctionContext() ||
10960  !scope_info->HasContext());
10961  return ScopeTypeLocal;
10962  case MODULE_SCOPE:
10963  ASSERT(context_->IsModuleContext());
10964  return ScopeTypeModule;
10965  case GLOBAL_SCOPE:
10966  ASSERT(context_->IsNativeContext());
10967  return ScopeTypeGlobal;
10968  case WITH_SCOPE:
10969  ASSERT(context_->IsWithContext());
10970  return ScopeTypeWith;
10971  case CATCH_SCOPE:
10972  ASSERT(context_->IsCatchContext());
10973  return ScopeTypeCatch;
10974  case BLOCK_SCOPE:
10975  ASSERT(!scope_info->HasContext() ||
10976  context_->IsBlockContext());
10977  return ScopeTypeBlock;
10978  case EVAL_SCOPE:
10979  UNREACHABLE();
10980  }
10981  }
10982  if (context_->IsNativeContext()) {
10983  ASSERT(context_->global_object()->IsGlobalObject());
10984  return ScopeTypeGlobal;
10985  }
10986  if (context_->IsFunctionContext()) {
10987  return ScopeTypeClosure;
10988  }
10989  if (context_->IsCatchContext()) {
10990  return ScopeTypeCatch;
10991  }
10992  if (context_->IsBlockContext()) {
10993  return ScopeTypeBlock;
10994  }
10995  if (context_->IsModuleContext()) {
10996  return ScopeTypeModule;
10997  }
10998  ASSERT(context_->IsWithContext());
10999  return ScopeTypeWith;
11000  }
11001 
11002  // Return the JavaScript object with the content of the current scope.
11003  Handle<JSObject> ScopeObject() {
11004  ASSERT(!failed_);
11005  switch (Type()) {
11006  case ScopeIterator::ScopeTypeGlobal:
11007  return Handle<JSObject>(CurrentContext()->global_object());
11008  case ScopeIterator::ScopeTypeLocal:
11009  // Materialize the content of the local scope into a JSObject.
11010  ASSERT(nested_scope_chain_.length() == 1);
11011  return MaterializeLocalScope(isolate_, frame_, inlined_jsframe_index_);
11012  case ScopeIterator::ScopeTypeWith:
11013  // Return the with object.
11014  return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
11015  case ScopeIterator::ScopeTypeCatch:
11016  return MaterializeCatchScope(isolate_, CurrentContext());
11017  case ScopeIterator::ScopeTypeClosure:
11018  // Materialize the content of the closure scope into a JSObject.
11019  return MaterializeClosure(isolate_, CurrentContext());
11020  case ScopeIterator::ScopeTypeBlock:
11021  return MaterializeBlockScope(isolate_, CurrentContext());
11022  case ScopeIterator::ScopeTypeModule:
11023  return MaterializeModuleScope(isolate_, CurrentContext());
11024  }
11025  UNREACHABLE();
11026  return Handle<JSObject>();
11027  }
11028 
11029  Handle<ScopeInfo> CurrentScopeInfo() {
11030  ASSERT(!failed_);
11031  if (!nested_scope_chain_.is_empty()) {
11032  return nested_scope_chain_.last();
11033  } else if (context_->IsBlockContext()) {
11034  return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension()));
11035  } else if (context_->IsFunctionContext()) {
11036  return Handle<ScopeInfo>(context_->closure()->shared()->scope_info());
11037  }
11038  return Handle<ScopeInfo>::null();
11039  }
11040 
11041  // Return the context for this scope. For the local context there might not
11042  // be an actual context.
11043  Handle<Context> CurrentContext() {
11044  ASSERT(!failed_);
11045  if (Type() == ScopeTypeGlobal ||
11046  nested_scope_chain_.is_empty()) {
11047  return context_;
11048  } else if (nested_scope_chain_.last()->HasContext()) {
11049  return context_;
11050  } else {
11051  return Handle<Context>();
11052  }
11053  }
11054 
11055 #ifdef DEBUG
11056  // Debug print of the content of the current scope.
11057  void DebugPrint() {
11058  ASSERT(!failed_);
11059  switch (Type()) {
11060  case ScopeIterator::ScopeTypeGlobal:
11061  PrintF("Global:\n");
11062  CurrentContext()->Print();
11063  break;
11064 
11065  case ScopeIterator::ScopeTypeLocal: {
11066  PrintF("Local:\n");
11067  function_->shared()->scope_info()->Print();
11068  if (!CurrentContext().is_null()) {
11069  CurrentContext()->Print();
11070  if (CurrentContext()->has_extension()) {
11071  Handle<Object> extension(CurrentContext()->extension());
11072  if (extension->IsJSContextExtensionObject()) {
11073  extension->Print();
11074  }
11075  }
11076  }
11077  break;
11078  }
11079 
11080  case ScopeIterator::ScopeTypeWith:
11081  PrintF("With:\n");
11082  CurrentContext()->extension()->Print();
11083  break;
11084 
11085  case ScopeIterator::ScopeTypeCatch:
11086  PrintF("Catch:\n");
11087  CurrentContext()->extension()->Print();
11088  CurrentContext()->get(Context::THROWN_OBJECT_INDEX)->Print();
11089  break;
11090 
11091  case ScopeIterator::ScopeTypeClosure:
11092  PrintF("Closure:\n");
11093  CurrentContext()->Print();
11094  if (CurrentContext()->has_extension()) {
11095  Handle<Object> extension(CurrentContext()->extension());
11096  if (extension->IsJSContextExtensionObject()) {
11097  extension->Print();
11098  }
11099  }
11100  break;
11101 
11102  default:
11103  UNREACHABLE();
11104  }
11105  PrintF("\n");
11106  }
11107 #endif
11108 
11109  private:
11110  Isolate* isolate_;
11111  JavaScriptFrame* frame_;
11112  int inlined_jsframe_index_;
11113  Handle<JSFunction> function_;
11114  Handle<Context> context_;
11115  List<Handle<ScopeInfo> > nested_scope_chain_;
11116  bool failed_;
11117 
11118  void RetrieveScopeChain(Scope* scope,
11119  Handle<SharedFunctionInfo> shared_info) {
11120  if (scope != NULL) {
11121  int source_position = shared_info->code()->SourcePosition(frame_->pc());
11122  scope->GetNestedScopeChain(&nested_scope_chain_, source_position);
11123  } else {
11124  // A failed reparse indicates that the preparser has diverged from the
11125  // parser or that the preparse data given to the initial parse has been
11126  // faulty. We fail in debug mode but in release mode we only provide the
11127  // information we get from the context chain but nothing about
11128  // completely stack allocated scopes or stack allocated locals.
11129  // Or it could be due to stack overflow.
11130  ASSERT(isolate_->has_pending_exception());
11131  failed_ = true;
11132  }
11133  }
11134 
11135  DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
11136 };
11137 
11138 
11139 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
11140  HandleScope scope(isolate);
11141  ASSERT(args.length() == 2);
11142 
11143  // Check arguments.
11144  Object* check;
11145  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11146  RUNTIME_ARGUMENTS(isolate, args));
11147  if (!maybe_check->ToObject(&check)) return maybe_check;
11148  }
11149  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
11150 
11151  // Get the frame where the debugging is performed.
11152  StackFrame::Id id = UnwrapFrameId(wrapped_id);
11153  JavaScriptFrameIterator it(isolate, id);
11154  JavaScriptFrame* frame = it.frame();
11155 
11156  // Count the visible scopes.
11157  int n = 0;
11158  for (ScopeIterator it(isolate, frame, 0);
11159  !it.Done();
11160  it.Next()) {
11161  n++;
11162  }
11163 
11164  return Smi::FromInt(n);
11165 }
11166 
11167 
11168 static const int kScopeDetailsTypeIndex = 0;
11169 static const int kScopeDetailsObjectIndex = 1;
11170 static const int kScopeDetailsSize = 2;
11171 
11172 
11173 static MaybeObject* MaterializeScopeDetails(Isolate* isolate,
11174  ScopeIterator* it) {
11175  // Calculate the size of the result.
11176  int details_size = kScopeDetailsSize;
11177  Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
11178 
11179  // Fill in scope details.
11180  details->set(kScopeDetailsTypeIndex, Smi::FromInt(it->Type()));
11181  Handle<JSObject> scope_object = it->ScopeObject();
11182  RETURN_IF_EMPTY_HANDLE(isolate, scope_object);
11183  details->set(kScopeDetailsObjectIndex, *scope_object);
11184 
11185  return *isolate->factory()->NewJSArrayWithElements(details);
11186 }
11187 
11188 // Return an array with scope details
11189 // args[0]: number: break id
11190 // args[1]: number: frame index
11191 // args[2]: number: inlined frame index
11192 // args[3]: number: scope index
11193 //
11194 // The array returned contains the following information:
11195 // 0: Scope type
11196 // 1: Scope object
11197 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
11198  HandleScope scope(isolate);
11199  ASSERT(args.length() == 4);
11200 
11201  // Check arguments.
11202  Object* check;
11203  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11204  RUNTIME_ARGUMENTS(isolate, args));
11205  if (!maybe_check->ToObject(&check)) return maybe_check;
11206  }
11207  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
11208  CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
11209  CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
11210 
11211  // Get the frame where the debugging is performed.
11212  StackFrame::Id id = UnwrapFrameId(wrapped_id);
11213  JavaScriptFrameIterator frame_it(isolate, id);
11214  JavaScriptFrame* frame = frame_it.frame();
11215 
11216  // Find the requested scope.
11217  int n = 0;
11218  ScopeIterator it(isolate, frame, inlined_jsframe_index);
11219  for (; !it.Done() && n < index; it.Next()) {
11220  n++;
11221  }
11222  if (it.Done()) {
11223  return isolate->heap()->undefined_value();
11224  }
11225  return MaterializeScopeDetails(isolate, &it);
11226 }
11227 
11228 
11229 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeCount) {
11230  HandleScope scope(isolate);
11231  ASSERT(args.length() == 1);
11232 
11233  // Check arguments.
11234  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
11235 
11236  // Count the visible scopes.
11237  int n = 0;
11238  for (ScopeIterator it(isolate, fun); !it.Done(); it.Next()) {
11239  n++;
11240  }
11241 
11242  return Smi::FromInt(n);
11243 }
11244 
11245 
11246 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeDetails) {
11247  HandleScope scope(isolate);
11248  ASSERT(args.length() == 2);
11249 
11250  // Check arguments.
11251  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
11252  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
11253 
11254  // Find the requested scope.
11255  int n = 0;
11256  ScopeIterator it(isolate, fun);
11257  for (; !it.Done() && n < index; it.Next()) {
11258  n++;
11259  }
11260  if (it.Done()) {
11261  return isolate->heap()->undefined_value();
11262  }
11263 
11264  return MaterializeScopeDetails(isolate, &it);
11265 }
11266 
11267 
11268 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) {
11269  HandleScope scope(isolate);
11270  ASSERT(args.length() == 0);
11271 
11272 #ifdef DEBUG
11273  // Print the scopes for the top frame.
11274  StackFrameLocator locator;
11275  JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
11276  for (ScopeIterator it(isolate, frame, 0);
11277  !it.Done();
11278  it.Next()) {
11279  it.DebugPrint();
11280  }
11281 #endif
11282  return isolate->heap()->undefined_value();
11283 }
11284 
11285 
11286 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadCount) {
11287  HandleScope scope(isolate);
11288  ASSERT(args.length() == 1);
11289 
11290  // Check arguments.
11291  Object* result;
11292  { MaybeObject* maybe_result = Runtime_CheckExecutionState(
11293  RUNTIME_ARGUMENTS(isolate, args));
11294  if (!maybe_result->ToObject(&result)) return maybe_result;
11295  }
11296 
11297  // Count all archived V8 threads.
11298  int n = 0;
11299  for (ThreadState* thread =
11300  isolate->thread_manager()->FirstThreadStateInUse();
11301  thread != NULL;
11302  thread = thread->Next()) {
11303  n++;
11304  }
11305 
11306  // Total number of threads is current thread and archived threads.
11307  return Smi::FromInt(n + 1);
11308 }
11309 
11310 
11311 static const int kThreadDetailsCurrentThreadIndex = 0;
11312 static const int kThreadDetailsThreadIdIndex = 1;
11313 static const int kThreadDetailsSize = 2;
11314 
11315 // Return an array with thread details
11316 // args[0]: number: break id
11317 // args[1]: number: thread index
11318 //
11319 // The array returned contains the following information:
11320 // 0: Is current thread?
11321 // 1: Thread id
11322 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadDetails) {
11323  HandleScope scope(isolate);
11324  ASSERT(args.length() == 2);
11325 
11326  // Check arguments.
11327  Object* check;
11328  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11329  RUNTIME_ARGUMENTS(isolate, args));
11330  if (!maybe_check->ToObject(&check)) return maybe_check;
11331  }
11332  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
11333 
11334  // Allocate array for result.
11335  Handle<FixedArray> details =
11336  isolate->factory()->NewFixedArray(kThreadDetailsSize);
11337 
11338  // Thread index 0 is current thread.
11339  if (index == 0) {
11340  // Fill the details.
11341  details->set(kThreadDetailsCurrentThreadIndex,
11342  isolate->heap()->true_value());
11343  details->set(kThreadDetailsThreadIdIndex,
11344  Smi::FromInt(ThreadId::Current().ToInteger()));
11345  } else {
11346  // Find the thread with the requested index.
11347  int n = 1;
11348  ThreadState* thread =
11349  isolate->thread_manager()->FirstThreadStateInUse();
11350  while (index != n && thread != NULL) {
11351  thread = thread->Next();
11352  n++;
11353  }
11354  if (thread == NULL) {
11355  return isolate->heap()->undefined_value();
11356  }
11357 
11358  // Fill the details.
11359  details->set(kThreadDetailsCurrentThreadIndex,
11360  isolate->heap()->false_value());
11361  details->set(kThreadDetailsThreadIdIndex,
11362  Smi::FromInt(thread->id().ToInteger()));
11363  }
11364 
11365  // Convert to JS array and return.
11366  return *isolate->factory()->NewJSArrayWithElements(details);
11367 }
11368 
11369 
11370 // Sets the disable break state
11371 // args[0]: disable break state
11372 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDisableBreak) {
11373  HandleScope scope(isolate);
11374  ASSERT(args.length() == 1);
11375  CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 0);
11376  isolate->debug()->set_disable_break(disable_break);
11377  return isolate->heap()->undefined_value();
11378 }
11379 
11380 
11381 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetBreakLocations) {
11382  HandleScope scope(isolate);
11383  ASSERT(args.length() == 1);
11384 
11385  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
11386  Handle<SharedFunctionInfo> shared(fun->shared());
11387  // Find the number of break points
11388  Handle<Object> break_locations = Debug::GetSourceBreakLocations(shared);
11389  if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
11390  // Return array as JS array
11391  return *isolate->factory()->NewJSArrayWithElements(
11392  Handle<FixedArray>::cast(break_locations));
11393 }
11394 
11395 
11396 // Set a break point in a function.
11397 // args[0]: function
11398 // args[1]: number: break source position (within the function source)
11399 // args[2]: number: break point object
11400 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFunctionBreakPoint) {
11401  HandleScope scope(isolate);
11402  ASSERT(args.length() == 3);
11403  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
11404  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
11405  RUNTIME_ASSERT(source_position >= 0);
11406  Handle<Object> break_point_object_arg = args.at<Object>(2);
11407 
11408  // Set break point.
11409  isolate->debug()->SetBreakPoint(function, break_point_object_arg,
11410  &source_position);
11411 
11412  return Smi::FromInt(source_position);
11413 }
11414 
11415 
11416 // Changes the state of a break point in a script and returns source position
11417 // where break point was set. NOTE: Regarding performance see the NOTE for
11418 // GetScriptFromScriptData.
11419 // args[0]: script to set break point in
11420 // args[1]: number: break source position (within the script source)
11421 // args[2]: number: break point object
11422 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScriptBreakPoint) {
11423  HandleScope scope(isolate);
11424  ASSERT(args.length() == 3);
11425  CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
11426  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
11427  RUNTIME_ASSERT(source_position >= 0);
11428  Handle<Object> break_point_object_arg = args.at<Object>(2);
11429 
11430  // Get the script from the script wrapper.
11431  RUNTIME_ASSERT(wrapper->value()->IsScript());
11432  Handle<Script> script(Script::cast(wrapper->value()));
11433 
11434  // Set break point.
11435  if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
11436  &source_position)) {
11437  return isolate->heap()->undefined_value();
11438  }
11439 
11440  return Smi::FromInt(source_position);
11441 }
11442 
11443 
11444 // Clear a break point
11445 // args[0]: number: break point object
11446 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearBreakPoint) {
11447  HandleScope scope(isolate);
11448  ASSERT(args.length() == 1);
11449  Handle<Object> break_point_object_arg = args.at<Object>(0);
11450 
11451  // Clear break point.
11452  isolate->debug()->ClearBreakPoint(break_point_object_arg);
11453 
11454  return isolate->heap()->undefined_value();
11455 }
11456 
11457 
11458 // Change the state of break on exceptions.
11459 // args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
11460 // args[1]: Boolean indicating on/off.
11461 RUNTIME_FUNCTION(MaybeObject*, Runtime_ChangeBreakOnException) {
11462  HandleScope scope(isolate);
11463  ASSERT(args.length() == 2);
11464  RUNTIME_ASSERT(args[0]->IsNumber());
11465  CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
11466 
11467  // If the number doesn't match an enum value, the ChangeBreakOnException
11468  // function will default to affecting caught exceptions.
11469  ExceptionBreakType type =
11470  static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
11471  // Update break point state.
11472  isolate->debug()->ChangeBreakOnException(type, enable);
11473  return isolate->heap()->undefined_value();
11474 }
11475 
11476 
11477 // Returns the state of break on exceptions
11478 // args[0]: boolean indicating uncaught exceptions
11479 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsBreakOnException) {
11480  HandleScope scope(isolate);
11481  ASSERT(args.length() == 1);
11482  RUNTIME_ASSERT(args[0]->IsNumber());
11483 
11484  ExceptionBreakType type =
11485  static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
11486  bool result = isolate->debug()->IsBreakOnException(type);
11487  return Smi::FromInt(result);
11488 }
11489 
11490 
11491 // Prepare for stepping
11492 // args[0]: break id for checking execution state
11493 // args[1]: step action from the enumeration StepAction
11494 // args[2]: number of times to perform the step, for step out it is the number
11495 // of frames to step down.
11496 RUNTIME_FUNCTION(MaybeObject*, Runtime_PrepareStep) {
11497  HandleScope scope(isolate);
11498  ASSERT(args.length() == 3);
11499  // Check arguments.
11500  Object* check;
11501  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11502  RUNTIME_ARGUMENTS(isolate, args));
11503  if (!maybe_check->ToObject(&check)) return maybe_check;
11504  }
11505  if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
11506  return isolate->Throw(isolate->heap()->illegal_argument_symbol());
11507  }
11508 
11509  // Get the step action and check validity.
11510  StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
11511  if (step_action != StepIn &&
11512  step_action != StepNext &&
11513  step_action != StepOut &&
11514  step_action != StepInMin &&
11515  step_action != StepMin) {
11516  return isolate->Throw(isolate->heap()->illegal_argument_symbol());
11517  }
11518 
11519  // Get the number of steps.
11520  int step_count = NumberToInt32(args[2]);
11521  if (step_count < 1) {
11522  return isolate->Throw(isolate->heap()->illegal_argument_symbol());
11523  }
11524 
11525  // Clear all current stepping setup.
11526  isolate->debug()->ClearStepping();
11527 
11528  // Prepare step.
11529  isolate->debug()->PrepareStep(static_cast<StepAction>(step_action),
11530  step_count);
11531  return isolate->heap()->undefined_value();
11532 }
11533 
11534 
11535 // Clear all stepping set by PrepareStep.
11536 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) {
11537  HandleScope scope(isolate);
11538  ASSERT(args.length() == 0);
11539  isolate->debug()->ClearStepping();
11540  return isolate->heap()->undefined_value();
11541 }
11542 
11543 
11544 // Creates a copy of the with context chain. The copy of the context chain is
11545 // is linked to the function context supplied.
11546 static Handle<Context> CopyNestedScopeContextChain(Isolate* isolate,
11547  Handle<JSFunction> function,
11548  Handle<Context> base,
11549  JavaScriptFrame* frame,
11550  int inlined_jsframe_index) {
11551  HandleScope scope(isolate);
11552  List<Handle<ScopeInfo> > scope_chain;
11553  List<Handle<Context> > context_chain;
11554 
11555  ScopeIterator it(isolate, frame, inlined_jsframe_index);
11556  if (it.Failed()) return Handle<Context>::null();
11557 
11558  for (; it.Type() != ScopeIterator::ScopeTypeGlobal &&
11559  it.Type() != ScopeIterator::ScopeTypeLocal ; it.Next()) {
11560  ASSERT(!it.Done());
11561  scope_chain.Add(it.CurrentScopeInfo());
11562  context_chain.Add(it.CurrentContext());
11563  }
11564 
11565  // At the end of the chain. Return the base context to link to.
11566  Handle<Context> context = base;
11567 
11568  // Iteratively copy and or materialize the nested contexts.
11569  while (!scope_chain.is_empty()) {
11570  Handle<ScopeInfo> scope_info = scope_chain.RemoveLast();
11571  Handle<Context> current = context_chain.RemoveLast();
11572  ASSERT(!(scope_info->HasContext() & current.is_null()));
11573 
11574  if (scope_info->Type() == CATCH_SCOPE) {
11575  Handle<String> name(String::cast(current->extension()));
11576  Handle<Object> thrown_object(current->get(Context::THROWN_OBJECT_INDEX));
11577  context =
11578  isolate->factory()->NewCatchContext(function,
11579  context,
11580  name,
11581  thrown_object);
11582  } else if (scope_info->Type() == BLOCK_SCOPE) {
11583  // Materialize the contents of the block scope into a JSObject.
11584  Handle<JSObject> block_scope_object =
11585  MaterializeBlockScope(isolate, current);
11586  CHECK(!block_scope_object.is_null());
11587  // Allocate a new function context for the debug evaluation and set the
11588  // extension object.
11589  Handle<Context> new_context =
11590  isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS,
11591  function);
11592  new_context->set_extension(*block_scope_object);
11593  new_context->set_previous(*context);
11594  context = new_context;
11595  } else {
11596  ASSERT(scope_info->Type() == WITH_SCOPE);
11597  ASSERT(current->IsWithContext());
11598  Handle<JSObject> extension(JSObject::cast(current->extension()));
11599  context =
11600  isolate->factory()->NewWithContext(function, context, extension);
11601  }
11602  }
11603 
11604  return scope.CloseAndEscape(context);
11605 }
11606 
11607 
11608 // Helper function to find or create the arguments object for
11609 // Runtime_DebugEvaluate.
11610 static Handle<Object> GetArgumentsObject(Isolate* isolate,
11611  JavaScriptFrame* frame,
11612  FrameInspector* frame_inspector,
11613  Handle<ScopeInfo> scope_info,
11614  Handle<Context> function_context) {
11615  // Try to find the value of 'arguments' to pass as parameter. If it is not
11616  // found (that is the debugged function does not reference 'arguments' and
11617  // does not support eval) then create an 'arguments' object.
11618  int index;
11619  if (scope_info->StackLocalCount() > 0) {
11620  index = scope_info->StackSlotIndex(isolate->heap()->arguments_symbol());
11621  if (index != -1) {
11622  return Handle<Object>(frame->GetExpression(index), isolate);
11623  }
11624  }
11625 
11626  if (scope_info->HasHeapAllocatedLocals()) {
11627  VariableMode mode;
11628  InitializationFlag init_flag;
11629  index = scope_info->ContextSlotIndex(
11630  isolate->heap()->arguments_symbol(), &mode, &init_flag);
11631  if (index != -1) {
11632  return Handle<Object>(function_context->get(index), isolate);
11633  }
11634  }
11635 
11636  Handle<JSFunction> function(JSFunction::cast(frame_inspector->GetFunction()));
11637  int length = frame_inspector->GetParametersCount();
11638  Handle<JSObject> arguments =
11639  isolate->factory()->NewArgumentsObject(function, length);
11640  Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
11641 
11642  AssertNoAllocation no_gc;
11643  WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
11644  for (int i = 0; i < length; i++) {
11645  array->set(i, frame_inspector->GetParameter(i), mode);
11646  }
11647  arguments->set_elements(*array);
11648  return arguments;
11649 }
11650 
11651 
11652 static const char kSourceStr[] =
11653  "(function(arguments,__source__){return eval(__source__);})";
11654 
11655 
11656 // Evaluate a piece of JavaScript in the context of a stack frame for
11657 // debugging. This is accomplished by creating a new context which in its
11658 // extension part has all the parameters and locals of the function on the
11659 // stack frame. A function which calls eval with the code to evaluate is then
11660 // compiled in this context and called in this context. As this context
11661 // replaces the context of the function on the stack frame a new (empty)
11662 // function is created as well to be used as the closure for the context.
11663 // This function and the context acts as replacements for the function on the
11664 // stack frame presenting the same view of the values of parameters and
11665 // local variables as if the piece of JavaScript was evaluated at the point
11666 // where the function on the stack frame is currently stopped.
11667 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
11668  HandleScope scope(isolate);
11669 
11670  // Check the execution state and decode arguments frame and source to be
11671  // evaluated.
11672  ASSERT(args.length() == 6);
11673  Object* check_result;
11674  { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(
11675  RUNTIME_ARGUMENTS(isolate, args));
11676  if (!maybe_check_result->ToObject(&check_result)) {
11677  return maybe_check_result;
11678  }
11679  }
11680  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
11681  CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
11682  CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
11683  CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
11684  Handle<Object> additional_context(args[5]);
11685 
11686  // Handle the processing of break.
11687  DisableBreak disable_break_save(disable_break);
11688 
11689  // Get the frame where the debugging is performed.
11690  StackFrame::Id id = UnwrapFrameId(wrapped_id);
11691  JavaScriptFrameIterator it(isolate, id);
11692  JavaScriptFrame* frame = it.frame();
11693  FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
11694  Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
11695  Handle<ScopeInfo> scope_info(function->shared()->scope_info());
11696 
11697  // Traverse the saved contexts chain to find the active context for the
11698  // selected frame.
11699  SaveContext* save = FindSavedContextForFrame(isolate, frame);
11700 
11701  SaveContext savex(isolate);
11702  isolate->set_context(*(save->context()));
11703 
11704  // Create the (empty) function replacing the function on the stack frame for
11705  // the purpose of evaluating in the context created below. It is important
11706  // that this function does not describe any parameters and local variables
11707  // in the context. If it does then this will cause problems with the lookup
11708  // in Context::Lookup, where context slots for parameters and local variables
11709  // are looked at before the extension object.
11710  Handle<JSFunction> go_between =
11711  isolate->factory()->NewFunction(isolate->factory()->empty_string(),
11712  isolate->factory()->undefined_value());
11713  go_between->set_context(function->context());
11714 #ifdef DEBUG
11715  Handle<ScopeInfo> go_between_scope_info(go_between->shared()->scope_info());
11716  ASSERT(go_between_scope_info->ParameterCount() == 0);
11717  ASSERT(go_between_scope_info->ContextLocalCount() == 0);
11718 #endif
11719 
11720  // Materialize the content of the local scope into a JSObject.
11721  Handle<JSObject> local_scope = MaterializeLocalScopeWithFrameInspector(
11722  isolate, frame, &frame_inspector);
11723  RETURN_IF_EMPTY_HANDLE(isolate, local_scope);
11724 
11725  // Allocate a new context for the debug evaluation and set the extension
11726  // object build.
11727  Handle<Context> context =
11728  isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS,
11729  go_between);
11730 
11731  // Use the materialized local scope in a with context.
11732  context =
11733  isolate->factory()->NewWithContext(go_between, context, local_scope);
11734 
11735  // Copy any with contexts present and chain them in front of this context.
11736  Handle<Context> frame_context(Context::cast(frame->context()));
11737  Handle<Context> function_context;
11738  // Get the function's context if it has one.
11739  if (scope_info->HasContext()) {
11740  function_context = Handle<Context>(frame_context->declaration_context());
11741  }
11742  context = CopyNestedScopeContextChain(isolate,
11743  go_between,
11744  context,
11745  frame,
11746  inlined_jsframe_index);
11747  if (context.is_null()) {
11748  ASSERT(isolate->has_pending_exception());
11749  MaybeObject* exception = isolate->pending_exception();
11750  isolate->clear_pending_exception();
11751  return exception;
11752  }
11753 
11754  if (additional_context->IsJSObject()) {
11755  Handle<JSObject> extension = Handle<JSObject>::cast(additional_context);
11756  context =
11757  isolate->factory()->NewWithContext(go_between, context, extension);
11758  }
11759 
11760  // Wrap the evaluation statement in a new function compiled in the newly
11761  // created context. The function has one parameter which has to be called
11762  // 'arguments'. This it to have access to what would have been 'arguments' in
11763  // the function being debugged.
11764  // function(arguments,__source__) {return eval(__source__);}
11765 
11766  Handle<String> function_source =
11767  isolate->factory()->NewStringFromAscii(
11768  Vector<const char>(kSourceStr, sizeof(kSourceStr) - 1));
11769 
11770  // Currently, the eval code will be executed in non-strict mode,
11771  // even in the strict code context.
11772  Handle<SharedFunctionInfo> shared =
11773  Compiler::CompileEval(function_source,
11774  context,
11775  context->IsNativeContext(),
11776  CLASSIC_MODE,
11777  RelocInfo::kNoPosition);
11778  if (shared.is_null()) return Failure::Exception();
11779  Handle<JSFunction> compiled_function =
11780  isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context);
11781 
11782  // Invoke the result of the compilation to get the evaluation function.
11783  bool has_pending_exception;
11784  Handle<Object> receiver(frame->receiver(), isolate);
11785  Handle<Object> evaluation_function =
11786  Execution::Call(compiled_function, receiver, 0, NULL,
11787  &has_pending_exception);
11788  if (has_pending_exception) return Failure::Exception();
11789 
11790  Handle<Object> arguments = GetArgumentsObject(isolate,
11791  frame,
11792  &frame_inspector,
11793  scope_info,
11794  function_context);
11795 
11796  // Check if eval is blocked in the context and temporarily allow it
11797  // for debugger.
11798  Handle<Context> native_context = Handle<Context>(context->native_context());
11799  bool eval_disabled =
11800  native_context->allow_code_gen_from_strings()->IsFalse();
11801  if (eval_disabled) {
11802  native_context->set_allow_code_gen_from_strings(
11803  isolate->heap()->true_value());
11804  }
11805  // Invoke the evaluation function and return the result.
11806  Handle<Object> argv[] = { arguments, source };
11807  Handle<Object> result =
11808  Execution::Call(Handle<JSFunction>::cast(evaluation_function),
11809  receiver,
11810  ARRAY_SIZE(argv),
11811  argv,
11812  &has_pending_exception);
11813  if (eval_disabled) {
11814  native_context->set_allow_code_gen_from_strings(
11815  isolate->heap()->false_value());
11816  }
11817  if (has_pending_exception) return Failure::Exception();
11818 
11819  // Skip the global proxy as it has no properties and always delegates to the
11820  // real global object.
11821  if (result->IsJSGlobalProxy()) {
11822  result = Handle<JSObject>(JSObject::cast(result->GetPrototype()));
11823  }
11824 
11825  return *result;
11826 }
11827 
11828 
11829 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) {
11830  HandleScope scope(isolate);
11831 
11832  // Check the execution state and decode arguments frame and source to be
11833  // evaluated.
11834  ASSERT(args.length() == 4);
11835  Object* check_result;
11836  { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(
11837  RUNTIME_ARGUMENTS(isolate, args));
11838  if (!maybe_check_result->ToObject(&check_result)) {
11839  return maybe_check_result;
11840  }
11841  }
11842  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
11843  CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
11844  Handle<Object> additional_context(args[3]);
11845 
11846  // Handle the processing of break.
11847  DisableBreak disable_break_save(disable_break);
11848 
11849  // Enter the top context from before the debugger was invoked.
11850  SaveContext save(isolate);
11851  SaveContext* top = &save;
11852  while (top != NULL && *top->context() == *isolate->debug()->debug_context()) {
11853  top = top->prev();
11854  }
11855  if (top != NULL) {
11856  isolate->set_context(*top->context());
11857  }
11858 
11859  // Get the native context now set to the top context from before the
11860  // debugger was invoked.
11861  Handle<Context> context = isolate->native_context();
11862 
11863  bool is_global = true;
11864 
11865  if (additional_context->IsJSObject()) {
11866  // Create a new with context with the additional context information between
11867  // the context of the debugged function and the eval code to be executed.
11868  context = isolate->factory()->NewWithContext(
11869  Handle<JSFunction>(context->closure()),
11870  context,
11871  Handle<JSObject>::cast(additional_context));
11872  is_global = false;
11873  }
11874 
11875  // Compile the source to be evaluated.
11876  // Currently, the eval code will be executed in non-strict mode,
11877  // even in the strict code context.
11878  Handle<SharedFunctionInfo> shared =
11879  Compiler::CompileEval(source,
11880  context,
11881  is_global,
11882  CLASSIC_MODE,
11883  RelocInfo::kNoPosition);
11884  if (shared.is_null()) return Failure::Exception();
11885  Handle<JSFunction> compiled_function =
11886  Handle<JSFunction>(
11887  isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
11888  context));
11889 
11890  // Invoke the result of the compilation to get the evaluation function.
11891  bool has_pending_exception;
11892  Handle<Object> receiver = isolate->global_object();
11893  Handle<Object> result =
11894  Execution::Call(compiled_function, receiver, 0, NULL,
11895  &has_pending_exception);
11896  // Clear the oneshot breakpoints so that the debugger does not step further.
11897  isolate->debug()->ClearStepping();
11898  if (has_pending_exception) return Failure::Exception();
11899  return *result;
11900 }
11901 
11902 
11903 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetLoadedScripts) {
11904  HandleScope scope(isolate);
11905  ASSERT(args.length() == 0);
11906 
11907  // Fill the script objects.
11908  Handle<FixedArray> instances = isolate->debug()->GetLoadedScripts();
11909 
11910  // Convert the script objects to proper JS objects.
11911  for (int i = 0; i < instances->length(); i++) {
11912  Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
11913  // Get the script wrapper in a local handle before calling GetScriptWrapper,
11914  // because using
11915  // instances->set(i, *GetScriptWrapper(script))
11916  // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
11917  // already have dereferenced the instances handle.
11918  Handle<JSValue> wrapper = GetScriptWrapper(script);
11919  instances->set(i, *wrapper);
11920  }
11921 
11922  // Return result as a JS array.
11923  Handle<JSObject> result =
11924  isolate->factory()->NewJSObject(isolate->array_function());
11925  isolate->factory()->SetContent(Handle<JSArray>::cast(result), instances);
11926  return *result;
11927 }
11928 
11929 
11930 // Helper function used by Runtime_DebugReferencedBy below.
11931 static int DebugReferencedBy(HeapIterator* iterator,
11932  JSObject* target,
11933  Object* instance_filter, int max_references,
11934  FixedArray* instances, int instances_size,
11935  JSFunction* arguments_function) {
11936  NoHandleAllocation ha;
11937  AssertNoAllocation no_alloc;
11938 
11939  // Iterate the heap.
11940  int count = 0;
11941  JSObject* last = NULL;
11942  HeapObject* heap_obj = NULL;
11943  while (((heap_obj = iterator->next()) != NULL) &&
11944  (max_references == 0 || count < max_references)) {
11945  // Only look at all JSObjects.
11946  if (heap_obj->IsJSObject()) {
11947  // Skip context extension objects and argument arrays as these are
11948  // checked in the context of functions using them.
11949  JSObject* obj = JSObject::cast(heap_obj);
11950  if (obj->IsJSContextExtensionObject() ||
11951  obj->map()->constructor() == arguments_function) {
11952  continue;
11953  }
11954 
11955  // Check if the JS object has a reference to the object looked for.
11956  if (obj->ReferencesObject(target)) {
11957  // Check instance filter if supplied. This is normally used to avoid
11958  // references from mirror objects (see Runtime_IsInPrototypeChain).
11959  if (!instance_filter->IsUndefined()) {
11960  Object* V = obj;
11961  while (true) {
11962  Object* prototype = V->GetPrototype();
11963  if (prototype->IsNull()) {
11964  break;
11965  }
11966  if (instance_filter == prototype) {
11967  obj = NULL; // Don't add this object.
11968  break;
11969  }
11970  V = prototype;
11971  }
11972  }
11973 
11974  if (obj != NULL) {
11975  // Valid reference found add to instance array if supplied an update
11976  // count.
11977  if (instances != NULL && count < instances_size) {
11978  instances->set(count, obj);
11979  }
11980  last = obj;
11981  count++;
11982  }
11983  }
11984  }
11985  }
11986 
11987  // Check for circular reference only. This can happen when the object is only
11988  // referenced from mirrors and has a circular reference in which case the
11989  // object is not really alive and would have been garbage collected if not
11990  // referenced from the mirror.
11991  if (count == 1 && last == target) {
11992  count = 0;
11993  }
11994 
11995  // Return the number of referencing objects found.
11996  return count;
11997 }
11998 
11999 
12000 // Scan the heap for objects with direct references to an object
12001 // args[0]: the object to find references to
12002 // args[1]: constructor function for instances to exclude (Mirror)
12003 // args[2]: the the maximum number of objects to return
12004 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugReferencedBy) {
12005  ASSERT(args.length() == 3);
12006 
12007  // First perform a full GC in order to avoid references from dead objects.
12008  isolate->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
12009  "%DebugReferencedBy");
12010  // The heap iterator reserves the right to do a GC to make the heap iterable.
12011  // Due to the GC above we know it won't need to do that, but it seems cleaner
12012  // to get the heap iterator constructed before we start having unprotected
12013  // Object* locals that are not protected by handles.
12014 
12015  // Check parameters.
12016  CONVERT_ARG_CHECKED(JSObject, target, 0);
12017  Object* instance_filter = args[1];
12018  RUNTIME_ASSERT(instance_filter->IsUndefined() ||
12019  instance_filter->IsJSObject());
12020  CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
12021  RUNTIME_ASSERT(max_references >= 0);
12022 
12023 
12024  // Get the constructor function for context extension and arguments array.
12025  JSObject* arguments_boilerplate =
12026  isolate->context()->native_context()->arguments_boilerplate();
12027  JSFunction* arguments_function =
12028  JSFunction::cast(arguments_boilerplate->map()->constructor());
12029 
12030  // Get the number of referencing objects.
12031  int count;
12032  HeapIterator heap_iterator;
12033  count = DebugReferencedBy(&heap_iterator,
12034  target, instance_filter, max_references,
12035  NULL, 0, arguments_function);
12036 
12037  // Allocate an array to hold the result.
12038  Object* object;
12039  { MaybeObject* maybe_object = isolate->heap()->AllocateFixedArray(count);
12040  if (!maybe_object->ToObject(&object)) return maybe_object;
12041  }
12042  FixedArray* instances = FixedArray::cast(object);
12043 
12044  // Fill the referencing objects.
12045  // AllocateFixedArray above does not make the heap non-iterable.
12046  ASSERT(HEAP->IsHeapIterable());
12047  HeapIterator heap_iterator2;
12048  count = DebugReferencedBy(&heap_iterator2,
12049  target, instance_filter, max_references,
12050  instances, count, arguments_function);
12051 
12052  // Return result as JS array.
12053  Object* result;
12054  MaybeObject* maybe_result = isolate->heap()->AllocateJSObject(
12055  isolate->context()->native_context()->array_function());
12056  if (!maybe_result->ToObject(&result)) return maybe_result;
12057  return JSArray::cast(result)->SetContent(instances);
12058 }
12059 
12060 
12061 // Helper function used by Runtime_DebugConstructedBy below.
12062 static int DebugConstructedBy(HeapIterator* iterator,
12063  JSFunction* constructor,
12064  int max_references,
12065  FixedArray* instances,
12066  int instances_size) {
12067  AssertNoAllocation no_alloc;
12068 
12069  // Iterate the heap.
12070  int count = 0;
12071  HeapObject* heap_obj = NULL;
12072  while (((heap_obj = iterator->next()) != NULL) &&
12073  (max_references == 0 || count < max_references)) {
12074  // Only look at all JSObjects.
12075  if (heap_obj->IsJSObject()) {
12076  JSObject* obj = JSObject::cast(heap_obj);
12077  if (obj->map()->constructor() == constructor) {
12078  // Valid reference found add to instance array if supplied an update
12079  // count.
12080  if (instances != NULL && count < instances_size) {
12081  instances->set(count, obj);
12082  }
12083  count++;
12084  }
12085  }
12086  }
12087 
12088  // Return the number of referencing objects found.
12089  return count;
12090 }
12091 
12092 
12093 // Scan the heap for objects constructed by a specific function.
12094 // args[0]: the constructor to find instances of
12095 // args[1]: the the maximum number of objects to return
12096 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugConstructedBy) {
12097  ASSERT(args.length() == 2);
12098 
12099  // First perform a full GC in order to avoid dead objects.
12100  isolate->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
12101  "%DebugConstructedBy");
12102 
12103  // Check parameters.
12104  CONVERT_ARG_CHECKED(JSFunction, constructor, 0);
12105  CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
12106  RUNTIME_ASSERT(max_references >= 0);
12107 
12108  // Get the number of referencing objects.
12109  int count;
12110  HeapIterator heap_iterator;
12111  count = DebugConstructedBy(&heap_iterator,
12112  constructor,
12113  max_references,
12114  NULL,
12115  0);
12116 
12117  // Allocate an array to hold the result.
12118  Object* object;
12119  { MaybeObject* maybe_object = isolate->heap()->AllocateFixedArray(count);
12120  if (!maybe_object->ToObject(&object)) return maybe_object;
12121  }
12122  FixedArray* instances = FixedArray::cast(object);
12123 
12124  ASSERT(HEAP->IsHeapIterable());
12125  // Fill the referencing objects.
12126  HeapIterator heap_iterator2;
12127  count = DebugConstructedBy(&heap_iterator2,
12128  constructor,
12129  max_references,
12130  instances,
12131  count);
12132 
12133  // Return result as JS array.
12134  Object* result;
12135  { MaybeObject* maybe_result = isolate->heap()->AllocateJSObject(
12136  isolate->context()->native_context()->array_function());
12137  if (!maybe_result->ToObject(&result)) return maybe_result;
12138  }
12139  return JSArray::cast(result)->SetContent(instances);
12140 }
12141 
12142 
12143 // Find the effective prototype object as returned by __proto__.
12144 // args[0]: the object to find the prototype for.
12145 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPrototype) {
12146  ASSERT(args.length() == 1);
12147 
12148  CONVERT_ARG_CHECKED(JSObject, obj, 0);
12149 
12150  // Use the __proto__ accessor.
12151  return Accessors::ObjectPrototype.getter(obj, NULL);
12152 }
12153 
12154 
12155 // Patches script source (should be called upon BeforeCompile event).
12156 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugSetScriptSource) {
12157  HandleScope scope(isolate);
12158  ASSERT(args.length() == 2);
12159 
12160  CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
12161  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
12162 
12163  RUNTIME_ASSERT(script_wrapper->value()->IsScript());
12164  Handle<Script> script(Script::cast(script_wrapper->value()));
12165 
12166  int compilation_state = Smi::cast(script->compilation_state())->value();
12167  RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL);
12168  script->set_source(*source);
12169 
12170  return isolate->heap()->undefined_value();
12171 }
12172 
12173 
12174 RUNTIME_FUNCTION(MaybeObject*, Runtime_SystemBreak) {
12175  ASSERT(args.length() == 0);
12176  CPU::DebugBreak();
12177  return isolate->heap()->undefined_value();
12178 }
12179 
12180 
12181 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleFunction) {
12182 #ifdef DEBUG
12183  HandleScope scope(isolate);
12184  ASSERT(args.length() == 1);
12185  // Get the function and make sure it is compiled.
12186  CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
12188  return Failure::Exception();
12189  }
12190  func->code()->PrintLn();
12191 #endif // DEBUG
12192  return isolate->heap()->undefined_value();
12193 }
12194 
12195 
12196 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleConstructor) {
12197 #ifdef DEBUG
12198  HandleScope scope(isolate);
12199  ASSERT(args.length() == 1);
12200  // Get the function and make sure it is compiled.
12201  CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
12203  return Failure::Exception();
12204  }
12205  func->shared()->construct_stub()->PrintLn();
12206 #endif // DEBUG
12207  return isolate->heap()->undefined_value();
12208 }
12209 
12210 
12211 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetInferredName) {
12212  NoHandleAllocation ha;
12213  ASSERT(args.length() == 1);
12214 
12215  CONVERT_ARG_CHECKED(JSFunction, f, 0);
12216  return f->shared()->inferred_name();
12217 }
12218 
12219 
12220 static int FindSharedFunctionInfosForScript(HeapIterator* iterator,
12221  Script* script,
12222  FixedArray* buffer) {
12223  AssertNoAllocation no_allocations;
12224  int counter = 0;
12225  int buffer_size = buffer->length();
12226  for (HeapObject* obj = iterator->next();
12227  obj != NULL;
12228  obj = iterator->next()) {
12229  ASSERT(obj != NULL);
12230  if (!obj->IsSharedFunctionInfo()) {
12231  continue;
12232  }
12233  SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
12234  if (shared->script() != script) {
12235  continue;
12236  }
12237  if (counter < buffer_size) {
12238  buffer->set(counter, shared);
12239  }
12240  counter++;
12241  }
12242  return counter;
12243 }
12244 
12245 // For a script finds all SharedFunctionInfo's in the heap that points
12246 // to this script. Returns JSArray of SharedFunctionInfo wrapped
12247 // in OpaqueReferences.
12248 RUNTIME_FUNCTION(MaybeObject*,
12249  Runtime_LiveEditFindSharedFunctionInfosForScript) {
12250  CHECK(isolate->debugger()->live_edit_enabled());
12251  ASSERT(args.length() == 1);
12252  HandleScope scope(isolate);
12253  CONVERT_ARG_CHECKED(JSValue, script_value, 0);
12254 
12255  RUNTIME_ASSERT(script_value->value()->IsScript());
12256  Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
12257 
12258  const int kBufferSize = 32;
12259 
12260  Handle<FixedArray> array;
12261  array = isolate->factory()->NewFixedArray(kBufferSize);
12262  int number;
12263  {
12264  isolate->heap()->EnsureHeapIsIterable();
12265  AssertNoAllocation no_allocations;
12266  HeapIterator heap_iterator;
12267  Script* scr = *script;
12268  FixedArray* arr = *array;
12269  number = FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
12270  }
12271  if (number > kBufferSize) {
12272  array = isolate->factory()->NewFixedArray(number);
12273  isolate->heap()->EnsureHeapIsIterable();
12274  AssertNoAllocation no_allocations;
12275  HeapIterator heap_iterator;
12276  Script* scr = *script;
12277  FixedArray* arr = *array;
12278  FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
12279  }
12280 
12281  Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array);
12282  result->set_length(Smi::FromInt(number));
12283 
12284  LiveEdit::WrapSharedFunctionInfos(result);
12285 
12286  return *result;
12287 }
12288 
12289 // For a script calculates compilation information about all its functions.
12290 // The script source is explicitly specified by the second argument.
12291 // The source of the actual script is not used, however it is important that
12292 // all generated code keeps references to this particular instance of script.
12293 // Returns a JSArray of compilation infos. The array is ordered so that
12294 // each function with all its descendant is always stored in a continues range
12295 // with the function itself going first. The root function is a script function.
12296 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditGatherCompileInfo) {
12297  CHECK(isolate->debugger()->live_edit_enabled());
12298  ASSERT(args.length() == 2);
12299  HandleScope scope(isolate);
12300  CONVERT_ARG_CHECKED(JSValue, script, 0);
12301  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
12302 
12303  RUNTIME_ASSERT(script->value()->IsScript());
12304  Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
12305 
12306  JSArray* result = LiveEdit::GatherCompileInfo(script_handle, source);
12307 
12308  if (isolate->has_pending_exception()) {
12309  return Failure::Exception();
12310  }
12311 
12312  return result;
12313 }
12314 
12315 // Changes the source of the script to a new_source.
12316 // If old_script_name is provided (i.e. is a String), also creates a copy of
12317 // the script with its original source and sends notification to debugger.
12318 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceScript) {
12319  CHECK(isolate->debugger()->live_edit_enabled());
12320  ASSERT(args.length() == 3);
12321  HandleScope scope(isolate);
12322  CONVERT_ARG_CHECKED(JSValue, original_script_value, 0);
12323  CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
12324  Handle<Object> old_script_name(args[2], isolate);
12325 
12326  RUNTIME_ASSERT(original_script_value->value()->IsScript());
12327  Handle<Script> original_script(Script::cast(original_script_value->value()));
12328 
12329  Object* old_script = LiveEdit::ChangeScriptSource(original_script,
12330  new_source,
12331  old_script_name);
12332 
12333  if (old_script->IsScript()) {
12334  Handle<Script> script_handle(Script::cast(old_script));
12335  return *(GetScriptWrapper(script_handle));
12336  } else {
12337  return isolate->heap()->null_value();
12338  }
12339 }
12340 
12341 
12342 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSourceUpdated) {
12343  CHECK(isolate->debugger()->live_edit_enabled());
12344  ASSERT(args.length() == 1);
12345  HandleScope scope(isolate);
12346  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 0);
12347  return LiveEdit::FunctionSourceUpdated(shared_info);
12348 }
12349 
12350 
12351 // Replaces code of SharedFunctionInfo with a new one.
12352 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceFunctionCode) {
12353  CHECK(isolate->debugger()->live_edit_enabled());
12354  ASSERT(args.length() == 2);
12355  HandleScope scope(isolate);
12356  CONVERT_ARG_HANDLE_CHECKED(JSArray, new_compile_info, 0);
12357  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 1);
12358 
12359  return LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
12360 }
12361 
12362 // Connects SharedFunctionInfo to another script.
12363 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSetScript) {
12364  CHECK(isolate->debugger()->live_edit_enabled());
12365  ASSERT(args.length() == 2);
12366  HandleScope scope(isolate);
12367  Handle<Object> function_object(args[0], isolate);
12368  Handle<Object> script_object(args[1], isolate);
12369 
12370  if (function_object->IsJSValue()) {
12371  Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
12372  if (script_object->IsJSValue()) {
12373  RUNTIME_ASSERT(JSValue::cast(*script_object)->value()->IsScript());
12374  Script* script = Script::cast(JSValue::cast(*script_object)->value());
12375  script_object = Handle<Object>(script, isolate);
12376  }
12377 
12378  LiveEdit::SetFunctionScript(function_wrapper, script_object);
12379  } else {
12380  // Just ignore this. We may not have a SharedFunctionInfo for some functions
12381  // and we check it in this function.
12382  }
12383 
12384  return isolate->heap()->undefined_value();
12385 }
12386 
12387 
12388 // In a code of a parent function replaces original function as embedded object
12389 // with a substitution one.
12390 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceRefToNestedFunction) {
12391  CHECK(isolate->debugger()->live_edit_enabled());
12392  ASSERT(args.length() == 3);
12393  HandleScope scope(isolate);
12394 
12395  CONVERT_ARG_HANDLE_CHECKED(JSValue, parent_wrapper, 0);
12396  CONVERT_ARG_HANDLE_CHECKED(JSValue, orig_wrapper, 1);
12397  CONVERT_ARG_HANDLE_CHECKED(JSValue, subst_wrapper, 2);
12398 
12399  LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper,
12400  subst_wrapper);
12401 
12402  return isolate->heap()->undefined_value();
12403 }
12404 
12405 
12406 // Updates positions of a shared function info (first parameter) according
12407 // to script source change. Text change is described in second parameter as
12408 // array of groups of 3 numbers:
12409 // (change_begin, change_end, change_end_new_position).
12410 // Each group describes a change in text; groups are sorted by change_begin.
12411 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditPatchFunctionPositions) {
12412  CHECK(isolate->debugger()->live_edit_enabled());
12413  ASSERT(args.length() == 2);
12414  HandleScope scope(isolate);
12415  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
12416  CONVERT_ARG_HANDLE_CHECKED(JSArray, position_change_array, 1);
12417 
12418  return LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
12419 }
12420 
12421 
12422 // For array of SharedFunctionInfo's (each wrapped in JSValue)
12423 // checks that none of them have activations on stacks (of any thread).
12424 // Returns array of the same length with corresponding results of
12425 // LiveEdit::FunctionPatchabilityStatus type.
12426 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCheckAndDropActivations) {
12427  CHECK(isolate->debugger()->live_edit_enabled());
12428  ASSERT(args.length() == 2);
12429  HandleScope scope(isolate);
12430  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
12431  CONVERT_BOOLEAN_ARG_CHECKED(do_drop, 1);
12432 
12433  return *LiveEdit::CheckAndDropActivations(shared_array, do_drop,
12434  isolate->runtime_zone());
12435 }
12436 
12437 // Compares 2 strings line-by-line, then token-wise and returns diff in form
12438 // of JSArray of triplets (pos1, pos1_end, pos2_end) describing list
12439 // of diff chunks.
12440 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCompareStrings) {
12441  CHECK(isolate->debugger()->live_edit_enabled());
12442  ASSERT(args.length() == 2);
12443  HandleScope scope(isolate);
12444  CONVERT_ARG_HANDLE_CHECKED(String, s1, 0);
12445  CONVERT_ARG_HANDLE_CHECKED(String, s2, 1);
12446 
12447  return *LiveEdit::CompareStrings(s1, s2);
12448 }
12449 
12450 
12451 // Restarts a call frame and completely drops all frames above.
12452 // Returns true if successful. Otherwise returns undefined or an error message.
12453 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditRestartFrame) {
12454  CHECK(isolate->debugger()->live_edit_enabled());
12455  HandleScope scope(isolate);
12456  ASSERT(args.length() == 2);
12457 
12458  // Check arguments.
12459  Object* check;
12460  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12461  RUNTIME_ARGUMENTS(isolate, args));
12462  if (!maybe_check->ToObject(&check)) return maybe_check;
12463  }
12464  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
12465  Heap* heap = isolate->heap();
12466 
12467  // Find the relevant frame with the requested index.
12468  StackFrame::Id id = isolate->debug()->break_frame_id();
12469  if (id == StackFrame::NO_ID) {
12470  // If there are no JavaScript stack frames return undefined.
12471  return heap->undefined_value();
12472  }
12473 
12474  int count = 0;
12475  JavaScriptFrameIterator it(isolate, id);
12476  for (; !it.done(); it.Advance()) {
12477  if (index < count + it.frame()->GetInlineCount()) break;
12478  count += it.frame()->GetInlineCount();
12479  }
12480  if (it.done()) return heap->undefined_value();
12481 
12482  const char* error_message =
12483  LiveEdit::RestartFrame(it.frame(), isolate->runtime_zone());
12484  if (error_message) {
12485  return *(isolate->factory()->LookupAsciiSymbol(error_message));
12486  }
12487  return heap->true_value();
12488 }
12489 
12490 
12491 // A testing entry. Returns statement position which is the closest to
12492 // source_position.
12493 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionCodePositionFromSource) {
12494  CHECK(isolate->debugger()->live_edit_enabled());
12495  ASSERT(args.length() == 2);
12496  HandleScope scope(isolate);
12497  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
12498  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
12499 
12500  Handle<Code> code(function->code(), isolate);
12501 
12502  if (code->kind() != Code::FUNCTION &&
12503  code->kind() != Code::OPTIMIZED_FUNCTION) {
12504  return isolate->heap()->undefined_value();
12505  }
12506 
12507  RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION));
12508  int closest_pc = 0;
12509  int distance = kMaxInt;
12510  while (!it.done()) {
12511  int statement_position = static_cast<int>(it.rinfo()->data());
12512  // Check if this break point is closer that what was previously found.
12513  if (source_position <= statement_position &&
12514  statement_position - source_position < distance) {
12515  closest_pc =
12516  static_cast<int>(it.rinfo()->pc() - code->instruction_start());
12517  distance = statement_position - source_position;
12518  // Check whether we can't get any closer.
12519  if (distance == 0) break;
12520  }
12521  it.next();
12522  }
12523 
12524  return Smi::FromInt(closest_pc);
12525 }
12526 
12527 
12528 // Calls specified function with or without entering the debugger.
12529 // This is used in unit tests to run code as if debugger is entered or simply
12530 // to have a stack with C++ frame in the middle.
12531 RUNTIME_FUNCTION(MaybeObject*, Runtime_ExecuteInDebugContext) {
12532  ASSERT(args.length() == 2);
12533  HandleScope scope(isolate);
12534  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
12535  CONVERT_BOOLEAN_ARG_CHECKED(without_debugger, 1);
12536 
12537  Handle<Object> result;
12538  bool pending_exception;
12539  {
12540  if (without_debugger) {
12541  result = Execution::Call(function, isolate->global_object(), 0, NULL,
12542  &pending_exception);
12543  } else {
12544  EnterDebugger enter_debugger;
12545  result = Execution::Call(function, isolate->global_object(), 0, NULL,
12546  &pending_exception);
12547  }
12548  }
12549  if (!pending_exception) {
12550  return *result;
12551  } else {
12552  return Failure::Exception();
12553  }
12554 }
12555 
12556 
12557 // Sets a v8 flag.
12558 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFlags) {
12559  CONVERT_ARG_CHECKED(String, arg, 0);
12560  SmartArrayPointer<char> flags =
12561  arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
12562  FlagList::SetFlagsFromString(*flags, StrLength(*flags));
12563  return isolate->heap()->undefined_value();
12564 }
12565 
12566 
12567 // Performs a GC.
12568 // Presently, it only does a full GC.
12569 RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectGarbage) {
12570  isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage");
12571  return isolate->heap()->undefined_value();
12572 }
12573 
12574 
12575 // Gets the current heap usage.
12576 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHeapUsage) {
12577  int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
12578  if (!Smi::IsValid(usage)) {
12579  return *isolate->factory()->NewNumberFromInt(usage);
12580  }
12581  return Smi::FromInt(usage);
12582 }
12583 
12584 
12585 // Captures a live object list from the present heap.
12586 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLOLEnabled) {
12587 #ifdef LIVE_OBJECT_LIST
12588  return isolate->heap()->true_value();
12589 #else
12590  return isolate->heap()->false_value();
12591 #endif
12592 }
12593 
12594 
12595 // Captures a live object list from the present heap.
12596 RUNTIME_FUNCTION(MaybeObject*, Runtime_CaptureLOL) {
12597 #ifdef LIVE_OBJECT_LIST
12598  return LiveObjectList::Capture();
12599 #else
12600  return isolate->heap()->undefined_value();
12601 #endif
12602 }
12603 
12604 
12605 // Deletes the specified live object list.
12606 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteLOL) {
12607 #ifdef LIVE_OBJECT_LIST
12608  CONVERT_SMI_ARG_CHECKED(id, 0);
12609  bool success = LiveObjectList::Delete(id);
12610  return isolate->heap()->ToBoolean(success);
12611 #else
12612  return isolate->heap()->undefined_value();
12613 #endif
12614 }
12615 
12616 
12617 // Generates the response to a debugger request for a dump of the objects
12618 // contained in the difference between the captured live object lists
12619 // specified by id1 and id2.
12620 // If id1 is 0 (i.e. not a valid lol), then the whole of lol id2 will be
12621 // dumped.
12622 RUNTIME_FUNCTION(MaybeObject*, Runtime_DumpLOL) {
12623 #ifdef LIVE_OBJECT_LIST
12624  HandleScope scope;
12625  CONVERT_SMI_ARG_CHECKED(id1, 0);
12626  CONVERT_SMI_ARG_CHECKED(id2, 1);
12627  CONVERT_SMI_ARG_CHECKED(start, 2);
12628  CONVERT_SMI_ARG_CHECKED(count, 3);
12629  CONVERT_ARG_HANDLE_CHECKED(JSObject, filter_obj, 4);
12630  EnterDebugger enter_debugger;
12631  return LiveObjectList::Dump(id1, id2, start, count, filter_obj);
12632 #else
12633  return isolate->heap()->undefined_value();
12634 #endif
12635 }
12636 
12637 
12638 // Gets the specified object as requested by the debugger.
12639 // This is only used for obj ids shown in live object lists.
12640 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObj) {
12641 #ifdef LIVE_OBJECT_LIST
12642  CONVERT_SMI_ARG_CHECKED(obj_id, 0);
12643  Object* result = LiveObjectList::GetObj(obj_id);
12644  return result;
12645 #else
12646  return isolate->heap()->undefined_value();
12647 #endif
12648 }
12649 
12650 
12651 // Gets the obj id for the specified address if valid.
12652 // This is only used for obj ids shown in live object lists.
12653 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObjId) {
12654 #ifdef LIVE_OBJECT_LIST
12655  HandleScope scope;
12656  CONVERT_ARG_HANDLE_CHECKED(String, address, 0);
12657  Object* result = LiveObjectList::GetObjId(address);
12658  return result;
12659 #else
12660  return isolate->heap()->undefined_value();
12661 #endif
12662 }
12663 
12664 
12665 // Gets the retainers that references the specified object alive.
12666 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObjRetainers) {
12667 #ifdef LIVE_OBJECT_LIST
12668  HandleScope scope;
12669  CONVERT_SMI_ARG_CHECKED(obj_id, 0);
12670  RUNTIME_ASSERT(args[1]->IsUndefined() || args[1]->IsJSObject());
12671  RUNTIME_ASSERT(args[2]->IsUndefined() || args[2]->IsBoolean());
12672  RUNTIME_ASSERT(args[3]->IsUndefined() || args[3]->IsSmi());
12673  RUNTIME_ASSERT(args[4]->IsUndefined() || args[4]->IsSmi());
12674  CONVERT_ARG_HANDLE_CHECKED(JSObject, filter_obj, 5);
12675 
12676  Handle<JSObject> instance_filter;
12677  if (args[1]->IsJSObject()) {
12678  instance_filter = args.at<JSObject>(1);
12679  }
12680  bool verbose = false;
12681  if (args[2]->IsBoolean()) {
12682  verbose = args[2]->IsTrue();
12683  }
12684  int start = 0;
12685  if (args[3]->IsSmi()) {
12686  start = args.smi_at(3);
12687  }
12688  int limit = Smi::kMaxValue;
12689  if (args[4]->IsSmi()) {
12690  limit = args.smi_at(4);
12691  }
12692 
12693  return LiveObjectList::GetObjRetainers(obj_id,
12694  instance_filter,
12695  verbose,
12696  start,
12697  limit,
12698  filter_obj);
12699 #else
12700  return isolate->heap()->undefined_value();
12701 #endif
12702 }
12703 
12704 
12705 // Gets the reference path between 2 objects.
12706 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLPath) {
12707 #ifdef LIVE_OBJECT_LIST
12708  HandleScope scope;
12709  CONVERT_SMI_ARG_CHECKED(obj_id1, 0);
12710  CONVERT_SMI_ARG_CHECKED(obj_id2, 1);
12711  RUNTIME_ASSERT(args[2]->IsUndefined() || args[2]->IsJSObject());
12712 
12713  Handle<JSObject> instance_filter;
12714  if (args[2]->IsJSObject()) {
12715  instance_filter = args.at<JSObject>(2);
12716  }
12717 
12718  Object* result =
12719  LiveObjectList::GetPath(obj_id1, obj_id2, instance_filter);
12720  return result;
12721 #else
12722  return isolate->heap()->undefined_value();
12723 #endif
12724 }
12725 
12726 
12727 // Generates the response to a debugger request for a list of all
12728 // previously captured live object lists.
12729 RUNTIME_FUNCTION(MaybeObject*, Runtime_InfoLOL) {
12730 #ifdef LIVE_OBJECT_LIST
12731  CONVERT_SMI_ARG_CHECKED(start, 0);
12732  CONVERT_SMI_ARG_CHECKED(count, 1);
12733  return LiveObjectList::Info(start, count);
12734 #else
12735  return isolate->heap()->undefined_value();
12736 #endif
12737 }
12738 
12739 
12740 // Gets a dump of the specified object as requested by the debugger.
12741 // This is only used for obj ids shown in live object lists.
12742 RUNTIME_FUNCTION(MaybeObject*, Runtime_PrintLOLObj) {
12743 #ifdef LIVE_OBJECT_LIST
12744  HandleScope scope;
12745  CONVERT_SMI_ARG_CHECKED(obj_id, 0);
12746  Object* result = LiveObjectList::PrintObj(obj_id);
12747  return result;
12748 #else
12749  return isolate->heap()->undefined_value();
12750 #endif
12751 }
12752 
12753 
12754 // Resets and releases all previously captured live object lists.
12755 RUNTIME_FUNCTION(MaybeObject*, Runtime_ResetLOL) {
12756 #ifdef LIVE_OBJECT_LIST
12758  return isolate->heap()->undefined_value();
12759 #else
12760  return isolate->heap()->undefined_value();
12761 #endif
12762 }
12763 
12764 
12765 // Generates the response to a debugger request for a summary of the types
12766 // of objects in the difference between the captured live object lists
12767 // specified by id1 and id2.
12768 // If id1 is 0 (i.e. not a valid lol), then the whole of lol id2 will be
12769 // summarized.
12770 RUNTIME_FUNCTION(MaybeObject*, Runtime_SummarizeLOL) {
12771 #ifdef LIVE_OBJECT_LIST
12772  HandleScope scope;
12773  CONVERT_SMI_ARG_CHECKED(id1, 0);
12774  CONVERT_SMI_ARG_CHECKED(id2, 1);
12775  CONVERT_ARG_HANDLE_CHECKED(JSObject, filter_obj, 2);
12776 
12777  EnterDebugger enter_debugger;
12778  return LiveObjectList::Summarize(id1, id2, filter_obj);
12779 #else
12780  return isolate->heap()->undefined_value();
12781 #endif
12782 }
12783 
12784 #endif // ENABLE_DEBUGGER_SUPPORT
12785 
12786 
12787 RUNTIME_FUNCTION(MaybeObject*, Runtime_ProfilerResume) {
12788  NoHandleAllocation ha;
12790  return isolate->heap()->undefined_value();
12791 }
12792 
12793 
12794 RUNTIME_FUNCTION(MaybeObject*, Runtime_ProfilerPause) {
12795  NoHandleAllocation ha;
12797  return isolate->heap()->undefined_value();
12798 }
12799 
12800 
12801 // Finds the script object from the script data. NOTE: This operation uses
12802 // heap traversal to find the function generated for the source position
12803 // for the requested break point. For lazily compiled functions several heap
12804 // traversals might be required rendering this operation as a rather slow
12805 // operation. However for setting break points which is normally done through
12806 // some kind of user interaction the performance is not crucial.
12807 static Handle<Object> Runtime_GetScriptFromScriptName(
12808  Handle<String> script_name) {
12809  // Scan the heap for Script objects to find the script with the requested
12810  // script data.
12811  Handle<Script> script;
12812  script_name->GetHeap()->EnsureHeapIsIterable();
12813  AssertNoAllocation no_allocation_during_heap_iteration;
12814  HeapIterator iterator;
12815  HeapObject* obj = NULL;
12816  while (script.is_null() && ((obj = iterator.next()) != NULL)) {
12817  // If a script is found check if it has the script data requested.
12818  if (obj->IsScript()) {
12819  if (Script::cast(obj)->name()->IsString()) {
12820  if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) {
12821  script = Handle<Script>(Script::cast(obj));
12822  }
12823  }
12824  }
12825  }
12826 
12827  // If no script with the requested script data is found return undefined.
12828  if (script.is_null()) return FACTORY->undefined_value();
12829 
12830  // Return the script found.
12831  return GetScriptWrapper(script);
12832 }
12833 
12834 
12835 // Get the script object from script data. NOTE: Regarding performance
12836 // see the NOTE for GetScriptFromScriptData.
12837 // args[0]: script data for the script to find the source for
12838 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScript) {
12839  HandleScope scope(isolate);
12840 
12841  ASSERT(args.length() == 1);
12842 
12843  CONVERT_ARG_CHECKED(String, script_name, 0);
12844 
12845  // Find the requested script.
12846  Handle<Object> result =
12847  Runtime_GetScriptFromScriptName(Handle<String>(script_name));
12848  return *result;
12849 }
12850 
12851 
12852 // Determines whether the given stack frame should be displayed in
12853 // a stack trace. The caller is the error constructor that asked
12854 // for the stack trace to be collected. The first time a construct
12855 // call to this function is encountered it is skipped. The seen_caller
12856 // in/out parameter is used to remember if the caller has been seen
12857 // yet.
12858 static bool ShowFrameInStackTrace(StackFrame* raw_frame,
12859  Object* caller,
12860  bool* seen_caller) {
12861  // Only display JS frames.
12862  if (!raw_frame->is_java_script()) {
12863  return false;
12864  }
12865  JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
12866  Object* raw_fun = frame->function();
12867  // Not sure when this can happen but skip it just in case.
12868  if (!raw_fun->IsJSFunction()) {
12869  return false;
12870  }
12871  if ((raw_fun == caller) && !(*seen_caller)) {
12872  *seen_caller = true;
12873  return false;
12874  }
12875  // Skip all frames until we've seen the caller.
12876  if (!(*seen_caller)) return false;
12877  // Also, skip non-visible built-in functions and any call with the builtins
12878  // object as receiver, so as to not reveal either the builtins object or
12879  // an internal function.
12880  // The --builtins-in-stack-traces command line flag allows including
12881  // internal call sites in the stack trace for debugging purposes.
12882  if (!FLAG_builtins_in_stack_traces) {
12883  JSFunction* fun = JSFunction::cast(raw_fun);
12884  if (frame->receiver()->IsJSBuiltinsObject() ||
12885  (fun->IsBuiltin() && !fun->shared()->native())) {
12886  return false;
12887  }
12888  }
12889  return true;
12890 }
12891 
12892 
12893 // Collect the raw data for a stack trace. Returns an array of 4
12894 // element segments each containing a receiver, function, code and
12895 // native code offset.
12896 RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectStackTrace) {
12897  ASSERT_EQ(args.length(), 3);
12898  CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
12899  Handle<Object> caller = args.at<Object>(1);
12900  CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[2]);
12901 
12902  HandleScope scope(isolate);
12903  Factory* factory = isolate->factory();
12904 
12905  limit = Max(limit, 0); // Ensure that limit is not negative.
12906  int initial_size = Min(limit, 10);
12907  Handle<FixedArray> elements =
12908  factory->NewFixedArrayWithHoles(initial_size * 4);
12909 
12910  StackFrameIterator iter(isolate);
12911  // If the caller parameter is a function we skip frames until we're
12912  // under it before starting to collect.
12913  bool seen_caller = !caller->IsJSFunction();
12914  int cursor = 0;
12915  int frames_seen = 0;
12916  while (!iter.done() && frames_seen < limit) {
12917  StackFrame* raw_frame = iter.frame();
12918  if (ShowFrameInStackTrace(raw_frame, *caller, &seen_caller)) {
12919  frames_seen++;
12920  JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
12921  // Set initial size to the maximum inlining level + 1 for the outermost
12922  // function.
12924  frame->Summarize(&frames);
12925  for (int i = frames.length() - 1; i >= 0; i--) {
12926  if (cursor + 4 > elements->length()) {
12927  int new_capacity = JSObject::NewElementsCapacity(elements->length());
12928  Handle<FixedArray> new_elements =
12929  factory->NewFixedArrayWithHoles(new_capacity);
12930  for (int i = 0; i < cursor; i++) {
12931  new_elements->set(i, elements->get(i));
12932  }
12933  elements = new_elements;
12934  }
12935  ASSERT(cursor + 4 <= elements->length());
12936 
12937  Handle<Object> recv = frames[i].receiver();
12938  Handle<JSFunction> fun = frames[i].function();
12939  Handle<Code> code = frames[i].code();
12940  Handle<Smi> offset(Smi::FromInt(frames[i].offset()));
12941  elements->set(cursor++, *recv);
12942  elements->set(cursor++, *fun);
12943  elements->set(cursor++, *code);
12944  elements->set(cursor++, *offset);
12945  }
12946  }
12947  iter.Advance();
12948  }
12949  Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
12950  // Capture and attach a more detailed stack trace if necessary.
12951  isolate->CaptureAndSetCurrentStackTraceFor(error_object);
12952  result->set_length(Smi::FromInt(cursor));
12953  return *result;
12954 }
12955 
12956 
12957 // Returns V8 version as a string.
12958 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetV8Version) {
12959  ASSERT_EQ(args.length(), 0);
12960 
12961  NoHandleAllocation ha;
12962 
12963  const char* version_string = v8::V8::GetVersion();
12964 
12965  return isolate->heap()->AllocateStringFromAscii(CStrVector(version_string),
12966  NOT_TENURED);
12967 }
12968 
12969 
12970 RUNTIME_FUNCTION(MaybeObject*, Runtime_Abort) {
12971  ASSERT(args.length() == 2);
12972  OS::PrintError("abort: %s\n",
12973  reinterpret_cast<char*>(args[0]) + args.smi_at(1));
12974  isolate->PrintStack();
12975  OS::Abort();
12976  UNREACHABLE();
12977  return NULL;
12978 }
12979 
12980 
12981 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFromCache) {
12982  // This is only called from codegen, so checks might be more lax.
12984  Object* key = args[1];
12985 
12986  int finger_index = cache->finger_index();
12987  Object* o = cache->get(finger_index);
12988  if (o == key) {
12989  // The fastest case: hit the same place again.
12990  return cache->get(finger_index + 1);
12991  }
12992 
12993  for (int i = finger_index - 2;
12995  i -= 2) {
12996  o = cache->get(i);
12997  if (o == key) {
12998  cache->set_finger_index(i);
12999  return cache->get(i + 1);
13000  }
13001  }
13002 
13003  int size = cache->size();
13004  ASSERT(size <= cache->length());
13005 
13006  for (int i = size - 2; i > finger_index; i -= 2) {
13007  o = cache->get(i);
13008  if (o == key) {
13009  cache->set_finger_index(i);
13010  return cache->get(i + 1);
13011  }
13012  }
13013 
13014  // There is no value in the cache. Invoke the function and cache result.
13015  HandleScope scope(isolate);
13016 
13017  Handle<JSFunctionResultCache> cache_handle(cache);
13018  Handle<Object> key_handle(key);
13019  Handle<Object> value;
13020  {
13022  cache_handle->get(JSFunctionResultCache::kFactoryIndex)));
13023  // TODO(antonm): consider passing a receiver when constructing a cache.
13024  Handle<Object> receiver(isolate->native_context()->global_object());
13025  // This handle is nor shared, nor used later, so it's safe.
13026  Handle<Object> argv[] = { key_handle };
13027  bool pending_exception;
13028  value = Execution::Call(factory,
13029  receiver,
13030  ARRAY_SIZE(argv),
13031  argv,
13032  &pending_exception);
13033  if (pending_exception) return Failure::Exception();
13034  }
13035 
13036 #ifdef VERIFY_HEAP
13037  if (FLAG_verify_heap) {
13038  cache_handle->JSFunctionResultCacheVerify();
13039  }
13040 #endif
13041 
13042  // Function invocation may have cleared the cache. Reread all the data.
13043  finger_index = cache_handle->finger_index();
13044  size = cache_handle->size();
13045 
13046  // If we have spare room, put new data into it, otherwise evict post finger
13047  // entry which is likely to be the least recently used.
13048  int index = -1;
13049  if (size < cache_handle->length()) {
13050  cache_handle->set_size(size + JSFunctionResultCache::kEntrySize);
13051  index = size;
13052  } else {
13053  index = finger_index + JSFunctionResultCache::kEntrySize;
13054  if (index == cache_handle->length()) {
13056  }
13057  }
13058 
13059  ASSERT(index % 2 == 0);
13061  ASSERT(index < cache_handle->length());
13062 
13063  cache_handle->set(index, *key_handle);
13064  cache_handle->set(index + 1, *value);
13065  cache_handle->set_finger_index(index);
13066 
13067 #ifdef VERIFY_HEAP
13068  if (FLAG_verify_heap) {
13069  cache_handle->JSFunctionResultCacheVerify();
13070  }
13071 #endif
13072 
13073  return *value;
13074 }
13075 
13076 
13077 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewMessageObject) {
13078  HandleScope scope(isolate);
13080  CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 1);
13081  return *isolate->factory()->NewJSMessageObject(
13082  type,
13083  arguments,
13084  0,
13085  0,
13086  isolate->factory()->undefined_value(),
13087  isolate->factory()->undefined_value(),
13088  isolate->factory()->undefined_value());
13089 }
13090 
13091 
13092 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetType) {
13094  return message->type();
13095 }
13096 
13097 
13098 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetArguments) {
13100  return message->arguments();
13101 }
13102 
13103 
13104 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetStartPosition) {
13106  return Smi::FromInt(message->start_position());
13107 }
13108 
13109 
13110 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetScript) {
13112  return message->script();
13113 }
13114 
13115 
13116 #ifdef DEBUG
13117 // ListNatives is ONLY used by the fuzz-natives.js in debug mode
13118 // Exclude the code in release mode.
13119 RUNTIME_FUNCTION(MaybeObject*, Runtime_ListNatives) {
13120  ASSERT(args.length() == 0);
13121  HandleScope scope;
13122 #define COUNT_ENTRY(Name, argc, ressize) + 1
13123  int entry_count = 0
13124  RUNTIME_FUNCTION_LIST(COUNT_ENTRY)
13125  INLINE_FUNCTION_LIST(COUNT_ENTRY)
13126  INLINE_RUNTIME_FUNCTION_LIST(COUNT_ENTRY);
13127 #undef COUNT_ENTRY
13128  Factory* factory = isolate->factory();
13129  Handle<FixedArray> elements = factory->NewFixedArray(entry_count);
13130  int index = 0;
13131  bool inline_runtime_functions = false;
13132 #define ADD_ENTRY(Name, argc, ressize) \
13133  { \
13134  HandleScope inner; \
13135  Handle<String> name; \
13136  /* Inline runtime functions have an underscore in front of the name. */ \
13137  if (inline_runtime_functions) { \
13138  name = factory->NewStringFromAscii( \
13139  Vector<const char>("_" #Name, StrLength("_" #Name))); \
13140  } else { \
13141  name = factory->NewStringFromAscii( \
13142  Vector<const char>(#Name, StrLength(#Name))); \
13143  } \
13144  Handle<FixedArray> pair_elements = factory->NewFixedArray(2); \
13145  pair_elements->set(0, *name); \
13146  pair_elements->set(1, Smi::FromInt(argc)); \
13147  Handle<JSArray> pair = factory->NewJSArrayWithElements(pair_elements); \
13148  elements->set(index++, *pair); \
13149  }
13150  inline_runtime_functions = false;
13151  RUNTIME_FUNCTION_LIST(ADD_ENTRY)
13152  inline_runtime_functions = true;
13153  INLINE_FUNCTION_LIST(ADD_ENTRY)
13154  INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY)
13155 #undef ADD_ENTRY
13156  ASSERT_EQ(index, entry_count);
13157  Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
13158  return *result;
13159 }
13160 #endif
13161 
13162 
13163 RUNTIME_FUNCTION(MaybeObject*, Runtime_Log) {
13164  ASSERT(args.length() == 2);
13165  CONVERT_ARG_CHECKED(String, format, 0);
13166  CONVERT_ARG_CHECKED(JSArray, elms, 1);
13167  String::FlatContent format_content = format->GetFlatContent();
13168  RUNTIME_ASSERT(format_content.IsAscii());
13169  Vector<const char> chars = format_content.ToAsciiVector();
13170  LOGGER->LogRuntime(chars, elms);
13171  return isolate->heap()->undefined_value();
13172 }
13173 
13174 
13175 RUNTIME_FUNCTION(MaybeObject*, Runtime_IS_VAR) {
13176  UNREACHABLE(); // implemented as macro in the parser
13177  return NULL;
13178 }
13179 
13180 
13181 #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \
13182  RUNTIME_FUNCTION(MaybeObject*, Runtime_Has##Name) { \
13183  CONVERT_ARG_CHECKED(JSObject, obj, 0); \
13184  return isolate->heap()->ToBoolean(obj->Has##Name()); \
13185  }
13186 
13187 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiElements)
13188 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements)
13189 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements)
13190 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
13191 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
13192 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
13193 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalPixelElements)
13194 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
13195 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalByteElements)
13196 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedByteElements)
13197 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalShortElements)
13198 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedShortElements)
13199 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalIntElements)
13200 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedIntElements)
13201 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalFloatElements)
13202 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalDoubleElements)
13203 // Properties test sitting with elements tests - not fooling anyone.
13205 
13206 #undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
13207 
13208 
13209 RUNTIME_FUNCTION(MaybeObject*, Runtime_HaveSameMap) {
13210  ASSERT(args.length() == 2);
13211  CONVERT_ARG_CHECKED(JSObject, obj1, 0);
13212  CONVERT_ARG_CHECKED(JSObject, obj2, 1);
13213  return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
13214 }
13215 
13216 // ----------------------------------------------------------------------------
13217 // Implementation of Runtime
13218 
13219 #define F(name, number_of_args, result_size) \
13220  { Runtime::k##name, Runtime::RUNTIME, #name, \
13221  FUNCTION_ADDR(Runtime_##name), number_of_args, result_size },
13222 
13223 
13224 #define I(name, number_of_args, result_size) \
13225  { Runtime::kInline##name, Runtime::INLINE, \
13226  "_" #name, NULL, number_of_args, result_size },
13227 
13228 static const Runtime::Function kIntrinsicFunctions[] = {
13232 };
13233 
13234 
13236  Object* dictionary) {
13237  ASSERT(Isolate::Current()->heap() == heap);
13238  ASSERT(dictionary != NULL);
13239  ASSERT(StringDictionary::cast(dictionary)->NumberOfElements() == 0);
13240  for (int i = 0; i < kNumFunctions; ++i) {
13241  Object* name_symbol;
13242  { MaybeObject* maybe_name_symbol =
13243  heap->LookupAsciiSymbol(kIntrinsicFunctions[i].name);
13244  if (!maybe_name_symbol->ToObject(&name_symbol)) return maybe_name_symbol;
13245  }
13246  StringDictionary* string_dictionary = StringDictionary::cast(dictionary);
13247  { MaybeObject* maybe_dictionary = string_dictionary->Add(
13248  String::cast(name_symbol),
13249  Smi::FromInt(i),
13250  PropertyDetails(NONE, NORMAL));
13251  if (!maybe_dictionary->ToObject(&dictionary)) {
13252  // Non-recoverable failure. Calling code must restart heap
13253  // initialization.
13254  return maybe_dictionary;
13255  }
13256  }
13257  }
13258  return dictionary;
13259 }
13260 
13261 
13263  Heap* heap = name->GetHeap();
13264  int entry = heap->intrinsic_function_names()->FindEntry(*name);
13265  if (entry != kNotFound) {
13266  Object* smi_index = heap->intrinsic_function_names()->ValueAt(entry);
13267  int function_index = Smi::cast(smi_index)->value();
13268  return &(kIntrinsicFunctions[function_index]);
13269  }
13270  return NULL;
13271 }
13272 
13273 
13275  return &(kIntrinsicFunctions[static_cast<int>(id)]);
13276 }
13277 
13278 
13280  Isolate* isolate = Isolate::Current();
13281  Failure* failure = Failure::cast(result);
13282  if (failure->IsRetryAfterGC()) {
13283  if (isolate->heap()->new_space()->AddFreshPage()) {
13284  return;
13285  }
13286 
13287  // Try to do a garbage collection; ignore it if it fails. The C
13288  // entry stub will throw an out-of-memory exception in that case.
13289  isolate->heap()->CollectGarbage(failure->allocation_space(),
13290  "Runtime::PerformGC");
13291  } else {
13292  // Handle last resort GC and make sure to allow future allocations
13293  // to grow the heap without causing GCs (if possible).
13294  isolate->counters()->gc_last_resort_from_js()->Increment();
13296  "Runtime::PerformGC");
13297  }
13298 }
13299 
13300 
13301 } } // namespace v8::internal
static bool IsBlack(MarkBit mark_bit)
Definition: mark-compact.h:70
Object * GetPrototype()
Definition: objects.cc:725
byte * Address
Definition: globals.h:157
MaybeObject * AllocateRawString< SeqAsciiString >(Isolate *isolate, int length)
Definition: runtime.cc:5485
#define INLINE_FUNCTION_LIST(F)
Definition: runtime.h:503
void ClearTypeFeedbackCells(Heap *heap)
Definition: objects.cc:8429
const SwVfpRegister s2
static Handle< Object > New(Handle< JSFunction > func, int argc, Handle< Object > argv[], bool *pending_exception)
Definition: execution.cc:183
STATIC_CHECK((kStringRepresentationMask|kStringEncodingMask)==Internals::kFullStringRepresentationMask)
static Handle< Object > SetProperty(Handle< JSReceiver > object, Handle< String > key, Handle< Object > value, PropertyAttributes attributes, StrictModeFlag strict_mode)
Definition: objects.cc:1893
static const int kMaxLength
Definition: objects.h:2366
void Destroy(Object **location)
void FlattenString(Handle< String > string)
Definition: handles.cc:211
static bool CompileLazy(Handle< JSFunction > function, ClearExceptionFlag flag)
Definition: objects.cc:7643
Handle< JSObject > NewJSObject(Handle< JSFunction > constructor, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:904
Object * function() const
Definition: frames-inl.h:231
FixedArray * function_bindings()
Definition: objects-inl.h:4506
static Object *& Object_at(Address addr)
Definition: v8memory.h:75
Object * LookupAccessor(String *name, AccessorComponent component)
Definition: objects.cc:4813
static const int kMaxAsciiCharCode
Definition: objects.h:7327
static const int kNotFound
Definition: runtime.h:635
#define CONVERT_SMI_ARG_CHECKED(name, index)
Definition: runtime.cc:91
static const int kGlobalFieldIndex
Definition: objects.h:6675
void set(int index, Object *value)
Definition: objects-inl.h:1757
bool is_hidden_prototype()
Definition: objects.h:4725
#define CONVERT_DOUBLE_ARG_CHECKED(name, index)
Definition: runtime.cc:98
static const Function * FunctionForSymbol(Handle< String > name)
Definition: runtime.cc:13262
void PrintF(const char *format,...)
Definition: v8utils.cc:40
static Object * GetObjId(Handle< String > address)
static String * cast(Object *obj)
MUST_USE_RESULT MaybeObject * Add(Key key, Object *value, PropertyDetails details)
Definition: objects.cc:12556
int64_t ToUTC(int64_t time_ms)
Definition: date.h:131
MaybeObject * TryFlatten(PretenureFlag pretenure=NOT_TENURED)
Definition: objects-inl.h:2428
static bool UseCrankshaft()
Definition: v8.h:86
uint32_t NumberToUint32(Object *number)
Definition: v8conversions.h:43
Object * ToBoolean(bool condition)
Definition: heap-inl.h:652
bool Compile(Handle< String > replacement, int capture_count, int subject_length)
Definition: runtime.cc:2748
Isolate * isolate()
Definition: heap-inl.h:503
double DoubleToInteger(double x)
static void PerformGC(Object *result)
Definition: runtime.cc:13279
void set_length(Smi *length)
Definition: objects-inl.h:5278
Handle< FixedArray > NewFixedArrayWithHoles(int size, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:53
static uint32_t encode(T value)
Definition: utils.h:262
static Smi * FromInt(int value)
Definition: objects-inl.h:981
bool IsFastObjectElementsKind(ElementsKind kind)
Handle< String > NewSubString(Handle< String > str, int begin, int end)
Definition: factory.cc:251
v8::Handle< v8::Array > GetKeysForIndexedInterceptor(Handle< JSReceiver > receiver, Handle< JSObject > object)
Definition: handles.cc:572
MUST_USE_RESULT MaybeObject * AllocateJSFunctionProxy(Object *handler, Object *call_trap, Object *construct_trap, Object *prototype)
Definition: heap.cc:4160
Handle< SeqAsciiString > NewRawAsciiString(int length, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:225
Handle< ObjectHashTable > NewObjectHashTable(int at_least_space_for)
Definition: factory.cc:107
void ReportFailedAccessCheck(JSObject *receiver, v8::AccessType type)
Definition: isolate.cc:773
static void RevertStackCheckCode(Code *unoptimized_code, Code *check_code, Code *replacement_code)
bool HasRealNamedProperty(String *key)
Definition: objects.cc:10524
int isless(double x, double y)
void CollectAllGarbage(int flags, const char *gc_reason=NULL)
Definition: heap.cc:538
Handle< JSArray > NewJSArray(int capacity, ElementsKind elements_kind=TERMINAL_FAST_ELEMENTS_KIND, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:937
static MUST_USE_RESULT MaybeObject * ForceDeleteObjectProperty(Isolate *isolate, Handle< JSReceiver > object, Handle< Object > key)
Definition: runtime.cc:4357
MaybeObject * TransitionElements(Handle< Object > object, ElementsKind to_kind, Isolate *isolate)
Definition: runtime.cc:441
static HeapObject * cast(Object *obj)
static Handle< T > cast(Handle< S > that)
Definition: handles.h:81
bool MayNamedAccess(JSObject *receiver, Object *key, v8::AccessType type)
Definition: isolate.cc:828
double ceiling(double x)
bool is_access_check_needed()
Definition: objects-inl.h:3082
static const int kSourceFieldIndex
Definition: objects.h:6674
void Add(Object *value)
Definition: runtime.cc:2377
static bool Analyze(CompilationInfo *info)
Definition: scopes.cc:274
T Max(T a, T b)
Definition: utils.h:222
const int kSmiValueSize
Definition: v8.h:4061
static AccessorPair * cast(Object *obj)
MaybeObject * AllocateRawString< SeqTwoByteString >(Isolate *isolate, int length)
Definition: runtime.cc:5479
static const int64_t kMaxTimeBeforeUTCInMs
Definition: date.h:56
MUST_USE_RESULT MaybeObject * LookupAsciiSymbol(Vector< const char > str)
Definition: heap.cc:5449
static Failure * OutOfMemoryException()
Definition: objects-inl.h:1029
static Handle< FixedArray > GetElements(Handle< FixedArray > value)
Definition: parser.cc:3877
static const char * LocalTimezone(double time)
double fast_sqrt(double input)
int32_t uc32
Definition: globals.h:260
bool is_identical_to(const Handle< T > other) const
Definition: handles.h:67
static Handle< Object > CreateRegExpLiteral(Handle< JSFunction > constructor, Handle< String > pattern, Handle< String > flags, bool *has_pending_exception)
Definition: jsregexp.cc:66
Vector< const char > ToAsciiVector()
Definition: objects.h:7139
static Map * cast(Object *obj)
static bool Parse(Vector< Char > str, FixedArray *output, UnicodeCache *cache)
static bool Delete(int id)
static const uint32_t kMaxElementCount
Definition: objects.h:2144
Object * ToBoolean()
Definition: objects.cc:107
static Handle< Object > GetConstructorDelegate(Handle< Object > object)
Definition: execution.cc:287
T & at(int i) const
Definition: list.h:90
int int32_t
Definition: unicode.cc:47
static Failure * Exception()
Definition: objects-inl.h:1024
int Search(Vector< const SubjectChar > subject, int index)
const int kMaxInt
Definition: globals.h:210
#define CONVERT_STRICT_MODE_ARG_CHECKED(name, index)
Definition: runtime.cc:120
static MUST_USE_RESULT MaybeObject * SetObjectProperty(Isolate *isolate, Handle< Object > object, Handle< Object > key, Handle< Object > value, PropertyAttributes attr, StrictModeFlag strict_mode)
Definition: runtime.cc:4222
virtual void Summarize(List< FrameSummary > *frames)
Definition: frames.cc:741
PropertyDescriptorIndices
Definition: runtime.cc:1053
#define RUNTIME_ARGUMENTS(isolate, args)
Definition: arguments.h:125
void FindAsciiStringIndices(Vector< const char > subject, char pattern, ZoneList< int > *indices, unsigned int limit, Zone *zone)
Definition: runtime.cc:2834
static const Function * FunctionForId(FunctionId id)
Definition: runtime.cc:13274
static Handle< Object > TransitionElementsKind(Handle< JSObject > object, ElementsKind to_kind)
Definition: objects.cc:10072
BitField< int, 0, kStringBuilderConcatHelperLengthBits > StringBuilderSubstringLength
Definition: runtime.cc:2429
static bool CompileOptimized(Handle< JSFunction > function, BailoutId osr_ast_id, ClearExceptionFlag flag)
Definition: objects.cc:7659
#define ASSERT(condition)
Definition: checks.h:270
static Handle< Object > SetOwnElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, StrictModeFlag strict_mode)
Definition: objects.cc:9874
static void DeoptimizeFunction(JSFunction *function)
Handle< JSArray > ToArray()
Definition: runtime.cc:9261
int IntegerLog2(uint32_t value)
static ExternalUnsignedShortArray * cast(Object *obj)
Handle< JSArray > GetKeysFor(Handle< JSReceiver > object, bool *threw)
Definition: handles.cc:699
static MaybeObject * Summarize(int id1, int id2, Handle< JSObject > filter_obj)
static Script * cast(Object *obj)
unsigned short uint16_t
Definition: unicode.cc:46
ArrayConcatVisitor(Isolate *isolate, Handle< FixedArray > storage, bool fast_elements)
Definition: runtime.cc:9212
static Context * cast(Object *context)
Definition: contexts.h:212
static const int kMaxLength
Definition: objects.h:7608
static SharedFunctionInfo * cast(Object *obj)
void MaterializeHeapObjects(JavaScriptFrameIterator *it)
Definition: deoptimizer.cc:639
Object * DataAt(int index)
Definition: objects-inl.h:4744
Handle< Object > NewNumber(double value, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:597
#define CHECK(condition)
Definition: checks.h:56
static Type GetType(Handle< FixedArray > value)
Definition: parser.cc:3871
bool IsInternalError() const
Definition: objects-inl.h:1002
FixedArrayBuilder(Handle< FixedArray > backing_store)
Definition: runtime.cc:2347
static const int kSize
Definition: objects.h:8355
int isnan(double x)
Handle< Object > GetProperty(Handle< JSReceiver > obj, const char *name)
Definition: handles.cc:282
MUST_USE_RESULT MaybeObject * CopyJSObject(JSObject *source)
Definition: heap.cc:4254
#define RETURN_IF_EMPTY_HANDLE(isolate, call)
Definition: isolate.h:135
MUST_USE_RESULT MaybeObject * Copy()
Definition: objects.cc:5130
void ReplaceCode(Code *code)
Definition: objects-inl.h:4362
Factory * factory()
Definition: isolate.h:992
bool IsFastElementsKind(ElementsKind kind)
static Handle< SharedFunctionInfo > CompileEval(Handle< String > source, Handle< Context > context, bool is_global, LanguageMode language_mode, int scope_position)
Definition: compiler.cc:619
PropertyAttributes
void visit(uint32_t i, Handle< Object > elm)
Definition: runtime.cc:9225
int fpclassify(double x)
int ComputeParametersCount() const
Definition: frames.h:499
#define CONVERT_LANGUAGE_MODE_ARG(name, index)
Definition: runtime.cc:130
bool AsArrayIndex(uint32_t *index)
Definition: objects-inl.h:5028
static bool Is(uchar c)
Definition: unicode.cc:779
#define RUNTIME_FUNCTION_LIST(F)
Definition: runtime.h:493
Object * GetValue(int descriptor_number)
Definition: objects-inl.h:2123
int ToInt() const
Definition: utils.h:1012
static Object ** RawField(HeapObject *obj, int offset)
Definition: objects-inl.h:971
const int kIntSize
Definition: globals.h:217
#define RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, value)
Definition: isolate.h:120
static void RecompileParallel(Handle< JSFunction > function)
Definition: compiler.cc:839
static Smi * cast(Object *object)
Handle< String > FlattenGetString(Handle< String > string)
Definition: handles.cc:216
static bool Parse(CompilationInfo *info, int flags)
Definition: parser.cc:5944
void FindStringIndices(Isolate *isolate, Vector< const SubjectChar > subject, Vector< const PatternChar > pattern, ZoneList< int > *indices, unsigned int limit, Zone *zone)
Definition: runtime.cc:2857
bool Equals(String *other)
Definition: objects-inl.h:2419
Handle< String > SubString(Handle< String > str, int start, int end, PretenureFlag pretenure)
Definition: handles.cc:326
static const int kHeaderSize
Definition: objects.h:1262
#define V8_INFINITY
Definition: globals.h:32
static MUST_USE_RESULT MaybeObject * InitializeIntrinsicFunctionNames(Heap *heap, Object *dictionary)
Definition: runtime.cc:13235
static const int kMultilineFieldIndex
Definition: objects.h:6677
bool CollectGarbage(AllocationSpace space, GarbageCollector collector, const char *gc_reason, const char *collector_reason)
Definition: heap.cc:577
void set_closure(JSFunction *closure)
Definition: contexts.h:308
static ExternalShortArray * cast(Object *obj)
static ScopeInfo * cast(Object *object)
int get(uchar c, uchar n, uchar *result)
Definition: unicode-inl.h:49
static MarkBit MarkBitFrom(Address addr)
uint8_t byte
Definition: globals.h:156
#define CONVERT_ARG_CHECKED(Type, name, index)
Definition: runtime.cc:73
GlobalObject * global_object()
Definition: contexts.h:328
static const char * GetVersion()
Definition: api.cc:4394
double StringToDouble(UnicodeCache *unicode_cache, const char *str, int flags, double empty_string_val)
Definition: conversions.cc:41
Object * ValueAt(int entry)
Definition: objects.h:3067
const int kStringBuilderConcatHelperPositionBits
Definition: runtime.cc:2420
Object * InObjectPropertyAtPut(int index, Object *value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
Definition: objects-inl.h:1611
uint64_t ObjectPair
Definition: runtime.cc:8554
static MaybeObject * Info(int start_idx, int dump_limit)
Handle< SeededNumberDictionary > DictionaryAtNumberPut(Handle< SeededNumberDictionary >, uint32_t key, Handle< Object > value)
Definition: factory.cc:1088
Handle< Map > GetElementsTransitionMap(Handle< JSObject > object, ElementsKind elements_kind)
Definition: factory.cc:513
bool IsNull() const
Definition: v8.h:4490
static Handle< Object > CharAt(Handle< String > str, uint32_t index)
Definition: execution.cc:691
Handle< Object > Lookup(Handle< String > name, ContextLookupFlags flags, int *index, PropertyAttributes *attributes, BindingFlags *binding_flags)
Definition: contexts.cc:87
HANDLE HANDLE LPSTACKFRAME64 StackFrame
static void Abort()
static const int kLiteralNativeContextIndex
Definition: objects.h:6195
#define UNREACHABLE()
Definition: checks.h:50
void EnsureHeapIsIterable()
Definition: heap.cc:5109
Handle< JSArray > ToJSArray(Handle< JSArray > target_array)
Definition: runtime.cc:2404
double StringToInt(UnicodeCache *unicode_cache, String *str, int radix)
T * start() const
Definition: utils.h:390
static void PrintTop(FILE *file, bool print_args, bool print_line_number)
Definition: frames.cc:754
STATIC_ASSERT((FixedDoubleArray::kHeaderSize &kDoubleAlignmentMask)==0)
void set_global_object(GlobalObject *object)
Definition: contexts.h:333
Handle< SeqTwoByteString > NewRawTwoByteString(int length, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:234
static SeededNumberDictionary * cast(Object *obj)
Definition: objects.h:3236
Handle< Object > LookupSingleCharacterStringFromCode(uint32_t index)
Definition: handles.cc:318
void Apply(ReplacementStringBuilder *builder, int match_from, int match_to, int32_t *match)
Definition: runtime.cc:2796
MUST_USE_RESULT MaybeObject * SetContent(FixedArrayBase *storage)
Definition: objects-inl.h:5291
static const int kInputIndex
Definition: objects.h:8358
void SetExpectedNofProperties(Handle< JSFunction > func, int nof)
Definition: handles.cc:157
#define MUST_USE_RESULT
Definition: globals.h:346
#define CONVERT_BOOLEAN_ARG_CHECKED(name, index)
Definition: runtime.cc:84
static ExternalIntArray * cast(Object *obj)
static ThreadId Current()
Definition: isolate.h:154
Context * native_context()
Definition: contexts.cc:58
int FastD2IChecked(double x)
Definition: conversions.h:58
V8EXPORT Local< Value > GetPrototype()
Definition: api.cc:2900
static MUST_USE_RESULT MaybeObject * HandleStackGuardInterrupt(Isolate *isolate)
Definition: execution.cc:921
Handle< Object > Create(Object *value)
bool CodeGenerationFromStringsAllowed(Isolate *isolate, Handle< Context > context)
Definition: runtime.cc:9026
static bool IsValidElementsTransition(ElementsKind from_kind, ElementsKind to_kind)
Definition: objects.cc:10148
static bool IsValid(intptr_t value)
Definition: objects-inl.h:1059
static Failure * cast(MaybeObject *object)
Definition: objects-inl.h:496
bool ToArrayIndex(uint32_t *index)
Definition: objects-inl.h:1682
bool(* AllowCodeGenerationFromStringsCallback)(Local< Context > context)
Definition: v8.h:2737
static const int kNoGCFlags
Definition: heap.h:1081
Handle< ObjectHashSet > ObjectHashSetAdd(Handle< ObjectHashSet > table, Handle< Object > key)
Definition: handles.cc:841
const int kPointerSize
Definition: globals.h:220
static void AddSubjectSlice(FixedArrayBuilder *builder, int from, int to)
Definition: runtime.cc:2451
T * NewArray(size_t size)
Definition: allocation.h:83
Handle< String > StringReplaceOneCharWithString(Isolate *isolate, Handle< String > subject, Handle< String > search, Handle< String > replace, bool *found, int recursion_limit)
Definition: runtime.cc:3280
static const int kMaxWidth
Definition: unicode.h:297
Handle< Object > SetProperty(Handle< Object > object, Handle< Object > key, Handle< Object > value, PropertyAttributes attributes, StrictModeFlag strict_mode)
Definition: handles.cc:232
static void ResumeProfiler()
Definition: api.cc:5468
static Handle< JSArray > SetLastMatchInfo(Handle< JSArray > last_match_info, Handle< String > subject, int capture_count, int32_t *match)
Definition: jsregexp.cc:685
const char * DoubleToCString(double v, Vector< char > buffer)
Definition: conversions.cc:68
intptr_t OffsetFrom(T x)
Definition: utils.h:126
bool IsAligned(T value, U alignment)
Definition: utils.h:206
static MaybeObject * Dump(int id1, int id2, int start_idx, int dump_limit, Handle< JSObject > filter_obj)
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName)
Definition: globals.h:318
static SeqAsciiString * cast(Object *obj)
static const int64_t kMaxTimeInMs
Definition: date.h:51
double power_double_double(double x, double y)
Definition: assembler.cc:1214
void set_hash_field(uint32_t value)
Definition: objects-inl.h:2411
GlobalHandles * global_handles()
Definition: isolate.h:880
Handle< JSValue > GetScriptWrapper(Handle< Script > script)
Definition: handles.cc:366
static ExternalUnsignedByteArray * cast(Object *obj)
bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, ElementsKind to_kind)
AllocationSpace allocation_space() const
Definition: objects-inl.h:1012
void increase_index_offset(uint32_t delta)
Definition: runtime.cc:9253
static void TransformToFastProperties(Handle< JSObject > object, int unused_property_fields)
Definition: objects.cc:3392
const uintptr_t kUintptrAllBitsSet
Definition: globals.h:234
bool IsNone() const
Definition: utils.h:1019
static Handle< Object > Compile(Handle< JSRegExp > re, Handle< String > pattern, Handle< String > flags, Zone *zone)
Definition: jsregexp.cc:168
static void Enter(Heap *heap, String *key_string, Object *key_pattern, FixedArray *value_array, ResultsCacheType type)
Definition: heap.cc:2847
static bool decode(uint32_t value)
Definition: utils.h:273
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: globals.h:307
void Update(Map *map, String *name, int field_offset)
Definition: heap.cc:7107
static Handle< Object > SetLocalPropertyIgnoreAttributes(Handle< JSObject > object, Handle< String > key, Handle< Object > value, PropertyAttributes attributes)
Definition: objects.cc:2952
const Register pc
static Handle< Object > Exec(Handle< JSRegExp > regexp, Handle< String > subject, int index, Handle< JSArray > lastMatchInfo)
Definition: jsregexp.cc:232
Vector< const uc16 > ToUC16Vector()
Definition: objects.h:7145
double modulo(double x, double y)
int length() const
Definition: utils.h:384
void EnsureCapacity(int elements)
Definition: runtime.cc:2362
Handle< FixedArray > GetKeysInFixedArrayFor(Handle< JSReceiver > object, KeyCollectionType type, bool *threw)
Definition: handles.cc:606
static double TimeCurrentMillis()
static FixedDoubleArray * cast(Object *obj)
int isinf(double x)
static MUST_USE_RESULT Handle< Object > SetElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, PropertyAttributes attr, StrictModeFlag strict_mode, SetPropertyMode set_mode=SET_PROPERTY)
Definition: objects.cc:9886
bool IsTwoByteRepresentation()
Definition: objects-inl.h:296
Object * FastPropertyAt(int index)
Definition: objects-inl.h:1566
static ExternalPixelArray * cast(Object *obj)
bool IsFastSmiElementsKind(ElementsKind kind)
static const int kMakeHeapIterableMask
Definition: heap.h:1088
static const int kIgnoreCaseFieldIndex
Definition: objects.h:6676
double power_double_int(double x, int y)
Definition: assembler.cc:1199
AccessType
Definition: v8.h:2131
static const int kHeaderSize
Definition: objects.h:7517
Definition: v8.h:105
WriteBarrierMode GetWriteBarrierMode(const AssertNoAllocation &)
Definition: objects-inl.h:1831
int CompareChars(const lchar *lhs, const rchar *rhs, int chars)
Definition: utils.h:768
PropertyDetails GetDetails(int descriptor_number)
Definition: objects-inl.h:2129
static JavaScriptFrame * cast(StackFrame *frame)
Definition: frames.h:532
Failure * Throw(Object *exception, MessageLocation *location=NULL)
Definition: isolate.cc:945
static MaybeObject * GetObjRetainers(int obj_id, Handle< JSObject > instance_filter, bool verbose, int start, int count, Handle< JSObject > filter_obj)
static ScopeInfo * Empty()
Definition: scopeinfo.cc:152
unibrow::Mapping< unibrow::ToUppercase, 128 > * to_upper_mapping()
Definition: runtime.h:562
static uint32_t MakeArrayIndexHash(uint32_t value, int length)
Definition: objects.cc:7290
static Object * Lookup(Heap *heap, String *key_string, Object *key_pattern, ResultsCacheType type)
Definition: heap.cc:2814
void Lookup(String *name, LookupResult *result)
Definition: objects.cc:4309
activate correct semantics for inheriting readonliness false
Definition: flags.cc:141
void set_map_no_write_barrier(Map *value)
Definition: objects-inl.h:1154
Handle< FixedArray > CopyFixedArray(Handle< FixedArray > array)
Definition: factory.cc:523
static Handle< Object > Call(Handle< Object > callable, Handle< Object > receiver, int argc, Handle< Object > argv[], bool *pending_exception, bool convert_receiver=false)
Definition: execution.cc:150
static BailoutId None()
Definition: utils.h:1014
Vector< const char > CStrVector(const char *data)
Definition: utils.h:526
Handle< ObjectHashTable > PutIntoObjectHashTable(Handle< ObjectHashTable > table, Handle< Object > key, Handle< Object > value)
Definition: handles.cc:857
void VisitThread(Isolate *isolate, ThreadLocalTop *top)
Definition: runtime.cc:7945
int StrLength(const char *string)
Definition: utils.h:234
static Local< Context > ToLocal(v8::internal::Handle< v8::internal::Context > obj)
ReplacementStringBuilder(Heap *heap, Handle< String > subject, int estimated_part_count)
Definition: runtime.cc:2438
static JSArray * cast(Object *obj)
Handle< JSArray > NewJSArrayWithElements(Handle< FixedArrayBase > elements, ElementsKind elements_kind=TERMINAL_FAST_ELEMENTS_KIND, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:951
ContextLookupFlags
Definition: contexts.h:38
#define ASSERT_LT(v1, v2)
Definition: checks.h:274
Context * context()
Definition: isolate.h:520
static const int kMaxLoopNestingMarker
Definition: objects.h:4527
bool IsFastSmiOrObjectElementsKind(ElementsKind kind)
void FindStringIndicesDispatch(Isolate *isolate, String *subject, String *pattern, ZoneList< int > *indices, unsigned int limit, Zone *zone)
Definition: runtime.cc:2879
static int StringMatch(Isolate *isolate, Handle< String > sub, Handle< String > pat, int index)
Definition: runtime.cc:3355
const SwVfpRegister s1
static SeqTwoByteString * cast(Object *obj)
MUST_USE_RESULT MaybeObject * AllocateJSProxy(Object *handler, Object *prototype)
Definition: heap.cc:4140
LocalElementType HasLocalElement(uint32_t index)
Definition: objects.cc:9168
static ExternalDoubleArray * cast(Object *obj)
static ExternalFloatArray * cast(Object *obj)
FlatContent GetFlatContent()
Definition: objects.cc:6191
int ArithmeticShiftRight(int x, int s)
Definition: utils.h:117
void set(int index, double value)
Definition: objects-inl.h:1808
MaybeObject * AllocateRawString(Isolate *isolate, int length)
bool has_named_interceptor()
Definition: objects.h:4734
static MUST_USE_RESULT MaybeObject * FunctionSetPrototype(JSObject *object, Object *value, void *)
Definition: accessors.cc:467
int Lookup(Map *map, String *name)
Definition: heap.cc:7095
char * DoubleToPrecisionCString(double value, int p)
Definition: conversions.cc:292
int32_t DoubleToInt32(double x)
int InitialSemiSpaceSize()
Definition: heap.h:476
void LocalLookup(String *name, LookupResult *result)
Definition: objects.cc:4267
static HeapNumber * cast(Object *obj)
static void WriteToFlat(String *source, sinkchar *sink, int from, int to)
Definition: objects.cc:6891
const int kStringBuilderConcatHelperLengthBits
Definition: runtime.cc:2419
MUST_USE_RESULT MaybeObject * NormalizeElements()
Definition: objects.cc:3416
static StringDictionary * cast(Object *obj)
Definition: objects.h:3182
v8::Handle< v8::Array > GetKeysForNamedInterceptor(Handle< JSReceiver > receiver, Handle< JSObject > object)
Definition: handles.cc:547
static double nan_value()
static ObjectHashTable * cast(Object *obj)
Definition: objects.h:3340
bool is_null() const
Definition: handles.h:87
JavaScriptFrameIteratorTemp< StackFrameIterator > JavaScriptFrameIterator
Definition: frames.h:775
#define RUNTIME_ASSERT(value)
Definition: runtime.cc:67
static const int kAtomPatternIndex
Definition: objects.h:6635
static int SetFlagsFromString(const char *str, int len)
Definition: flags.cc:475
void AddSubjectSlice(int from, int to)
Definition: runtime.cc:2475
static JSGlobalPropertyCell * cast(Object *obj)
static bool EnsureCompiled(Handle< JSFunction > function, ClearExceptionFlag flag)
Definition: objects.cc:7668
static Deoptimizer * Grab(Isolate *isolate)
Definition: deoptimizer.cc:99
#define UNIMPLEMENTED()
Definition: checks.h:48
uint16_t uc16
Definition: globals.h:259
static bool IsUpperCaseChar(RuntimeState *runtime_state, uint16_t ch)
Definition: runtime.cc:6298
void set_extension(Object *object)
Definition: contexts.h:319
PropertyDetails DetailsAt(int entry)
Definition: objects.h:3077
Handle< Object > NewTypeError(const char *type, Vector< Handle< Object > > args)
Definition: factory.cc:630
static Handle< Object > CreateArrayLiteralBoilerplate(Isolate *isolate, Handle< FixedArray > literals, Handle< FixedArray > elements)
Definition: runtime.cc:461
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction pairs(ARM only)") DEFINE_bool(enable_unaligned_accesses
static Handle< Object > GetFunctionDelegate(Handle< Object > object)
Definition: execution.cc:229
static JSReceiver * cast(Object *obj)
static JSValue * cast(Object *obj)
Definition: objects-inl.h:4600
bool IsFunctionContext()
Definition: contexts.h:350
void AddString(Handle< String > string)
Definition: runtime.cc:2481
static void PrintError(const char *format,...)
static Handle< T > null()
Definition: handles.h:86
bool is_undetectable()
Definition: objects.h:4757
void MemsetPointer(T **dest, U *value, int counter)
Definition: v8utils.h:149
int SearchString(Isolate *isolate, Vector< const SubjectChar > subject, Vector< const PatternChar > pattern, int start_index)
void Set(int index, uint16_t value)
Definition: objects-inl.h:2470
static void IncrementLiveBytesFromMutator(Address address, int by)
Definition: spaces.cc:769
#define HEAP
Definition: isolate.h:1433
void set_is_access_check_needed(bool access_check_needed)
Definition: objects-inl.h:3073
MUST_USE_RESULT MaybeObject * GetProperty(String *key)
Definition: objects-inl.h:859
static MUST_USE_RESULT MaybeObject * GetObjectProperty(Isolate *isolate, Handle< Object > object, Handle< Object > key)
Definition: runtime.cc:3970
#define ASSERT_EQ(v1, v2)
Definition: checks.h:271
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if expose natives in global object expose gc extension number of stack frames to capture disable builtin natives files print a stack trace if an assertion failure occurs use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations prepare for turning on always opt minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions automatically set the debug break flag when debugger commands are in the queue always cause a debug break before aborting maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print more details following each garbage collection print amount of external allocated memory after each time it is adjusted flush code that we expect not to use again before full gc do incremental marking steps track object counts and memory usage use caching Perform compaction on every full GC Never perform compaction on full GC testing only Compact code space on full incremental collections Default seed for initializing random allows verbose printing trace parsing and preparsing Check icache flushes in ARM and MIPS simulator Stack alingment in bytes in print stack trace when throwing exceptions randomize hashes to avoid predictable hash Fixed seed to use to hash property keys(0 means random)" "(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(preemption
static const int kIndexIndex
Definition: objects.h:8357
Object * extension()
Definition: contexts.h:318
InstanceType instance_type()
Definition: objects-inl.h:3009
static MUST_USE_RESULT MaybeObject * ForceSetObjectProperty(Isolate *isolate, Handle< JSObject > object, Handle< Object > key, Handle< Object > value, PropertyAttributes attr)
Definition: runtime.cc:4304
static JSProxy * cast(Object *obj)
#define CONVERT_ARG_HANDLE_CHECKED(Type, name, index)
Definition: runtime.cc:77
void USE(T)
Definition: globals.h:289
int32_t NumberToInt32(Object *number)
Definition: v8conversions.h:37
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if expose natives in global object expose gc extension number of stack frames to capture disable builtin natives files print a stack trace if an assertion failure occurs use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations prepare for turning on always opt minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions automatically set the debug break flag when debugger commands are in the queue always cause a debug break before aborting maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print more details following each garbage collection print amount of external allocated memory after each time it is adjusted flush code that we expect not to use again before full gc do incremental marking steps track object counts and memory usage use caching Perform compaction on every full GC Never perform compaction on full GC testing only Compact code space on full incremental collections Default seed for initializing random allows verbose printing trace parsing and preparsing Check icache flushes in ARM and MIPS simulator Stack alingment in bytes in print stack trace when throwing exceptions randomize hashes to avoid predictable hash Fixed seed to use to hash property activate a timer that switches between V8 threads testing_bool_flag float flag Seed used for threading test randomness A filename with extra code to be included in the Print usage message
Definition: flags.cc:495
Counters * counters()
Definition: isolate.h:819
static Object * GetPath(int obj_id1, int obj_id2, Handle< JSObject > instance_filter)
#define ASSERT_NE(v1, v2)
Definition: checks.h:272
static AccessorInfo * cast(Object *obj)
static FixedArray * cast(Object *obj)
static const int kHeaderSize
Definition: objects.h:2173
Handle< FixedDoubleArray > CopyFixedDoubleArray(Handle< FixedDoubleArray > array)
Definition: factory.cc:528
void set_previous(Context *context)
Definition: contexts.h:315
static const int kBoundFunctionIndex
Definition: objects.h:6198
Failure * ThrowIllegalOperation()
Definition: isolate.cc:966
static Handle< Object > GetElement(Handle< Object > object, uint32_t index)
Definition: objects.cc:250
static Handle< Object > PreventExtensions(Handle< JSObject > object)
Definition: objects.cc:4138
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:38
bool IsEmpty() const
Definition: v8.h:209
bool HasCapacity(int elements)
Definition: runtime.cc:2356
#define FACTORY
Definition: isolate.h:1434
double FastI2D(int x)
Definition: conversions.h:76
static void NormalizeProperties(Handle< JSObject > object, PropertyNormalizationMode mode, int expected_additional_properties)
Definition: objects.cc:3275
void Reset(Input input)
Definition: unicode-inl.h:233
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
Definition: flags.cc:301
Definition: v8.h:1405
Object * get(int index)
Definition: objects-inl.h:1737
int FindEntry(String *key)
Definition: objects.cc:11351
static Handle< Object > ToString(Handle< Object > obj, bool *exc)
Definition: execution.cc:639
Handle< Object > ErrorMessageForCodeGenerationFromStrings()
Definition: contexts.cc:308
bool IsFastHoleyElementsKind(ElementsKind kind)
static const int kMaxInliningLevels
Definition: compiler.h:419
Handle< FixedArray > array()
Definition: runtime.cc:2392
V8EXPORT Local< Object > ToObject() const
Definition: api.cc:2353
static uint32_t & uint32_at(Address addr)
Definition: v8memory.h:47
void CreateFillerObjectAt(Address addr, int size)
Definition: heap.cc:3558
Handle< Object > ForceSetProperty(Handle< JSObject > object, Handle< Object > key, Handle< Object > value, PropertyAttributes attributes)
Definition: handles.cc:246
char * DoubleToExponentialCString(double value, int f)
Definition: conversions.cc:247
Handle< ObjectHashSet > ObjectHashSetRemove(Handle< ObjectHashSet > table, Handle< Object > key)
Definition: handles.cc:849
static bool is_valid(T value)
Definition: utils.h:257
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
BitField< int, kStringBuilderConcatHelperLengthBits, kStringBuilderConcatHelperPositionBits > StringBuilderSubstringPosition
Definition: runtime.cc:2433
static Object * GetObj(int obj_id)
static const int kMaxLength
Definition: objects.h:7386
bool HasLocalProperty(String *name)
Definition: objects-inl.h:5055
static ExternalByteArray * cast(Object *obj)
Vector< Handle< Object > > HandleVector(v8::internal::Handle< T > *elms, int length)
Definition: v8utils.h:117
char * DoubleToRadixCString(double value, int radix)
Definition: conversions.cc:362
static MaybeObject * Capture()
static const int kLastIndexFieldIndex
Definition: objects.h:6678
ActivationsFinder(JSFunction *function)
Definition: runtime.cc:7942
static GlobalObject * cast(Object *obj)
static const int kBoundThisIndex
Definition: objects.h:6199
static Object * PrintObj(int obj_id)
void DeleteArray(T *array)
Definition: allocation.h:91
T Min(T a, T b)
Definition: utils.h:229
void Flush(FILE *out)
Definition: v8utils.cc:65
#define INLINE_RUNTIME_FUNCTION_LIST(F)
Definition: runtime.h:541
static ConsString * cast(Object *obj)
static Handle< Object > TryGetConstructorDelegate(Handle< Object > object, bool *has_pending_exception)
Definition: execution.cc:313
#define LOGGER
Definition: isolate.h:1436
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if expose natives in global object expose gc extension number of stack frames to capture disable builtin natives files print a stack trace if an assertion failure occurs use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations prepare for turning on always opt minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions automatically set the debug break flag when debugger commands are in the queue always cause a debug break before aborting maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print more details following each garbage collection print amount of external allocated memory after each time it is adjusted flush code that we expect not to use again before full gc do incremental marking steps track object counts and memory usage use caching Perform compaction on every full GC Never perform compaction on full GC testing only Compact code space on full incremental collections Default seed for initializing random allows verbose printing trace parsing and preparsing Check icache flushes in ARM and MIPS simulator Stack alingment in bytes in print stack trace when throwing exceptions randomize hashes to avoid predictable hash Fixed seed to use to hash property activate a timer that switches between V8 threads testing_bool_flag float flag Seed used for threading test randomness A filename with extra code to be included in the Print usage including flags
Definition: flags.cc:495
static int NewElementsCapacity(int old_capacity)
Definition: objects.h:1806
static FixedArrayBase * cast(Object *object)
Definition: objects-inl.h:1731
#define CONVERT_NUMBER_CHECKED(type, name, Type, obj)
Definition: runtime.cc:105
static Context * NativeContextFromLiterals(FixedArray *literals)
Definition: objects.cc:7794
#define CONVERT_PROPERTY_DETAILS_CHECKED(name, index)
Definition: runtime.cc:113
Handle< String > NewConsString(Handle< String > first, Handle< String > second)
Definition: factory.cc:243
static const int kMaxValue
Definition: objects.h:1050
static void DebugBreak()
static const int kBoundArgumentsStartIndex
Definition: objects.h:6200
static ExternalUnsignedIntArray * cast(Object *obj)
static const int kNotFound
Definition: objects.h:2619
static void DefineAccessor(Handle< JSObject > object, Handle< String > name, Handle< Object > getter, Handle< Object > setter, PropertyAttributes attributes)
Definition: objects.cc:4576
void check(i::Vector< const char > string)
static void FatalProcessOutOfMemory(const char *location, bool take_snapshot=false)
NewSpace * new_space()
Definition: heap.h:505
MUST_USE_RESULT MaybeObject * CopyReplaceDescriptor(DescriptorArray *descriptors, Descriptor *descriptor, int index, TransitionFlag flag)
Definition: objects.cc:5223
#define ARRAY_SIZE(a)
Definition: globals.h:281
StringDictionary * property_dictionary()
Definition: objects-inl.h:4899
Handle< ObjectHashSet > NewObjectHashSet(int at_least_space_for)
Definition: factory.cc:99
static void PauseProfiler()
Definition: api.cc:5462
static const int kMaxLength
Definition: objects.h:7556
Object * GetParameter(int index) const
Definition: frames-inl.h:211
static Handle< Object > TryGetFunctionDelegate(Handle< Object > object, bool *has_pending_exception)
Definition: execution.cc:256
#define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name)
Definition: runtime.cc:13181
void set_allow_osr_at_loop_nesting_level(int level)
Definition: objects-inl.h:3298
static ObjectHashSet * cast(Object *obj)
Definition: objects.h:3320
static JSObject * cast(Object *obj)
void ClearInlineCaches()
Definition: objects.cc:8414
static const int kMaxArrayIndexSize
Definition: objects.h:7324
static MUST_USE_RESULT MaybeObject * GetElementOrCharAt(Isolate *isolate, Handle< Object > object, uint32_t index)
Definition: runtime.cc:3945
unsigned int uchar
Definition: unicode.h:40
int FastD2I(double x)
Definition: conversions.h:69
V8EXPORT Local< Uint32 > ToArrayIndex() const
Definition: api.cc:2633
Handle< T > CloseAndEscape(Handle< T > handle_value)
Definition: handles-inl.h:113
bool IsFastDoubleElementsKind(ElementsKind kind)
char * DoubleToFixedCString(double value, int f)
Definition: conversions.cc:143
Handle< SeededNumberDictionary > NewSeededNumberDictionary(int at_least_space_for)
Definition: factory.cc:81
static DeoptimizationInputData * cast(Object *obj)
FixedArrayBuilder(Isolate *isolate, int initial_capacity)
Definition: runtime.cc:2338
kPropertyAccessorsOffset kNamedPropertyHandlerOffset kInstanceTemplateOffset kAccessCheckInfoOffset kEvalFrominstructionsOffsetOffset kInstanceClassNameOffset flag
Definition: objects-inl.h:3923
static JSGlobalObject * cast(Object *obj)
static JSFunction * cast(Object *obj)