v8  3.11.10(node0.8.26)
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-array-pointer.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 global 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 global 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 global 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::GlobalContextFromLiterals(*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::GlobalContextFromLiterals(*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* global_context = isolate->context()->global_context();
478  Object* maybe_maps_array = global_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  boilerplate =
639  Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
640  if (boilerplate.is_null()) return Failure::Exception();
641  // Update the functions literal and return the boilerplate.
642  literals->set(literals_index, *boilerplate);
643  }
644  return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate));
645 }
646 
647 
648 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralShallow) {
649  HandleScope scope(isolate);
650  ASSERT(args.length() == 3);
652  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
654 
655  // Check if boilerplate exists. If not, create it first.
656  Handle<Object> boilerplate(literals->get(literals_index), isolate);
657  if (*boilerplate == isolate->heap()->undefined_value()) {
658  ASSERT(*elements != isolate->heap()->empty_fixed_array());
659  boilerplate =
660  Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
661  if (boilerplate.is_null()) return Failure::Exception();
662  // Update the functions literal and return the boilerplate.
663  literals->set(literals_index, *boilerplate);
664  }
665  if (JSObject::cast(*boilerplate)->elements()->map() ==
666  isolate->heap()->fixed_cow_array_map()) {
667  isolate->counters()->cow_arrays_created_runtime()->Increment();
668  }
669  return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate));
670 }
671 
672 
673 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSProxy) {
674  ASSERT(args.length() == 2);
675  Object* handler = args[0];
676  Object* prototype = args[1];
677  Object* used_prototype =
678  prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
679  return isolate->heap()->AllocateJSProxy(handler, used_prototype);
680 }
681 
682 
683 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSFunctionProxy) {
684  ASSERT(args.length() == 4);
685  Object* handler = args[0];
686  Object* call_trap = args[1];
687  Object* construct_trap = args[2];
688  Object* prototype = args[3];
689  Object* used_prototype =
690  prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
691  return isolate->heap()->AllocateJSFunctionProxy(
692  handler, call_trap, construct_trap, used_prototype);
693 }
694 
695 
696 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSProxy) {
697  ASSERT(args.length() == 1);
698  Object* obj = args[0];
699  return isolate->heap()->ToBoolean(obj->IsJSProxy());
700 }
701 
702 
703 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSFunctionProxy) {
704  ASSERT(args.length() == 1);
705  Object* obj = args[0];
706  return isolate->heap()->ToBoolean(obj->IsJSFunctionProxy());
707 }
708 
709 
710 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHandler) {
711  ASSERT(args.length() == 1);
712  CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
713  return proxy->handler();
714 }
715 
716 
717 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetCallTrap) {
718  ASSERT(args.length() == 1);
720  return proxy->call_trap();
721 }
722 
723 
724 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructTrap) {
725  ASSERT(args.length() == 1);
727  return proxy->construct_trap();
728 }
729 
730 
731 RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) {
732  ASSERT(args.length() == 1);
733  CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
734  proxy->Fix();
735  return isolate->heap()->undefined_value();
736 }
737 
738 
739 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInitialize) {
740  HandleScope scope(isolate);
741  ASSERT(args.length() == 1);
742  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
743  Handle<ObjectHashSet> table = isolate->factory()->NewObjectHashSet(0);
744  holder->set_table(*table);
745  return *holder;
746 }
747 
748 
749 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAdd) {
750  HandleScope scope(isolate);
751  ASSERT(args.length() == 2);
752  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
753  Handle<Object> key(args[1]);
754  Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
755  table = ObjectHashSetAdd(table, key);
756  holder->set_table(*table);
757  return isolate->heap()->undefined_symbol();
758 }
759 
760 
761 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetHas) {
762  HandleScope scope(isolate);
763  ASSERT(args.length() == 2);
764  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
765  Handle<Object> key(args[1]);
766  Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
767  return isolate->heap()->ToBoolean(table->Contains(*key));
768 }
769 
770 
771 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDelete) {
772  HandleScope scope(isolate);
773  ASSERT(args.length() == 2);
774  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
775  Handle<Object> key(args[1]);
776  Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
777  table = ObjectHashSetRemove(table, key);
778  holder->set_table(*table);
779  return isolate->heap()->undefined_symbol();
780 }
781 
782 
783 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapInitialize) {
784  HandleScope scope(isolate);
785  ASSERT(args.length() == 1);
786  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
787  Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
788  holder->set_table(*table);
789  return *holder;
790 }
791 
792 
793 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGet) {
794  HandleScope scope(isolate);
795  ASSERT(args.length() == 2);
796  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
797  Handle<Object> key(args[1]);
798  return ObjectHashTable::cast(holder->table())->Lookup(*key);
799 }
800 
801 
802 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapSet) {
803  HandleScope scope(isolate);
804  ASSERT(args.length() == 3);
805  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
806  Handle<Object> key(args[1]);
807  Handle<Object> value(args[2]);
808  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
809  Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
810  holder->set_table(*new_table);
811  return *value;
812 }
813 
814 
815 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapInitialize) {
816  HandleScope scope(isolate);
817  ASSERT(args.length() == 1);
819  ASSERT(weakmap->map()->inobject_properties() == 0);
820  Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
821  weakmap->set_table(*table);
822  weakmap->set_next(Smi::FromInt(0));
823  return *weakmap;
824 }
825 
826 
827 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapGet) {
828  NoHandleAllocation ha;
829  ASSERT(args.length() == 2);
832  return ObjectHashTable::cast(weakmap->table())->Lookup(*key);
833 }
834 
835 
836 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapSet) {
837  HandleScope scope(isolate);
838  ASSERT(args.length() == 3);
841  Handle<Object> value(args[2]);
842  Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table()));
843  Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
844  weakmap->set_table(*new_table);
845  return *value;
846 }
847 
848 
849 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) {
850  NoHandleAllocation ha;
851  ASSERT(args.length() == 1);
852  Object* obj = args[0];
853  if (!obj->IsJSObject()) return isolate->heap()->null_value();
854  return JSObject::cast(obj)->class_name();
855 }
856 
857 
858 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) {
859  NoHandleAllocation ha;
860  ASSERT(args.length() == 1);
861  CONVERT_ARG_CHECKED(JSReceiver, input_obj, 0);
862  Object* obj = input_obj;
863  // We don't expect access checks to be needed on JSProxy objects.
864  ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
865  do {
866  if (obj->IsAccessCheckNeeded() &&
867  !isolate->MayNamedAccess(JSObject::cast(obj),
868  isolate->heap()->Proto_symbol(),
869  v8::ACCESS_GET)) {
871  return isolate->heap()->undefined_value();
872  }
873  obj = obj->GetPrototype();
874  } while (obj->IsJSObject() &&
876  return obj;
877 }
878 
879 
880 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) {
881  NoHandleAllocation ha;
882  ASSERT(args.length() == 2);
883  // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
884  Object* O = args[0];
885  Object* V = args[1];
886  while (true) {
887  Object* prototype = V->GetPrototype();
888  if (prototype->IsNull()) return isolate->heap()->false_value();
889  if (O == prototype) return isolate->heap()->true_value();
890  V = prototype;
891  }
892 }
893 
894 
895 // Recursively traverses hidden prototypes if property is not found
896 static void GetOwnPropertyImplementation(JSObject* obj,
897  String* name,
898  LookupResult* result) {
899  obj->LocalLookupRealNamedProperty(name, result);
900 
901  if (!result->IsProperty()) {
902  Object* proto = obj->GetPrototype();
903  if (proto->IsJSObject() &&
905  GetOwnPropertyImplementation(JSObject::cast(proto),
906  name, result);
907  }
908 }
909 
910 
911 static bool CheckAccessException(LookupResult* result,
912  v8::AccessType access_type) {
913  if (result->type() == CALLBACKS) {
914  Object* callback = result->GetCallbackObject();
915  if (callback->IsAccessorInfo()) {
916  AccessorInfo* info = AccessorInfo::cast(callback);
917  bool can_access =
918  (access_type == v8::ACCESS_HAS &&
919  (info->all_can_read() || info->all_can_write())) ||
920  (access_type == v8::ACCESS_GET && info->all_can_read()) ||
921  (access_type == v8::ACCESS_SET && info->all_can_write());
922  return can_access;
923  }
924  }
925 
926  return false;
927 }
928 
929 
930 static bool CheckAccess(JSObject* obj,
931  String* name,
932  LookupResult* result,
933  v8::AccessType access_type) {
934  ASSERT(result->IsProperty());
935 
936  JSObject* holder = result->holder();
937  JSObject* current = obj;
938  Isolate* isolate = obj->GetIsolate();
939  while (true) {
940  if (current->IsAccessCheckNeeded() &&
941  !isolate->MayNamedAccess(current, name, access_type)) {
942  // Access check callback denied the access, but some properties
943  // can have a special permissions which override callbacks descision
944  // (currently see v8::AccessControl).
945  break;
946  }
947 
948  if (current == holder) {
949  return true;
950  }
951 
952  current = JSObject::cast(current->GetPrototype());
953  }
954 
955  // API callbacks can have per callback access exceptions.
956  switch (result->type()) {
957  case CALLBACKS: {
958  if (CheckAccessException(result, access_type)) {
959  return true;
960  }
961  break;
962  }
963  case INTERCEPTOR: {
964  // If the object has an interceptor, try real named properties.
965  // Overwrite the result to fetch the correct property later.
966  holder->LookupRealNamedProperty(name, result);
967  if (result->IsProperty()) {
968  if (CheckAccessException(result, access_type)) {
969  return true;
970  }
971  }
972  break;
973  }
974  default:
975  break;
976  }
977 
978  isolate->ReportFailedAccessCheck(current, access_type);
979  return false;
980 }
981 
982 
983 // TODO(1095): we should traverse hidden prototype hierachy as well.
984 static bool CheckElementAccess(JSObject* obj,
985  uint32_t index,
986  v8::AccessType access_type) {
987  if (obj->IsAccessCheckNeeded() &&
988  !obj->GetIsolate()->MayIndexedAccess(obj, index, access_type)) {
989  return false;
990  }
991 
992  return true;
993 }
994 
995 
996 // Enumerator used as indices into the array returned from GetOwnProperty
1006 };
1007 
1008 
1009 static MaybeObject* GetOwnProperty(Isolate* isolate,
1010  Handle<JSObject> obj,
1011  Handle<String> name) {
1012  Heap* heap = isolate->heap();
1013  Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
1014  Handle<JSArray> desc = isolate->factory()->NewJSArrayWithElements(elms);
1015  LookupResult result(isolate);
1016  // This could be an element.
1017  uint32_t index;
1018  if (name->AsArrayIndex(&index)) {
1019  switch (obj->HasLocalElement(index)) {
1021  return heap->undefined_value();
1022 
1024  // Special handling of string objects according to ECMAScript 5
1025  // 15.5.5.2. Note that this might be a string object with elements
1026  // other than the actual string value. This is covered by the
1027  // subsequent cases.
1028  Handle<JSValue> js_value = Handle<JSValue>::cast(obj);
1029  Handle<String> str(String::cast(js_value->value()));
1030  Handle<String> substr = SubString(str, index, index + 1, NOT_TENURED);
1031 
1032  elms->set(IS_ACCESSOR_INDEX, heap->false_value());
1033  elms->set(VALUE_INDEX, *substr);
1034  elms->set(WRITABLE_INDEX, heap->false_value());
1035  elms->set(ENUMERABLE_INDEX, heap->true_value());
1036  elms->set(CONFIGURABLE_INDEX, heap->false_value());
1037  return *desc;
1038  }
1039 
1041  case JSObject::FAST_ELEMENT: {
1042  elms->set(IS_ACCESSOR_INDEX, heap->false_value());
1043  Handle<Object> value = Object::GetElement(obj, index);
1044  RETURN_IF_EMPTY_HANDLE(isolate, value);
1045  elms->set(VALUE_INDEX, *value);
1046  elms->set(WRITABLE_INDEX, heap->true_value());
1047  elms->set(ENUMERABLE_INDEX, heap->true_value());
1048  elms->set(CONFIGURABLE_INDEX, heap->true_value());
1049  return *desc;
1050  }
1051 
1053  Handle<JSObject> holder = obj;
1054  if (obj->IsJSGlobalProxy()) {
1055  Object* proto = obj->GetPrototype();
1056  if (proto->IsNull()) return heap->undefined_value();
1057  ASSERT(proto->IsJSGlobalObject());
1058  holder = Handle<JSObject>(JSObject::cast(proto));
1059  }
1060  FixedArray* elements = FixedArray::cast(holder->elements());
1061  SeededNumberDictionary* dictionary = NULL;
1062  if (elements->map() == heap->non_strict_arguments_elements_map()) {
1063  dictionary = SeededNumberDictionary::cast(elements->get(1));
1064  } else {
1065  dictionary = SeededNumberDictionary::cast(elements);
1066  }
1067  int entry = dictionary->FindEntry(index);
1069  PropertyDetails details = dictionary->DetailsAt(entry);
1070  switch (details.type()) {
1071  case CALLBACKS: {
1072  // This is an accessor property with getter and/or setter.
1073  AccessorPair* accessors =
1074  AccessorPair::cast(dictionary->ValueAt(entry));
1075  elms->set(IS_ACCESSOR_INDEX, heap->true_value());
1076  if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) {
1077  elms->set(GETTER_INDEX, accessors->GetComponent(ACCESSOR_GETTER));
1078  }
1079  if (CheckElementAccess(*obj, index, v8::ACCESS_SET)) {
1080  elms->set(SETTER_INDEX, accessors->GetComponent(ACCESSOR_SETTER));
1081  }
1082  break;
1083  }
1084  case NORMAL: {
1085  // This is a data property.
1086  elms->set(IS_ACCESSOR_INDEX, heap->false_value());
1087  Handle<Object> value = Object::GetElement(obj, index);
1088  ASSERT(!value.is_null());
1089  elms->set(VALUE_INDEX, *value);
1090  elms->set(WRITABLE_INDEX, heap->ToBoolean(!details.IsReadOnly()));
1091  break;
1092  }
1093  default:
1094  UNREACHABLE();
1095  break;
1096  }
1097  elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!details.IsDontEnum()));
1098  elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!details.IsDontDelete()));
1099  return *desc;
1100  }
1101  }
1102  }
1103 
1104  // Use recursive implementation to also traverse hidden prototypes
1105  GetOwnPropertyImplementation(*obj, *name, &result);
1106 
1107  if (!result.IsProperty()) {
1108  return heap->undefined_value();
1109  }
1110 
1111  if (!CheckAccess(*obj, *name, &result, v8::ACCESS_HAS)) {
1112  return heap->false_value();
1113  }
1114 
1115  elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!result.IsDontEnum()));
1116  elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!result.IsDontDelete()));
1117 
1118  bool is_js_accessor = (result.type() == CALLBACKS) &&
1119  (result.GetCallbackObject()->IsAccessorPair());
1120 
1121  if (is_js_accessor) {
1122  // __defineGetter__/__defineSetter__ callback.
1123  elms->set(IS_ACCESSOR_INDEX, heap->true_value());
1124 
1125  AccessorPair* accessors = AccessorPair::cast(result.GetCallbackObject());
1126  if (CheckAccess(*obj, *name, &result, v8::ACCESS_GET)) {
1127  elms->set(GETTER_INDEX, accessors->GetComponent(ACCESSOR_GETTER));
1128  }
1129  if (CheckAccess(*obj, *name, &result, v8::ACCESS_SET)) {
1130  elms->set(SETTER_INDEX, accessors->GetComponent(ACCESSOR_SETTER));
1131  }
1132  } else {
1133  elms->set(IS_ACCESSOR_INDEX, heap->false_value());
1134  elms->set(WRITABLE_INDEX, heap->ToBoolean(!result.IsReadOnly()));
1135 
1136  PropertyAttributes attrs;
1137  Object* value;
1138  // GetProperty will check access and report any violations.
1139  { MaybeObject* maybe_value = obj->GetProperty(*obj, &result, *name, &attrs);
1140  if (!maybe_value->ToObject(&value)) return maybe_value;
1141  }
1142  elms->set(VALUE_INDEX, value);
1143  }
1144 
1145  return *desc;
1146 }
1147 
1148 
1149 // Returns an array with the property description:
1150 // if args[1] is not a property on args[0]
1151 // returns undefined
1152 // if args[1] is a data property on args[0]
1153 // [false, value, Writeable, Enumerable, Configurable]
1154 // if args[1] is an accessor on args[0]
1155 // [true, GetFunction, SetFunction, Enumerable, Configurable]
1156 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) {
1157  ASSERT(args.length() == 2);
1158  HandleScope scope(isolate);
1161  return GetOwnProperty(isolate, obj, name);
1162 }
1163 
1164 
1165 RUNTIME_FUNCTION(MaybeObject*, Runtime_PreventExtensions) {
1166  ASSERT(args.length() == 1);
1167  CONVERT_ARG_CHECKED(JSObject, obj, 0);
1168  return obj->PreventExtensions();
1169 }
1170 
1171 
1172 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsExtensible) {
1173  ASSERT(args.length() == 1);
1174  CONVERT_ARG_CHECKED(JSObject, obj, 0);
1175  if (obj->IsJSGlobalProxy()) {
1176  Object* proto = obj->GetPrototype();
1177  if (proto->IsNull()) return isolate->heap()->false_value();
1178  ASSERT(proto->IsJSGlobalObject());
1179  obj = JSObject::cast(proto);
1180  }
1181  return isolate->heap()->ToBoolean(obj->map()->is_extensible());
1182 }
1183 
1184 
1185 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpCompile) {
1186  HandleScope scope(isolate);
1187  ASSERT(args.length() == 3);
1189  CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
1191  Handle<Object> result = RegExpImpl::Compile(re, pattern, flags);
1192  if (result.is_null()) return Failure::Exception();
1193  return *result;
1194 }
1195 
1196 
1197 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateApiFunction) {
1198  HandleScope scope(isolate);
1199  ASSERT(args.length() == 1);
1201  return *isolate->factory()->CreateApiFunction(data);
1202 }
1203 
1204 
1205 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsTemplate) {
1206  ASSERT(args.length() == 1);
1207  Object* arg = args[0];
1208  bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
1209  return isolate->heap()->ToBoolean(result);
1210 }
1211 
1212 
1213 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetTemplateField) {
1214  ASSERT(args.length() == 2);
1215  CONVERT_ARG_CHECKED(HeapObject, templ, 0);
1216  CONVERT_SMI_ARG_CHECKED(index, 1)
1217  int offset = index * kPointerSize + HeapObject::kHeaderSize;
1218  InstanceType type = templ->map()->instance_type();
1220  type == OBJECT_TEMPLATE_INFO_TYPE);
1221  RUNTIME_ASSERT(offset > 0);
1222  if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
1224  } else {
1226  }
1227  return *HeapObject::RawField(templ, offset);
1228 }
1229 
1230 
1231 RUNTIME_FUNCTION(MaybeObject*, Runtime_DisableAccessChecks) {
1232  ASSERT(args.length() == 1);
1233  CONVERT_ARG_CHECKED(HeapObject, object, 0);
1234  Map* old_map = object->map();
1235  bool needs_access_checks = old_map->is_access_check_needed();
1236  if (needs_access_checks) {
1237  // Copy map so it won't interfere constructor's initial map.
1238  Object* new_map;
1239  { MaybeObject* maybe_new_map =
1241  if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
1242  }
1243 
1244  Map::cast(new_map)->set_is_access_check_needed(false);
1245  object->set_map(Map::cast(new_map));
1246  }
1247  return isolate->heap()->ToBoolean(needs_access_checks);
1248 }
1249 
1250 
1251 RUNTIME_FUNCTION(MaybeObject*, Runtime_EnableAccessChecks) {
1252  ASSERT(args.length() == 1);
1253  CONVERT_ARG_CHECKED(HeapObject, object, 0);
1254  Map* old_map = object->map();
1255  if (!old_map->is_access_check_needed()) {
1256  // Copy map so it won't interfere constructor's initial map.
1257  Object* new_map;
1258  { MaybeObject* maybe_new_map =
1260  if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
1261  }
1262 
1263  Map::cast(new_map)->set_is_access_check_needed(true);
1264  object->set_map(Map::cast(new_map));
1265  }
1266  return isolate->heap()->undefined_value();
1267 }
1268 
1269 
1270 static Failure* ThrowRedeclarationError(Isolate* isolate,
1271  const char* type,
1272  Handle<String> name) {
1273  HandleScope scope(isolate);
1274  Handle<Object> type_handle =
1275  isolate->factory()->NewStringFromAscii(CStrVector(type));
1276  Handle<Object> args[2] = { type_handle, name };
1277  Handle<Object> error =
1278  isolate->factory()->NewTypeError("redeclaration", HandleVector(args, 2));
1279  return isolate->Throw(*error);
1280 }
1281 
1282 
1283 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
1284  ASSERT(args.length() == 3);
1285  HandleScope scope(isolate);
1287  isolate->context()->global());
1288 
1289  Handle<Context> context = args.at<Context>(0);
1292 
1293  // Traverse the name/value pairs and set the properties.
1294  int length = pairs->length();
1295  for (int i = 0; i < length; i += 2) {
1296  HandleScope scope(isolate);
1297  Handle<String> name(String::cast(pairs->get(i)));
1298  Handle<Object> value(pairs->get(i + 1), isolate);
1299 
1300  // We have to declare a global const property. To capture we only
1301  // assign to it when evaluating the assignment for "const x =
1302  // <expr>" the initial value is the hole.
1303  bool is_var = value->IsUndefined();
1304  bool is_const = value->IsTheHole();
1305  bool is_function = value->IsSharedFunctionInfo();
1306  bool is_module = value->IsJSModule();
1307  ASSERT(is_var + is_const + is_function + is_module == 1);
1308 
1309  if (is_var || is_const) {
1310  // Lookup the property in the global object, and don't set the
1311  // value of the variable if the property is already there.
1312  // Do the lookup locally only, see ES5 errata.
1313  LookupResult lookup(isolate);
1314  if (FLAG_es52_globals)
1315  global->LocalLookup(*name, &lookup);
1316  else
1317  global->Lookup(*name, &lookup);
1318  if (lookup.IsProperty()) {
1319  // We found an existing property. Unless it was an interceptor
1320  // that claims the property is absent, skip this declaration.
1321  if (lookup.type() != INTERCEPTOR) continue;
1322  PropertyAttributes attributes = global->GetPropertyAttribute(*name);
1323  if (attributes != ABSENT) continue;
1324  // Fall-through and introduce the absent property by using
1325  // SetProperty.
1326  }
1327  } else if (is_function) {
1328  // Copy the function and update its context. Use it as value.
1331  Handle<JSFunction> function =
1332  isolate->factory()->NewFunctionFromSharedFunctionInfo(
1333  shared, context, TENURED);
1334  value = function;
1335  }
1336 
1337  LookupResult lookup(isolate);
1338  global->LocalLookup(*name, &lookup);
1339 
1340  // Compute the property attributes. According to ECMA-262,
1341  // the property must be non-configurable except in eval.
1342  int attr = NONE;
1343  bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
1344  if (!is_eval || is_module) {
1345  attr |= DONT_DELETE;
1346  }
1347  bool is_native = DeclareGlobalsNativeFlag::decode(flags);
1348  if (is_const || is_module || (is_native && is_function)) {
1349  attr |= READ_ONLY;
1350  }
1351 
1353 
1354  if (!lookup.IsProperty() || is_function || is_module) {
1355  // If the local property exists, check that we can reconfigure it
1356  // as required for function declarations.
1357  if (lookup.IsProperty() && lookup.IsDontDelete()) {
1358  if (lookup.IsReadOnly() || lookup.IsDontEnum() ||
1359  lookup.type() == CALLBACKS) {
1360  return ThrowRedeclarationError(
1361  isolate, is_function ? "function" : "module", name);
1362  }
1363  // If the existing property is not configurable, keep its attributes.
1364  attr = lookup.GetAttributes();
1365  }
1366  // Define or redefine own property.
1367  RETURN_IF_EMPTY_HANDLE(isolate,
1369  global, name, value, static_cast<PropertyAttributes>(attr)));
1370  } else {
1371  // Do a [[Put]] on the existing (own) property.
1372  RETURN_IF_EMPTY_HANDLE(isolate,
1374  global, name, value, static_cast<PropertyAttributes>(attr),
1375  language_mode == CLASSIC_MODE ? kNonStrictMode : kStrictMode));
1376  }
1377  }
1378 
1379  ASSERT(!isolate->has_pending_exception());
1380  return isolate->heap()->undefined_value();
1381 }
1382 
1383 
1384 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
1385  HandleScope scope(isolate);
1386  ASSERT(args.length() == 4);
1387 
1388  // Declarations are always made in a function or global context. In the
1389  // case of eval code, the context passed is the context of the caller,
1390  // which may be some nested context and not the declaration context.
1391  RUNTIME_ASSERT(args[0]->IsContext());
1392  Handle<Context> context(Context::cast(args[0])->declaration_context());
1393 
1394  Handle<String> name(String::cast(args[1]));
1395  PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2));
1396  RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE);
1397  Handle<Object> initial_value(args[3], isolate);
1398 
1399  int index;
1400  PropertyAttributes attributes;
1402  BindingFlags binding_flags;
1403  Handle<Object> holder =
1404  context->Lookup(name, flags, &index, &attributes, &binding_flags);
1405 
1406  if (attributes != ABSENT) {
1407  // The name was declared before; check for conflicting re-declarations.
1408  // Note: this is actually inconsistent with what happens for globals (where
1409  // we silently ignore such declarations).
1410  if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
1411  // Functions are not read-only.
1412  ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
1413  const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
1414  return ThrowRedeclarationError(isolate, type, name);
1415  }
1416 
1417  // Initialize it if necessary.
1418  if (*initial_value != NULL) {
1419  if (index >= 0) {
1420  ASSERT(holder.is_identical_to(context));
1421  if (((attributes & READ_ONLY) == 0) ||
1422  context->get(index)->IsTheHole()) {
1423  context->set(index, *initial_value);
1424  }
1425  } else {
1426  // Slow case: The property is in the context extension object of a
1427  // function context or the global object of a global context.
1428  Handle<JSObject> object = Handle<JSObject>::cast(holder);
1430  isolate,
1431  JSReceiver::SetProperty(object, name, initial_value, mode,
1432  kNonStrictMode));
1433  }
1434  }
1435 
1436  } else {
1437  // The property is not in the function context. It needs to be
1438  // "declared" in the function context's extension context or as a
1439  // property of the the global object.
1440  Handle<JSObject> object;
1441  if (context->has_extension()) {
1442  object = Handle<JSObject>(JSObject::cast(context->extension()));
1443  } else {
1444  // Context extension objects are allocated lazily.
1445  ASSERT(context->IsFunctionContext());
1446  object = isolate->factory()->NewJSObject(
1447  isolate->context_extension_function());
1448  context->set_extension(*object);
1449  }
1450  ASSERT(*object != NULL);
1451 
1452  // Declare the property by setting it to the initial value if provided,
1453  // or undefined, and use the correct mode (e.g. READ_ONLY attribute for
1454  // constant declarations).
1455  ASSERT(!object->HasLocalProperty(*name));
1456  Handle<Object> value(isolate->heap()->undefined_value(), isolate);
1457  if (*initial_value != NULL) value = initial_value;
1458  // Declaring a const context slot is a conflicting declaration if
1459  // there is a callback with that name in a prototype. It is
1460  // allowed to introduce const variables in
1461  // JSContextExtensionObjects. They are treated specially in
1462  // SetProperty and no setters are invoked for those since they are
1463  // not real JSObjects.
1464  if (initial_value->IsTheHole() &&
1465  !object->IsJSContextExtensionObject()) {
1466  LookupResult lookup(isolate);
1467  object->Lookup(*name, &lookup);
1468  if (lookup.IsFound() && (lookup.type() == CALLBACKS)) {
1469  return ThrowRedeclarationError(isolate, "const", name);
1470  }
1471  }
1472  if (object->IsJSGlobalObject()) {
1473  // Define own property on the global object.
1474  RETURN_IF_EMPTY_HANDLE(isolate,
1475  JSObject::SetLocalPropertyIgnoreAttributes(object, name, value, mode));
1476  } else {
1477  RETURN_IF_EMPTY_HANDLE(isolate,
1478  JSReceiver::SetProperty(object, name, value, mode, kNonStrictMode));
1479  }
1480  }
1481 
1482  return isolate->heap()->undefined_value();
1483 }
1484 
1485 
1486 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
1487  NoHandleAllocation nha;
1488  // args[0] == name
1489  // args[1] == language_mode
1490  // args[2] == value (optional)
1491 
1492  // Determine if we need to assign to the variable if it already
1493  // exists (based on the number of arguments).
1494  RUNTIME_ASSERT(args.length() == 2 || args.length() == 3);
1495  bool assign = args.length() == 3;
1496 
1498  GlobalObject* global = isolate->context()->global();
1499  RUNTIME_ASSERT(args[1]->IsSmi());
1500  CONVERT_LANGUAGE_MODE_ARG(language_mode, 1);
1501  StrictModeFlag strict_mode_flag = (language_mode == CLASSIC_MODE)
1503 
1504  // According to ECMA-262, section 12.2, page 62, the property must
1505  // not be deletable.
1506  PropertyAttributes attributes = DONT_DELETE;
1507 
1508  // Lookup the property locally in the global object. If it isn't
1509  // there, there is a property with this name in the prototype chain.
1510  // We follow Safari and Firefox behavior and only set the property
1511  // locally if there is an explicit initialization value that we have
1512  // to assign to the property.
1513  // Note that objects can have hidden prototypes, so we need to traverse
1514  // the whole chain of hidden prototypes to do a 'local' lookup.
1515  Object* object = global;
1516  LookupResult lookup(isolate);
1517  while (object->IsJSObject() &&
1518  JSObject::cast(object)->map()->is_hidden_prototype()) {
1519  JSObject* raw_holder = JSObject::cast(object);
1520  raw_holder->LocalLookup(*name, &lookup);
1521  if (lookup.IsFound() && lookup.type() == INTERCEPTOR) {
1522  HandleScope handle_scope(isolate);
1523  Handle<JSObject> holder(raw_holder);
1524  PropertyAttributes intercepted = holder->GetPropertyAttribute(*name);
1525  // Update the raw pointer in case it's changed due to GC.
1526  raw_holder = *holder;
1527  if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
1528  // Found an interceptor that's not read only.
1529  if (assign) {
1530  return raw_holder->SetProperty(
1531  &lookup, *name, args[2], attributes, strict_mode_flag);
1532  } else {
1533  return isolate->heap()->undefined_value();
1534  }
1535  }
1536  }
1537  object = raw_holder->GetPrototype();
1538  }
1539 
1540  // Reload global in case the loop above performed a GC.
1541  global = isolate->context()->global();
1542  if (assign) {
1543  return global->SetProperty(*name, args[2], attributes, strict_mode_flag);
1544  }
1545  return isolate->heap()->undefined_value();
1546 }
1547 
1548 
1549 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
1550  // All constants are declared with an initial value. The name
1551  // of the constant is the first argument and the initial value
1552  // is the second.
1553  RUNTIME_ASSERT(args.length() == 2);
1555  Handle<Object> value = args.at<Object>(1);
1556 
1557  // Get the current global object from top.
1558  GlobalObject* global = isolate->context()->global();
1559 
1560  // According to ECMA-262, section 12.2, page 62, the property must
1561  // not be deletable. Since it's a const, it must be READ_ONLY too.
1562  PropertyAttributes attributes =
1563  static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
1564 
1565  // Lookup the property locally in the global object. If it isn't
1566  // there, we add the property and take special precautions to always
1567  // add it as a local property even in case of callbacks in the
1568  // prototype chain (this rules out using SetProperty).
1569  // We use SetLocalPropertyIgnoreAttributes instead
1570  LookupResult lookup(isolate);
1571  global->LocalLookup(*name, &lookup);
1572  if (!lookup.IsProperty()) {
1573  return global->SetLocalPropertyIgnoreAttributes(*name,
1574  *value,
1575  attributes);
1576  }
1577 
1578  if (!lookup.IsReadOnly()) {
1579  // Restore global object from context (in case of GC) and continue
1580  // with setting the value.
1581  HandleScope handle_scope(isolate);
1582  Handle<GlobalObject> global(isolate->context()->global());
1583 
1584  // BUG 1213575: Handle the case where we have to set a read-only
1585  // property through an interceptor and only do it if it's
1586  // uninitialized, e.g. the hole. Nirk...
1587  // Passing non-strict mode because the property is writable.
1589  isolate,
1590  JSReceiver::SetProperty(global, name, value, attributes,
1591  kNonStrictMode));
1592  return *value;
1593  }
1594 
1595  // Set the value, but only if we're assigning the initial value to a
1596  // constant. For now, we determine this by checking if the
1597  // current value is the hole.
1598  // Strict mode handling not needed (const is disallowed in strict mode).
1599  PropertyType type = lookup.type();
1600  if (type == FIELD) {
1601  FixedArray* properties = global->properties();
1602  int index = lookup.GetFieldIndex();
1603  if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) {
1604  properties->set(index, *value);
1605  }
1606  } else if (type == NORMAL) {
1607  if (global->GetNormalizedProperty(&lookup)->IsTheHole() ||
1608  !lookup.IsReadOnly()) {
1609  global->SetNormalizedProperty(&lookup, *value);
1610  }
1611  } else {
1612  // Ignore re-initialization of constants that have already been
1613  // assigned a function value.
1614  ASSERT(lookup.IsReadOnly() && type == CONSTANT_FUNCTION);
1615  }
1616 
1617  // Use the set value as the result of the operation.
1618  return *value;
1619 }
1620 
1621 
1622 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) {
1623  HandleScope scope(isolate);
1624  ASSERT(args.length() == 3);
1625 
1626  Handle<Object> value(args[0], isolate);
1627  ASSERT(!value->IsTheHole());
1628 
1629  // Initializations are always done in a function or global context.
1630  RUNTIME_ASSERT(args[1]->IsContext());
1631  Handle<Context> context(Context::cast(args[1])->declaration_context());
1632 
1633  Handle<String> name(String::cast(args[2]));
1634 
1635  int index;
1636  PropertyAttributes attributes;
1638  BindingFlags binding_flags;
1639  Handle<Object> holder =
1640  context->Lookup(name, flags, &index, &attributes, &binding_flags);
1641 
1642  if (index >= 0) {
1643  ASSERT(holder->IsContext());
1644  // Property was found in a context. Perform the assignment if we
1645  // found some non-constant or an uninitialized constant.
1646  Handle<Context> context = Handle<Context>::cast(holder);
1647  if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) {
1648  context->set(index, *value);
1649  }
1650  return *value;
1651  }
1652 
1653  // The property could not be found, we introduce it as a property of the
1654  // global object.
1655  if (attributes == ABSENT) {
1657  isolate->context()->global());
1658  // Strict mode not needed (const disallowed in strict mode).
1660  isolate,
1661  JSReceiver::SetProperty(global, name, value, NONE, kNonStrictMode));
1662  return *value;
1663  }
1664 
1665  // The property was present in some function's context extension object,
1666  // as a property on the subject of a with, or as a property of the global
1667  // object.
1668  //
1669  // In most situations, eval-introduced consts should still be present in
1670  // the context extension object. However, because declaration and
1671  // initialization are separate, the property might have been deleted
1672  // before we reach the initialization point.
1673  //
1674  // Example:
1675  //
1676  // function f() { eval("delete x; const x;"); }
1677  //
1678  // In that case, the initialization behaves like a normal assignment.
1679  Handle<JSObject> object = Handle<JSObject>::cast(holder);
1680 
1681  if (*object == context->extension()) {
1682  // This is the property that was introduced by the const declaration.
1683  // Set it if it hasn't been set before. NOTE: We cannot use
1684  // GetProperty() to get the current value as it 'unholes' the value.
1685  LookupResult lookup(isolate);
1686  object->LocalLookupRealNamedProperty(*name, &lookup);
1687  ASSERT(lookup.IsFound()); // the property was declared
1688  ASSERT(lookup.IsReadOnly()); // and it was declared as read-only
1689 
1690  PropertyType type = lookup.type();
1691  if (type == FIELD) {
1692  FixedArray* properties = object->properties();
1693  int index = lookup.GetFieldIndex();
1694  if (properties->get(index)->IsTheHole()) {
1695  properties->set(index, *value);
1696  }
1697  } else if (type == NORMAL) {
1698  if (object->GetNormalizedProperty(&lookup)->IsTheHole()) {
1699  object->SetNormalizedProperty(&lookup, *value);
1700  }
1701  } else {
1702  // We should not reach here. Any real, named property should be
1703  // either a field or a dictionary slot.
1704  UNREACHABLE();
1705  }
1706  } else {
1707  // The property was found on some other object. Set it if it is not a
1708  // read-only property.
1709  if ((attributes & READ_ONLY) == 0) {
1710  // Strict mode not needed (const disallowed in strict mode).
1712  isolate,
1713  JSReceiver::SetProperty(object, name, value, attributes,
1714  kNonStrictMode));
1715  }
1716  }
1717 
1718  return *value;
1719 }
1720 
1721 
1722 RUNTIME_FUNCTION(MaybeObject*,
1723  Runtime_OptimizeObjectForAddingMultipleProperties) {
1724  HandleScope scope(isolate);
1725  ASSERT(args.length() == 2);
1727  CONVERT_SMI_ARG_CHECKED(properties, 1);
1728  if (object->HasFastProperties()) {
1730  }
1731  return *object;
1732 }
1733 
1734 
1735 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) {
1736  HandleScope scope(isolate);
1737  ASSERT(args.length() == 4);
1739  CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
1740  // Due to the way the JS calls are constructed this must be less than the
1741  // length of a string, i.e. it is always a Smi. We check anyway for security.
1742  CONVERT_SMI_ARG_CHECKED(index, 2);
1743  CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
1744  RUNTIME_ASSERT(last_match_info->HasFastObjectElements());
1745  RUNTIME_ASSERT(index >= 0);
1746  RUNTIME_ASSERT(index <= subject->length());
1747  isolate->counters()->regexp_entry_runtime()->Increment();
1748  Handle<Object> result = RegExpImpl::Exec(regexp,
1749  subject,
1750  index,
1751  last_match_info,
1752  isolate->zone());
1753  if (result.is_null()) return Failure::Exception();
1754  return *result;
1755 }
1756 
1757 
1758 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpConstructResult) {
1759  ASSERT(args.length() == 3);
1760  CONVERT_SMI_ARG_CHECKED(elements_count, 0);
1761  if (elements_count < 0 ||
1762  elements_count > FixedArray::kMaxLength ||
1763  !Smi::IsValid(elements_count)) {
1764  return isolate->ThrowIllegalOperation();
1765  }
1766  Object* new_object;
1767  { MaybeObject* maybe_new_object =
1768  isolate->heap()->AllocateFixedArrayWithHoles(elements_count);
1769  if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
1770  }
1771  FixedArray* elements = FixedArray::cast(new_object);
1772  { MaybeObject* maybe_new_object = isolate->heap()->AllocateRaw(
1774  if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
1775  }
1776  {
1777  AssertNoAllocation no_gc;
1778  HandleScope scope(isolate);
1779  reinterpret_cast<HeapObject*>(new_object)->
1780  set_map(isolate->global_context()->regexp_result_map());
1781  }
1782  JSArray* array = JSArray::cast(new_object);
1783  array->set_properties(isolate->heap()->empty_fixed_array());
1784  array->set_elements(elements);
1785  array->set_length(Smi::FromInt(elements_count));
1786  // Write in-object properties after the length of the array.
1789  return array;
1790 }
1791 
1792 
1793 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) {
1794  AssertNoAllocation no_alloc;
1795  ASSERT(args.length() == 5);
1796  CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
1797  CONVERT_ARG_CHECKED(String, source, 1);
1798  // If source is the empty string we set it to "(?:)" instead as
1799  // suggested by ECMA-262, 5th, section 15.10.4.1.
1800  if (source->length() == 0) source = isolate->heap()->query_colon_symbol();
1801 
1802  Object* global = args[2];
1803  if (!global->IsTrue()) global = isolate->heap()->false_value();
1804 
1805  Object* ignoreCase = args[3];
1806  if (!ignoreCase->IsTrue()) ignoreCase = isolate->heap()->false_value();
1807 
1808  Object* multiline = args[4];
1809  if (!multiline->IsTrue()) multiline = isolate->heap()->false_value();
1810 
1811  Map* map = regexp->map();
1812  Object* constructor = map->constructor();
1813  if (constructor->IsJSFunction() &&
1814  JSFunction::cast(constructor)->initial_map() == map) {
1815  // If we still have the original map, set in-object properties directly.
1816  regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, source);
1817  // Both true and false are immovable immortal objects so no need for write
1818  // barrier.
1819  regexp->InObjectPropertyAtPut(
1821  regexp->InObjectPropertyAtPut(
1823  regexp->InObjectPropertyAtPut(
1825  regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex,
1826  Smi::FromInt(0),
1827  SKIP_WRITE_BARRIER); // It's a Smi.
1828  return regexp;
1829  }
1830 
1831  // Map has changed, so use generic, but slower, method.
1832  PropertyAttributes final =
1834  PropertyAttributes writable =
1835  static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
1836  Heap* heap = isolate->heap();
1837  MaybeObject* result;
1838  result = regexp->SetLocalPropertyIgnoreAttributes(heap->source_symbol(),
1839  source,
1840  final);
1841  ASSERT(!result->IsFailure());
1842  result = regexp->SetLocalPropertyIgnoreAttributes(heap->global_symbol(),
1843  global,
1844  final);
1845  ASSERT(!result->IsFailure());
1846  result =
1847  regexp->SetLocalPropertyIgnoreAttributes(heap->ignore_case_symbol(),
1848  ignoreCase,
1849  final);
1850  ASSERT(!result->IsFailure());
1851  result = regexp->SetLocalPropertyIgnoreAttributes(heap->multiline_symbol(),
1852  multiline,
1853  final);
1854  ASSERT(!result->IsFailure());
1855  result =
1856  regexp->SetLocalPropertyIgnoreAttributes(heap->last_index_symbol(),
1857  Smi::FromInt(0),
1858  writable);
1859  ASSERT(!result->IsFailure());
1860  USE(result);
1861  return regexp;
1862 }
1863 
1864 
1865 RUNTIME_FUNCTION(MaybeObject*, Runtime_FinishArrayPrototypeSetup) {
1866  HandleScope scope(isolate);
1867  ASSERT(args.length() == 1);
1868  CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0);
1869  // This is necessary to enable fast checks for absence of elements
1870  // on Array.prototype and below.
1871  prototype->set_elements(isolate->heap()->empty_fixed_array());
1872  return Smi::FromInt(0);
1873 }
1874 
1875 
1876 static Handle<JSFunction> InstallBuiltin(Isolate* isolate,
1877  Handle<JSObject> holder,
1878  const char* name,
1879  Builtins::Name builtin_name) {
1880  Handle<String> key = isolate->factory()->LookupAsciiSymbol(name);
1881  Handle<Code> code(isolate->builtins()->builtin(builtin_name));
1882  Handle<JSFunction> optimized =
1883  isolate->factory()->NewFunction(key,
1886  code,
1887  false);
1888  optimized->shared()->DontAdaptArguments();
1889  JSReceiver::SetProperty(holder, key, optimized, NONE, kStrictMode);
1890  return optimized;
1891 }
1892 
1893 
1894 RUNTIME_FUNCTION(MaybeObject*, Runtime_SpecialArrayFunctions) {
1895  HandleScope scope(isolate);
1896  ASSERT(args.length() == 1);
1898 
1899  InstallBuiltin(isolate, holder, "pop", Builtins::kArrayPop);
1900  InstallBuiltin(isolate, holder, "push", Builtins::kArrayPush);
1901  InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift);
1902  InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift);
1903  InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice);
1904  InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
1905  InstallBuiltin(isolate, holder, "concat", Builtins::kArrayConcat);
1906 
1907  return *holder;
1908 }
1909 
1910 
1911 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultReceiver) {
1912  ASSERT(args.length() == 1);
1913  CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
1914 
1915  if (!callable->IsJSFunction()) {
1916  HandleScope scope(isolate);
1917  bool threw = false;
1918  Handle<Object> delegate =
1920  if (threw) return Failure::Exception();
1921  callable = JSFunction::cast(*delegate);
1922  }
1923  JSFunction* function = JSFunction::cast(callable);
1924 
1925  SharedFunctionInfo* shared = function->shared();
1926  if (shared->native() || !shared->is_classic_mode()) {
1927  return isolate->heap()->undefined_value();
1928  }
1929  // Returns undefined for strict or native functions, or
1930  // the associated global receiver for "normal" functions.
1931 
1932  Context* global_context =
1933  function->context()->global()->global_context();
1934  return global_context->global()->global_receiver();
1935 }
1936 
1937 
1938 RUNTIME_FUNCTION(MaybeObject*, Runtime_MaterializeRegExpLiteral) {
1939  HandleScope scope(isolate);
1940  ASSERT(args.length() == 4);
1941  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
1942  int index = args.smi_at(1);
1943  Handle<String> pattern = args.at<String>(2);
1944  Handle<String> flags = args.at<String>(3);
1945 
1946  // Get the RegExp function from the context in the literals array.
1947  // This is the RegExp function from the context in which the
1948  // function was created. We do not use the RegExp function from the
1949  // current global context because this might be the RegExp function
1950  // from another context which we should not have access to.
1951  Handle<JSFunction> constructor =
1953  JSFunction::GlobalContextFromLiterals(*literals)->regexp_function());
1954  // Compute the regular expression literal.
1955  bool has_pending_exception;
1956  Handle<Object> regexp =
1957  RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
1958  &has_pending_exception);
1959  if (has_pending_exception) {
1960  ASSERT(isolate->has_pending_exception());
1961  return Failure::Exception();
1962  }
1963  literals->set(index, *regexp);
1964  return *regexp;
1965 }
1966 
1967 
1968 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetName) {
1969  NoHandleAllocation ha;
1970  ASSERT(args.length() == 1);
1971 
1973  return f->shared()->name();
1974 }
1975 
1976 
1977 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetName) {
1978  NoHandleAllocation ha;
1979  ASSERT(args.length() == 2);
1980 
1982  CONVERT_ARG_CHECKED(String, name, 1);
1983  f->shared()->set_name(name);
1984  return isolate->heap()->undefined_value();
1985 }
1986 
1987 
1988 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionNameShouldPrintAsAnonymous) {
1989  NoHandleAllocation ha;
1990  ASSERT(args.length() == 1);
1992  return isolate->heap()->ToBoolean(
1993  f->shared()->name_should_print_as_anonymous());
1994 }
1995 
1996 
1997 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) {
1998  NoHandleAllocation ha;
1999  ASSERT(args.length() == 1);
2001  f->shared()->set_name_should_print_as_anonymous(true);
2002  return isolate->heap()->undefined_value();
2003 }
2004 
2005 
2006 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) {
2007  NoHandleAllocation ha;
2008  ASSERT(args.length() == 1);
2009 
2011  Object* obj = f->RemovePrototype();
2012  if (obj->IsFailure()) return obj;
2013 
2014  return isolate->heap()->undefined_value();
2015 }
2016 
2017 
2018 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScript) {
2019  HandleScope scope(isolate);
2020  ASSERT(args.length() == 1);
2021 
2023  Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate);
2024  if (!script->IsScript()) return isolate->heap()->undefined_value();
2025 
2026  return *GetScriptWrapper(Handle<Script>::cast(script));
2027 }
2028 
2029 
2030 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetSourceCode) {
2031  HandleScope scope(isolate);
2032  ASSERT(args.length() == 1);
2033 
2035  Handle<SharedFunctionInfo> shared(f->shared());
2036  return *shared->GetSourceCode();
2037 }
2038 
2039 
2040 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScriptSourcePosition) {
2041  NoHandleAllocation ha;
2042  ASSERT(args.length() == 1);
2043 
2045  int pos = fun->shared()->start_position();
2046  return Smi::FromInt(pos);
2047 }
2048 
2049 
2050 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetPositionForOffset) {
2051  ASSERT(args.length() == 2);
2052 
2053  CONVERT_ARG_CHECKED(Code, code, 0);
2054  CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]);
2055 
2056  RUNTIME_ASSERT(0 <= offset && offset < code->Size());
2057 
2058  Address pc = code->address() + offset;
2059  return Smi::FromInt(code->SourcePosition(pc));
2060 }
2061 
2062 
2063 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetInstanceClassName) {
2064  NoHandleAllocation ha;
2065  ASSERT(args.length() == 2);
2066 
2068  CONVERT_ARG_CHECKED(String, name, 1);
2069  fun->SetInstanceClassName(name);
2070  return isolate->heap()->undefined_value();
2071 }
2072 
2073 
2074 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetLength) {
2075  NoHandleAllocation ha;
2076  ASSERT(args.length() == 2);
2077 
2079  CONVERT_SMI_ARG_CHECKED(length, 1);
2080  fun->shared()->set_length(length);
2081  return isolate->heap()->undefined_value();
2082 }
2083 
2084 
2085 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) {
2086  NoHandleAllocation ha;
2087  ASSERT(args.length() == 2);
2088 
2090  ASSERT(fun->should_have_prototype());
2091  Object* obj;
2092  { MaybeObject* maybe_obj =
2093  Accessors::FunctionSetPrototype(fun, args[1], NULL);
2094  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2095  }
2096  return args[0]; // return TOS
2097 }
2098 
2099 
2100 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) {
2101  NoHandleAllocation ha;
2102  RUNTIME_ASSERT(args.length() == 1);
2103  CONVERT_ARG_CHECKED(JSFunction, function, 0);
2104 
2105  MaybeObject* maybe_name =
2106  isolate->heap()->AllocateStringFromAscii(CStrVector("prototype"));
2107  String* name;
2108  if (!maybe_name->To(&name)) return maybe_name;
2109 
2110  if (function->HasFastProperties()) {
2111  // Construct a new field descriptor with updated attributes.
2112  DescriptorArray* instance_desc = function->map()->instance_descriptors();
2113  int index = instance_desc->Search(name);
2115  PropertyDetails details = instance_desc->GetDetails(index);
2116  CallbacksDescriptor new_desc(name,
2117  instance_desc->GetValue(index),
2118  static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
2119  details.index());
2120  // Construct a new field descriptors array containing the new descriptor.
2121  Object* descriptors_unchecked;
2122  { MaybeObject* maybe_descriptors_unchecked =
2123  instance_desc->CopyInsert(&new_desc, REMOVE_TRANSITIONS);
2124  if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) {
2125  return maybe_descriptors_unchecked;
2126  }
2127  }
2128  DescriptorArray* new_descriptors =
2129  DescriptorArray::cast(descriptors_unchecked);
2130  // Create a new map featuring the new field descriptors array.
2131  Object* map_unchecked;
2132  { MaybeObject* maybe_map_unchecked = function->map()->CopyDropDescriptors();
2133  if (!maybe_map_unchecked->ToObject(&map_unchecked)) {
2134  return maybe_map_unchecked;
2135  }
2136  }
2137  Map* new_map = Map::cast(map_unchecked);
2138  new_map->set_instance_descriptors(new_descriptors);
2139  function->set_map(new_map);
2140  } else { // Dictionary properties.
2141  // Directly manipulate the property details.
2142  int entry = function->property_dictionary()->FindEntry(name);
2144  PropertyDetails details = function->property_dictionary()->DetailsAt(entry);
2145  PropertyDetails new_details(
2146  static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
2147  details.type(),
2148  details.index());
2149  function->property_dictionary()->DetailsAtPut(entry, new_details);
2150  }
2151  return function;
2152 }
2153 
2154 
2155 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) {
2156  NoHandleAllocation ha;
2157  ASSERT(args.length() == 1);
2158 
2160  return isolate->heap()->ToBoolean(f->shared()->IsApiFunction());
2161 }
2162 
2163 
2164 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) {
2165  NoHandleAllocation ha;
2166  ASSERT(args.length() == 1);
2167 
2169  return isolate->heap()->ToBoolean(f->IsBuiltin());
2170 }
2171 
2172 
2173 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
2174  HandleScope scope(isolate);
2175  ASSERT(args.length() == 2);
2176 
2178  Handle<Object> code = args.at<Object>(1);
2179 
2180  if (code->IsNull()) return *target;
2181  RUNTIME_ASSERT(code->IsJSFunction());
2183  Handle<SharedFunctionInfo> target_shared(target->shared());
2184  Handle<SharedFunctionInfo> source_shared(source->shared());
2185 
2186  if (!source->is_compiled() &&
2188  return Failure::Exception();
2189  }
2190 
2191  // Set the code, scope info, formal parameter count, and the length
2192  // of the target shared function info. Set the source code of the
2193  // target function to undefined. SetCode is only used for built-in
2194  // constructors like String, Array, and Object, and some web code
2195  // doesn't like seeing source code for constructors.
2196  target_shared->set_code(source_shared->code());
2197  target_shared->set_scope_info(source_shared->scope_info());
2198  target_shared->set_length(source_shared->length());
2199  target_shared->set_formal_parameter_count(
2200  source_shared->formal_parameter_count());
2201  target_shared->set_script(isolate->heap()->undefined_value());
2202 
2203  // Since we don't store the source we should never optimize this.
2204  target_shared->code()->set_optimizable(false);
2205 
2206  // Clear the optimization hints related to the compiled code as these
2207  // are no longer valid when the code is overwritten.
2208  target_shared->ClearThisPropertyAssignmentsInfo();
2209 
2210  // Set the code of the target function.
2211  target->ReplaceCode(source_shared->code());
2212 
2213  // Make sure we get a fresh copy of the literal vector to avoid cross
2214  // context contamination.
2215  Handle<Context> context(source->context());
2216  int number_of_literals = source->NumberOfLiterals();
2217  Handle<FixedArray> literals =
2218  isolate->factory()->NewFixedArray(number_of_literals, TENURED);
2219  if (number_of_literals > 0) {
2221  context->global_context());
2222  }
2223  target->set_context(*context);
2224  target->set_literals(*literals);
2225  target->set_next_function_link(isolate->heap()->undefined_value());
2226 
2227  if (isolate->logger()->is_logging() || CpuProfiler::is_profiling(isolate)) {
2228  isolate->logger()->LogExistingFunction(
2229  source_shared, Handle<Code>(source_shared->code()));
2230  }
2231 
2232  return *target;
2233 }
2234 
2235 
2236 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetExpectedNumberOfProperties) {
2237  HandleScope scope(isolate);
2238  ASSERT(args.length() == 2);
2239  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
2240  CONVERT_SMI_ARG_CHECKED(num, 1);
2241  RUNTIME_ASSERT(num >= 0);
2242  SetExpectedNofProperties(function, num);
2243  return isolate->heap()->undefined_value();
2244 }
2245 
2246 
2247 MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate,
2248  Object* char_code) {
2249  uint32_t code;
2250  if (char_code->ToArrayIndex(&code)) {
2251  if (code <= 0xffff) {
2252  return isolate->heap()->LookupSingleCharacterStringFromCode(code);
2253  }
2254  }
2255  return isolate->heap()->empty_string();
2256 }
2257 
2258 
2259 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCharCodeAt) {
2260  NoHandleAllocation ha;
2261  ASSERT(args.length() == 2);
2262 
2263  CONVERT_ARG_CHECKED(String, subject, 0);
2264  Object* index = args[1];
2265  RUNTIME_ASSERT(index->IsNumber());
2266 
2267  uint32_t i = 0;
2268  if (index->IsSmi()) {
2269  int value = Smi::cast(index)->value();
2270  if (value < 0) return isolate->heap()->nan_value();
2271  i = value;
2272  } else {
2273  ASSERT(index->IsHeapNumber());
2274  double value = HeapNumber::cast(index)->value();
2275  i = static_cast<uint32_t>(DoubleToInteger(value));
2276  }
2277 
2278  // Flatten the string. If someone wants to get a char at an index
2279  // in a cons string, it is likely that more indices will be
2280  // accessed.
2281  Object* flat;
2282  { MaybeObject* maybe_flat = subject->TryFlatten();
2283  if (!maybe_flat->ToObject(&flat)) return maybe_flat;
2284  }
2285  subject = String::cast(flat);
2286 
2287  if (i >= static_cast<uint32_t>(subject->length())) {
2288  return isolate->heap()->nan_value();
2289  }
2290 
2291  return Smi::FromInt(subject->Get(i));
2292 }
2293 
2294 
2295 RUNTIME_FUNCTION(MaybeObject*, Runtime_CharFromCode) {
2296  NoHandleAllocation ha;
2297  ASSERT(args.length() == 1);
2298  return CharFromCode(isolate, args[0]);
2299 }
2300 
2301 
2303  public:
2304  explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity)
2305  : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)),
2306  length_(0),
2307  has_non_smi_elements_(false) {
2308  // Require a non-zero initial size. Ensures that doubling the size to
2309  // extend the array will work.
2310  ASSERT(initial_capacity > 0);
2311  }
2312 
2313  explicit FixedArrayBuilder(Handle<FixedArray> backing_store)
2314  : array_(backing_store),
2315  length_(0),
2316  has_non_smi_elements_(false) {
2317  // Require a non-zero initial size. Ensures that doubling the size to
2318  // extend the array will work.
2319  ASSERT(backing_store->length() > 0);
2320  }
2321 
2322  bool HasCapacity(int elements) {
2323  int length = array_->length();
2324  int required_length = length_ + elements;
2325  return (length >= required_length);
2326  }
2327 
2328  void EnsureCapacity(int elements) {
2329  int length = array_->length();
2330  int required_length = length_ + elements;
2331  if (length < required_length) {
2332  int new_length = length;
2333  do {
2334  new_length *= 2;
2335  } while (new_length < required_length);
2336  Handle<FixedArray> extended_array =
2337  array_->GetIsolate()->factory()->NewFixedArrayWithHoles(new_length);
2338  array_->CopyTo(0, *extended_array, 0, length_);
2339  array_ = extended_array;
2340  }
2341  }
2342 
2343  void Add(Object* value) {
2344  ASSERT(!value->IsSmi());
2345  ASSERT(length_ < capacity());
2346  array_->set(length_, value);
2347  length_++;
2348  has_non_smi_elements_ = true;
2349  }
2350 
2351  void Add(Smi* value) {
2352  ASSERT(value->IsSmi());
2353  ASSERT(length_ < capacity());
2354  array_->set(length_, value);
2355  length_++;
2356  }
2357 
2359  return array_;
2360  }
2361 
2362  int length() {
2363  return length_;
2364  }
2365 
2366  int capacity() {
2367  return array_->length();
2368  }
2369 
2371  Handle<JSArray> result_array = FACTORY->NewJSArrayWithElements(array_);
2372  result_array->set_length(Smi::FromInt(length_));
2373  return result_array;
2374  }
2375 
2377  FACTORY->SetContent(target_array, array_);
2378  target_array->set_length(Smi::FromInt(length_));
2379  return target_array;
2380  }
2381 
2382  private:
2383  Handle<FixedArray> array_;
2384  int length_;
2385  bool has_non_smi_elements_;
2386 };
2387 
2388 
2389 // Forward declarations.
2392 
2393 template <typename schar>
2394 static inline void StringBuilderConcatHelper(String*,
2395  schar*,
2396  FixedArray*,
2397  int);
2398 
2401 typedef BitField<int,
2405 
2406 
2408  public:
2410  Handle<String> subject,
2411  int estimated_part_count)
2412  : heap_(heap),
2413  array_builder_(heap->isolate(), estimated_part_count),
2414  subject_(subject),
2415  character_count_(0),
2416  is_ascii_(subject->IsAsciiRepresentation()) {
2417  // Require a non-zero initial size. Ensures that doubling the size to
2418  // extend the array will work.
2419  ASSERT(estimated_part_count > 0);
2420  }
2421 
2422  static inline void AddSubjectSlice(FixedArrayBuilder* builder,
2423  int from,
2424  int to) {
2425  ASSERT(from >= 0);
2426  int length = to - from;
2427  ASSERT(length > 0);
2430  int encoded_slice = StringBuilderSubstringLength::encode(length) |
2432  builder->Add(Smi::FromInt(encoded_slice));
2433  } else {
2434  // Otherwise encode as two smis.
2435  builder->Add(Smi::FromInt(-length));
2436  builder->Add(Smi::FromInt(from));
2437  }
2438  }
2439 
2440 
2441  void EnsureCapacity(int elements) {
2442  array_builder_.EnsureCapacity(elements);
2443  }
2444 
2445 
2446  void AddSubjectSlice(int from, int to) {
2447  AddSubjectSlice(&array_builder_, from, to);
2448  IncrementCharacterCount(to - from);
2449  }
2450 
2451 
2452  void AddString(Handle<String> string) {
2453  int length = string->length();
2454  ASSERT(length > 0);
2455  AddElement(*string);
2456  if (!string->IsAsciiRepresentation()) {
2457  is_ascii_ = false;
2458  }
2459  IncrementCharacterCount(length);
2460  }
2461 
2462 
2464  if (array_builder_.length() == 0) {
2465  return heap_->isolate()->factory()->empty_string();
2466  }
2467 
2468  Handle<String> joined_string;
2469  if (is_ascii_) {
2470  Handle<SeqAsciiString> seq = NewRawAsciiString(character_count_);
2471  AssertNoAllocation no_alloc;
2472  char* char_buffer = seq->GetChars();
2473  StringBuilderConcatHelper(*subject_,
2474  char_buffer,
2475  *array_builder_.array(),
2476  array_builder_.length());
2477  joined_string = Handle<String>::cast(seq);
2478  } else {
2479  // Non-ASCII.
2480  Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_);
2481  AssertNoAllocation no_alloc;
2482  uc16* char_buffer = seq->GetChars();
2483  StringBuilderConcatHelper(*subject_,
2484  char_buffer,
2485  *array_builder_.array(),
2486  array_builder_.length());
2487  joined_string = Handle<String>::cast(seq);
2488  }
2489  return joined_string;
2490  }
2491 
2492 
2494  if (character_count_ > String::kMaxLength - by) {
2495  V8::FatalProcessOutOfMemory("String.replace result too large.");
2496  }
2497  character_count_ += by;
2498  }
2499 
2501  return array_builder_.ToJSArray();
2502  }
2503 
2504  private:
2505  Handle<SeqAsciiString> NewRawAsciiString(int length) {
2506  return heap_->isolate()->factory()->NewRawAsciiString(length);
2507  }
2508 
2509 
2510  Handle<SeqTwoByteString> NewRawTwoByteString(int length) {
2511  return heap_->isolate()->factory()->NewRawTwoByteString(length);
2512  }
2513 
2514 
2515  void AddElement(Object* element) {
2516  ASSERT(element->IsSmi() || element->IsString());
2517  ASSERT(array_builder_.capacity() > array_builder_.length());
2518  array_builder_.Add(element);
2519  }
2520 
2521  Heap* heap_;
2522  FixedArrayBuilder array_builder_;
2523  Handle<String> subject_;
2524  int character_count_;
2525  bool is_ascii_;
2526 };
2527 
2528 
2530  public:
2532  : parts_(1, zone), replacement_substrings_(0, zone),
2533  simple_hint_(false),
2534  zone_(zone) {}
2535 
2536  void Compile(Handle<String> replacement,
2537  int capture_count,
2538  int subject_length);
2539 
2540  void Apply(ReplacementStringBuilder* builder,
2541  int match_from,
2542  int match_to,
2543  Handle<JSArray> last_match_info);
2544 
2545  // Number of distinct parts of the replacement pattern.
2546  int parts() {
2547  return parts_.length();
2548  }
2549 
2550  bool simple_hint() {
2551  return simple_hint_;
2552  }
2553 
2554  Zone* zone() const { return zone_; }
2555 
2556  private:
2557  enum PartType {
2558  SUBJECT_PREFIX = 1,
2559  SUBJECT_SUFFIX,
2560  SUBJECT_CAPTURE,
2561  REPLACEMENT_SUBSTRING,
2562  REPLACEMENT_STRING,
2563 
2564  NUMBER_OF_PART_TYPES
2565  };
2566 
2567  struct ReplacementPart {
2568  static inline ReplacementPart SubjectMatch() {
2569  return ReplacementPart(SUBJECT_CAPTURE, 0);
2570  }
2571  static inline ReplacementPart SubjectCapture(int capture_index) {
2572  return ReplacementPart(SUBJECT_CAPTURE, capture_index);
2573  }
2574  static inline ReplacementPart SubjectPrefix() {
2575  return ReplacementPart(SUBJECT_PREFIX, 0);
2576  }
2577  static inline ReplacementPart SubjectSuffix(int subject_length) {
2578  return ReplacementPart(SUBJECT_SUFFIX, subject_length);
2579  }
2580  static inline ReplacementPart ReplacementString() {
2581  return ReplacementPart(REPLACEMENT_STRING, 0);
2582  }
2583  static inline ReplacementPart ReplacementSubString(int from, int to) {
2584  ASSERT(from >= 0);
2585  ASSERT(to > from);
2586  return ReplacementPart(-from, to);
2587  }
2588 
2589  // If tag <= 0 then it is the negation of a start index of a substring of
2590  // the replacement pattern, otherwise it's a value from PartType.
2591  ReplacementPart(int tag, int data)
2592  : tag(tag), data(data) {
2593  // Must be non-positive or a PartType value.
2594  ASSERT(tag < NUMBER_OF_PART_TYPES);
2595  }
2596  // Either a value of PartType or a non-positive number that is
2597  // the negation of an index into the replacement string.
2598  int tag;
2599  // The data value's interpretation depends on the value of tag:
2600  // tag == SUBJECT_PREFIX ||
2601  // tag == SUBJECT_SUFFIX: data is unused.
2602  // tag == SUBJECT_CAPTURE: data is the number of the capture.
2603  // tag == REPLACEMENT_SUBSTRING ||
2604  // tag == REPLACEMENT_STRING: data is index into array of substrings
2605  // of the replacement string.
2606  // tag <= 0: Temporary representation of the substring of the replacement
2607  // string ranging over -tag .. data.
2608  // Is replaced by REPLACEMENT_{SUB,}STRING when we create the
2609  // substring objects.
2610  int data;
2611  };
2612 
2613  template<typename Char>
2614  static bool ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
2615  Vector<Char> characters,
2616  int capture_count,
2617  int subject_length,
2618  Zone* zone) {
2619  int length = characters.length();
2620  int last = 0;
2621  for (int i = 0; i < length; i++) {
2622  Char c = characters[i];
2623  if (c == '$') {
2624  int next_index = i + 1;
2625  if (next_index == length) { // No next character!
2626  break;
2627  }
2628  Char c2 = characters[next_index];
2629  switch (c2) {
2630  case '$':
2631  if (i > last) {
2632  // There is a substring before. Include the first "$".
2633  parts->Add(ReplacementPart::ReplacementSubString(last, next_index),
2634  zone);
2635  last = next_index + 1; // Continue after the second "$".
2636  } else {
2637  // Let the next substring start with the second "$".
2638  last = next_index;
2639  }
2640  i = next_index;
2641  break;
2642  case '`':
2643  if (i > last) {
2644  parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
2645  }
2646  parts->Add(ReplacementPart::SubjectPrefix(), zone);
2647  i = next_index;
2648  last = i + 1;
2649  break;
2650  case '\'':
2651  if (i > last) {
2652  parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
2653  }
2654  parts->Add(ReplacementPart::SubjectSuffix(subject_length), zone);
2655  i = next_index;
2656  last = i + 1;
2657  break;
2658  case '&':
2659  if (i > last) {
2660  parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
2661  }
2662  parts->Add(ReplacementPart::SubjectMatch(), zone);
2663  i = next_index;
2664  last = i + 1;
2665  break;
2666  case '0':
2667  case '1':
2668  case '2':
2669  case '3':
2670  case '4':
2671  case '5':
2672  case '6':
2673  case '7':
2674  case '8':
2675  case '9': {
2676  int capture_ref = c2 - '0';
2677  if (capture_ref > capture_count) {
2678  i = next_index;
2679  continue;
2680  }
2681  int second_digit_index = next_index + 1;
2682  if (second_digit_index < length) {
2683  // Peek ahead to see if we have two digits.
2684  Char c3 = characters[second_digit_index];
2685  if ('0' <= c3 && c3 <= '9') { // Double digits.
2686  int double_digit_ref = capture_ref * 10 + c3 - '0';
2687  if (double_digit_ref <= capture_count) {
2688  next_index = second_digit_index;
2689  capture_ref = double_digit_ref;
2690  }
2691  }
2692  }
2693  if (capture_ref > 0) {
2694  if (i > last) {
2695  parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
2696  }
2697  ASSERT(capture_ref <= capture_count);
2698  parts->Add(ReplacementPart::SubjectCapture(capture_ref), zone);
2699  last = next_index + 1;
2700  }
2701  i = next_index;
2702  break;
2703  }
2704  default:
2705  i = next_index;
2706  break;
2707  }
2708  }
2709  }
2710  if (length > last) {
2711  if (last == 0) {
2712  parts->Add(ReplacementPart::ReplacementString(), zone);
2713  return true;
2714  } else {
2715  parts->Add(ReplacementPart::ReplacementSubString(last, length), zone);
2716  }
2717  }
2718  return false;
2719  }
2720 
2721  ZoneList<ReplacementPart> parts_;
2722  ZoneList<Handle<String> > replacement_substrings_;
2723  bool simple_hint_;
2724  Zone* zone_;
2725 };
2726 
2727 
2729  int capture_count,
2730  int subject_length) {
2731  {
2732  AssertNoAllocation no_alloc;
2733  String::FlatContent content = replacement->GetFlatContent();
2734  ASSERT(content.IsFlat());
2735  if (content.IsAscii()) {
2736  simple_hint_ = ParseReplacementPattern(&parts_,
2737  content.ToAsciiVector(),
2738  capture_count,
2739  subject_length,
2740  zone());
2741  } else {
2742  ASSERT(content.IsTwoByte());
2743  simple_hint_ = ParseReplacementPattern(&parts_,
2744  content.ToUC16Vector(),
2745  capture_count,
2746  subject_length,
2747  zone());
2748  }
2749  }
2750  Isolate* isolate = replacement->GetIsolate();
2751  // Find substrings of replacement string and create them as String objects.
2752  int substring_index = 0;
2753  for (int i = 0, n = parts_.length(); i < n; i++) {
2754  int tag = parts_[i].tag;
2755  if (tag <= 0) { // A replacement string slice.
2756  int from = -tag;
2757  int to = parts_[i].data;
2758  replacement_substrings_.Add(
2759  isolate->factory()->NewSubString(replacement, from, to), zone());
2760  parts_[i].tag = REPLACEMENT_SUBSTRING;
2761  parts_[i].data = substring_index;
2762  substring_index++;
2763  } else if (tag == REPLACEMENT_STRING) {
2764  replacement_substrings_.Add(replacement, zone());
2765  parts_[i].data = substring_index;
2766  substring_index++;
2767  }
2768  }
2769 }
2770 
2771 
2773  int match_from,
2774  int match_to,
2775  Handle<JSArray> last_match_info) {
2776  for (int i = 0, n = parts_.length(); i < n; i++) {
2777  ReplacementPart part = parts_[i];
2778  switch (part.tag) {
2779  case SUBJECT_PREFIX:
2780  if (match_from > 0) builder->AddSubjectSlice(0, match_from);
2781  break;
2782  case SUBJECT_SUFFIX: {
2783  int subject_length = part.data;
2784  if (match_to < subject_length) {
2785  builder->AddSubjectSlice(match_to, subject_length);
2786  }
2787  break;
2788  }
2789  case SUBJECT_CAPTURE: {
2790  int capture = part.data;
2791  FixedArray* match_info = FixedArray::cast(last_match_info->elements());
2792  int from = RegExpImpl::GetCapture(match_info, capture * 2);
2793  int to = RegExpImpl::GetCapture(match_info, capture * 2 + 1);
2794  if (from >= 0 && to > from) {
2795  builder->AddSubjectSlice(from, to);
2796  }
2797  break;
2798  }
2799  case REPLACEMENT_SUBSTRING:
2800  case REPLACEMENT_STRING:
2801  builder->AddString(replacement_substrings_[part.data]);
2802  break;
2803  default:
2804  UNREACHABLE();
2805  }
2806  }
2807 }
2808 
2809 
2811  char pattern,
2812  ZoneList<int>* indices,
2813  unsigned int limit,
2814  Zone* zone) {
2815  ASSERT(limit > 0);
2816  // Collect indices of pattern in subject using memchr.
2817  // Stop after finding at most limit values.
2818  const char* subject_start = reinterpret_cast<const char*>(subject.start());
2819  const char* subject_end = subject_start + subject.length();
2820  const char* pos = subject_start;
2821  while (limit > 0) {
2822  pos = reinterpret_cast<const char*>(
2823  memchr(pos, pattern, subject_end - pos));
2824  if (pos == NULL) return;
2825  indices->Add(static_cast<int>(pos - subject_start), zone);
2826  pos++;
2827  limit--;
2828  }
2829 }
2830 
2831 
2832 template <typename SubjectChar, typename PatternChar>
2834  Vector<const SubjectChar> subject,
2835  Vector<const PatternChar> pattern,
2836  ZoneList<int>* indices,
2837  unsigned int limit,
2838  Zone* zone) {
2839  ASSERT(limit > 0);
2840  // Collect indices of pattern in subject.
2841  // Stop after finding at most limit values.
2842  int pattern_length = pattern.length();
2843  int index = 0;
2844  StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
2845  while (limit > 0) {
2846  index = search.Search(subject, index);
2847  if (index < 0) return;
2848  indices->Add(index, zone);
2849  index += pattern_length;
2850  limit--;
2851  }
2852 }
2853 
2854 
2856  String* subject,
2857  String* pattern,
2858  ZoneList<int>* indices,
2859  unsigned int limit,
2860  Zone* zone) {
2861  {
2862  AssertNoAllocation no_gc;
2863  String::FlatContent subject_content = subject->GetFlatContent();
2864  String::FlatContent pattern_content = pattern->GetFlatContent();
2865  ASSERT(subject_content.IsFlat());
2866  ASSERT(pattern_content.IsFlat());
2867  if (subject_content.IsAscii()) {
2868  Vector<const char> subject_vector = subject_content.ToAsciiVector();
2869  if (pattern_content.IsAscii()) {
2870  Vector<const char> pattern_vector = pattern_content.ToAsciiVector();
2871  if (pattern_vector.length() == 1) {
2872  FindAsciiStringIndices(subject_vector,
2873  pattern_vector[0],
2874  indices,
2875  limit,
2876  zone);
2877  } else {
2878  FindStringIndices(isolate,
2879  subject_vector,
2880  pattern_vector,
2881  indices,
2882  limit,
2883  zone);
2884  }
2885  } else {
2886  FindStringIndices(isolate,
2887  subject_vector,
2888  pattern_content.ToUC16Vector(),
2889  indices,
2890  limit,
2891  zone);
2892  }
2893  } else {
2894  Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
2895  if (pattern_content.IsAscii()) {
2896  FindStringIndices(isolate,
2897  subject_vector,
2898  pattern_content.ToAsciiVector(),
2899  indices,
2900  limit,
2901  zone);
2902  } else {
2903  FindStringIndices(isolate,
2904  subject_vector,
2905  pattern_content.ToUC16Vector(),
2906  indices,
2907  limit,
2908  zone);
2909  }
2910  }
2911  }
2912 }
2913 
2914 
2915 // Two smis before and after the match, for very long strings.
2917 
2918 
2919 static void SetLastMatchInfoNoCaptures(Handle<String> subject,
2920  Handle<JSArray> last_match_info,
2921  int match_start,
2922  int match_end) {
2923  // Fill last_match_info with a single capture.
2924  last_match_info->EnsureSize(2 + RegExpImpl::kLastMatchOverhead);
2925  AssertNoAllocation no_gc;
2926  FixedArray* elements = FixedArray::cast(last_match_info->elements());
2927  RegExpImpl::SetLastCaptureCount(elements, 2);
2928  RegExpImpl::SetLastInput(elements, *subject);
2929  RegExpImpl::SetLastSubject(elements, *subject);
2930  RegExpImpl::SetCapture(elements, 0, match_start);
2931  RegExpImpl::SetCapture(elements, 1, match_end);
2932 }
2933 
2934 
2935 template <typename SubjectChar, typename PatternChar>
2936 static bool SearchStringMultiple(Isolate* isolate,
2937  Vector<const SubjectChar> subject,
2938  Vector<const PatternChar> pattern,
2939  String* pattern_string,
2940  FixedArrayBuilder* builder,
2941  int* match_pos) {
2942  int pos = *match_pos;
2943  int subject_length = subject.length();
2944  int pattern_length = pattern.length();
2945  int max_search_start = subject_length - pattern_length;
2946  StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
2947  while (pos <= max_search_start) {
2948  if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
2949  *match_pos = pos;
2950  return false;
2951  }
2952  // Position of end of previous match.
2953  int match_end = pos + pattern_length;
2954  int new_pos = search.Search(subject, match_end);
2955  if (new_pos >= 0) {
2956  // A match.
2957  if (new_pos > match_end) {
2959  match_end,
2960  new_pos);
2961  }
2962  pos = new_pos;
2963  builder->Add(pattern_string);
2964  } else {
2965  break;
2966  }
2967  }
2968 
2969  if (pos < max_search_start) {
2971  pos + pattern_length,
2972  subject_length);
2973  }
2974  *match_pos = pos;
2975  return true;
2976 }
2977 
2978 
2979 
2980 
2981 template<typename ResultSeqString>
2982 MUST_USE_RESULT static MaybeObject* StringReplaceAtomRegExpWithString(
2983  Isolate* isolate,
2984  Handle<String> subject,
2985  Handle<JSRegExp> pattern_regexp,
2986  Handle<String> replacement,
2987  Handle<JSArray> last_match_info,
2988  Zone* zone) {
2989  ASSERT(subject->IsFlat());
2990  ASSERT(replacement->IsFlat());
2991 
2992  ZoneScope zone_space(isolate, DELETE_ON_EXIT);
2993  ZoneList<int> indices(8, isolate->zone());
2994  ASSERT_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag());
2995  String* pattern =
2996  String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex));
2997  int subject_len = subject->length();
2998  int pattern_len = pattern->length();
2999  int replacement_len = replacement->length();
3000 
3001  FindStringIndicesDispatch(isolate, *subject, pattern, &indices, 0xffffffff,
3002  zone);
3003 
3004  int matches = indices.length();
3005  if (matches == 0) return *subject;
3006 
3007  // Detect integer overflow.
3008  int64_t result_len_64 =
3009  (static_cast<int64_t>(replacement_len) -
3010  static_cast<int64_t>(pattern_len)) *
3011  static_cast<int64_t>(matches) +
3012  static_cast<int64_t>(subject_len);
3013  if (result_len_64 > INT_MAX) return Failure::OutOfMemoryException();
3014  int result_len = static_cast<int>(result_len_64);
3015 
3016  int subject_pos = 0;
3017  int result_pos = 0;
3018 
3019  Handle<ResultSeqString> result;
3020  if (ResultSeqString::kHasAsciiEncoding) {
3022  isolate->factory()->NewRawAsciiString(result_len));
3023  } else {
3025  isolate->factory()->NewRawTwoByteString(result_len));
3026  }
3027 
3028  for (int i = 0; i < matches; i++) {
3029  // Copy non-matched subject content.
3030  if (subject_pos < indices.at(i)) {
3031  String::WriteToFlat(*subject,
3032  result->GetChars() + result_pos,
3033  subject_pos,
3034  indices.at(i));
3035  result_pos += indices.at(i) - subject_pos;
3036  }
3037 
3038  // Replace match.
3039  if (replacement_len > 0) {
3040  String::WriteToFlat(*replacement,
3041  result->GetChars() + result_pos,
3042  0,
3043  replacement_len);
3044  result_pos += replacement_len;
3045  }
3046 
3047  subject_pos = indices.at(i) + pattern_len;
3048  }
3049  // Add remaining subject content at the end.
3050  if (subject_pos < subject_len) {
3051  String::WriteToFlat(*subject,
3052  result->GetChars() + result_pos,
3053  subject_pos,
3054  subject_len);
3055  }
3056 
3057  SetLastMatchInfoNoCaptures(subject,
3058  last_match_info,
3059  indices.at(matches - 1),
3060  indices.at(matches - 1) + pattern_len);
3061 
3062  return *result;
3063 }
3064 
3065 
3066 MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithString(
3067  Isolate* isolate,
3068  String* subject,
3069  JSRegExp* regexp,
3070  String* replacement,
3071  JSArray* last_match_info,
3072  Zone* zone) {
3073  ASSERT(subject->IsFlat());
3074  ASSERT(replacement->IsFlat());
3075 
3076  HandleScope handles(isolate);
3077 
3078  int length = subject->length();
3079  Handle<String> subject_handle(subject);
3080  Handle<JSRegExp> regexp_handle(regexp);
3081  Handle<String> replacement_handle(replacement);
3082  Handle<JSArray> last_match_info_handle(last_match_info);
3083  Handle<Object> match = RegExpImpl::Exec(regexp_handle,
3084  subject_handle,
3085  0,
3086  last_match_info_handle,
3087  isolate->zone());
3088  if (match.is_null()) {
3089  return Failure::Exception();
3090  }
3091  if (match->IsNull()) {
3092  return *subject_handle;
3093  }
3094 
3095  int capture_count = regexp_handle->CaptureCount();
3096 
3097  // CompiledReplacement uses zone allocation.
3098  ZoneScope zonescope(isolate, DELETE_ON_EXIT);
3099  CompiledReplacement compiled_replacement(isolate->zone());
3100  compiled_replacement.Compile(replacement_handle,
3101  capture_count,
3102  length);
3103 
3104  bool is_global = regexp_handle->GetFlags().is_global();
3105 
3106  // Shortcut for simple non-regexp global replacements
3107  if (is_global &&
3108  regexp_handle->TypeTag() == JSRegExp::ATOM &&
3109  compiled_replacement.simple_hint()) {
3110  if (subject_handle->HasOnlyAsciiChars() &&
3111  replacement_handle->HasOnlyAsciiChars()) {
3112  return StringReplaceAtomRegExpWithString<SeqAsciiString>(
3113  isolate,
3114  subject_handle,
3115  regexp_handle,
3116  replacement_handle,
3117  last_match_info_handle,
3118  zone);
3119  } else {
3120  return StringReplaceAtomRegExpWithString<SeqTwoByteString>(
3121  isolate,
3122  subject_handle,
3123  regexp_handle,
3124  replacement_handle,
3125  last_match_info_handle,
3126  zone);
3127  }
3128  }
3129 
3130  // Guessing the number of parts that the final result string is built
3131  // from. Global regexps can match any number of times, so we guess
3132  // conservatively.
3133  int expected_parts =
3134  (compiled_replacement.parts() + 1) * (is_global ? 4 : 1) + 1;
3135  ReplacementStringBuilder builder(isolate->heap(),
3136  subject_handle,
3137  expected_parts);
3138 
3139  // Index of end of last match.
3140  int prev = 0;
3141 
3142  // Number of parts added by compiled replacement plus preceeding
3143  // string and possibly suffix after last match. It is possible for
3144  // all components to use two elements when encoded as two smis.
3145  const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2);
3146  bool matched = true;
3147  do {
3148  ASSERT(last_match_info_handle->HasFastObjectElements());
3149  // Increase the capacity of the builder before entering local handle-scope,
3150  // so its internal buffer can safely allocate a new handle if it grows.
3151  builder.EnsureCapacity(parts_added_per_loop);
3152 
3153  HandleScope loop_scope(isolate);
3154  int start, end;
3155  {
3156  AssertNoAllocation match_info_array_is_not_in_a_handle;
3157  FixedArray* match_info_array =
3158  FixedArray::cast(last_match_info_handle->elements());
3159 
3160  ASSERT_EQ(capture_count * 2 + 2,
3161  RegExpImpl::GetLastCaptureCount(match_info_array));
3162  start = RegExpImpl::GetCapture(match_info_array, 0);
3163  end = RegExpImpl::GetCapture(match_info_array, 1);
3164  }
3165 
3166  if (prev < start) {
3167  builder.AddSubjectSlice(prev, start);
3168  }
3169  compiled_replacement.Apply(&builder,
3170  start,
3171  end,
3172  last_match_info_handle);
3173  prev = end;
3174 
3175  // Only continue checking for global regexps.
3176  if (!is_global) break;
3177 
3178  // Continue from where the match ended, unless it was an empty match.
3179  int next = end;
3180  if (start == end) {
3181  next = end + 1;
3182  if (next > length) break;
3183  }
3184 
3185  match = RegExpImpl::Exec(regexp_handle,
3186  subject_handle,
3187  next,
3188  last_match_info_handle,
3189  isolate->zone());
3190  if (match.is_null()) {
3191  return Failure::Exception();
3192  }
3193  matched = !match->IsNull();
3194  } while (matched);
3195 
3196  if (prev < length) {
3197  builder.AddSubjectSlice(prev, length);
3198  }
3199 
3200  return *(builder.ToString());
3201 }
3202 
3203 
3204 template <typename ResultSeqString>
3205 MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithEmptyString(
3206  Isolate* isolate,
3207  String* subject,
3208  JSRegExp* regexp,
3209  JSArray* last_match_info,
3210  Zone* zone) {
3211  ASSERT(subject->IsFlat());
3212 
3213  HandleScope handles(isolate);
3214 
3215  Handle<String> subject_handle(subject);
3216  Handle<JSRegExp> regexp_handle(regexp);
3217  Handle<JSArray> last_match_info_handle(last_match_info);
3218 
3219  // Shortcut for simple non-regexp global replacements
3220  if (regexp_handle->GetFlags().is_global() &&
3221  regexp_handle->TypeTag() == JSRegExp::ATOM) {
3222  Handle<String> empty_string_handle(HEAP->empty_string());
3223  if (subject_handle->HasOnlyAsciiChars()) {
3224  return StringReplaceAtomRegExpWithString<SeqAsciiString>(
3225  isolate,
3226  subject_handle,
3227  regexp_handle,
3228  empty_string_handle,
3229  last_match_info_handle,
3230  zone);
3231  } else {
3232  return StringReplaceAtomRegExpWithString<SeqTwoByteString>(
3233  isolate,
3234  subject_handle,
3235  regexp_handle,
3236  empty_string_handle,
3237  last_match_info_handle,
3238  zone);
3239  }
3240  }
3241 
3242  Handle<Object> match = RegExpImpl::Exec(regexp_handle,
3243  subject_handle,
3244  0,
3245  last_match_info_handle,
3246  isolate->zone());
3247  if (match.is_null()) return Failure::Exception();
3248  if (match->IsNull()) return *subject_handle;
3249 
3250  ASSERT(last_match_info_handle->HasFastObjectElements());
3251 
3252  int start, end;
3253  {
3254  AssertNoAllocation match_info_array_is_not_in_a_handle;
3255  FixedArray* match_info_array =
3256  FixedArray::cast(last_match_info_handle->elements());
3257 
3258  start = RegExpImpl::GetCapture(match_info_array, 0);
3259  end = RegExpImpl::GetCapture(match_info_array, 1);
3260  }
3261 
3262  bool global = regexp_handle->GetFlags().is_global();
3263 
3264  if (start == end && !global) return *subject_handle;
3265 
3266  int length = subject_handle->length();
3267  int new_length = length - (end - start);
3268  if (new_length == 0) {
3269  return isolate->heap()->empty_string();
3270  }
3271  Handle<ResultSeqString> answer;
3272  if (ResultSeqString::kHasAsciiEncoding) {
3274  isolate->factory()->NewRawAsciiString(new_length));
3275  } else {
3277  isolate->factory()->NewRawTwoByteString(new_length));
3278  }
3279 
3280  // If the regexp isn't global, only match once.
3281  if (!global) {
3282  if (start > 0) {
3283  String::WriteToFlat(*subject_handle,
3284  answer->GetChars(),
3285  0,
3286  start);
3287  }
3288  if (end < length) {
3289  String::WriteToFlat(*subject_handle,
3290  answer->GetChars() + start,
3291  end,
3292  length);
3293  }
3294  return *answer;
3295  }
3296 
3297  int prev = 0; // Index of end of last match.
3298  int next = 0; // Start of next search (prev unless last match was empty).
3299  int position = 0;
3300 
3301  do {
3302  if (prev < start) {
3303  // Add substring subject[prev;start] to answer string.
3304  String::WriteToFlat(*subject_handle,
3305  answer->GetChars() + position,
3306  prev,
3307  start);
3308  position += start - prev;
3309  }
3310  prev = end;
3311  next = end;
3312  // Continue from where the match ended, unless it was an empty match.
3313  if (start == end) {
3314  next++;
3315  if (next > length) break;
3316  }
3317  match = RegExpImpl::Exec(regexp_handle,
3318  subject_handle,
3319  next,
3320  last_match_info_handle,
3321  isolate->zone());
3322  if (match.is_null()) return Failure::Exception();
3323  if (match->IsNull()) break;
3324 
3325  ASSERT(last_match_info_handle->HasFastObjectElements());
3326  HandleScope loop_scope(isolate);
3327  {
3328  AssertNoAllocation match_info_array_is_not_in_a_handle;
3329  FixedArray* match_info_array =
3330  FixedArray::cast(last_match_info_handle->elements());
3331  start = RegExpImpl::GetCapture(match_info_array, 0);
3332  end = RegExpImpl::GetCapture(match_info_array, 1);
3333  }
3334  } while (true);
3335 
3336  if (prev < length) {
3337  // Add substring subject[prev;length] to answer string.
3338  String::WriteToFlat(*subject_handle,
3339  answer->GetChars() + position,
3340  prev,
3341  length);
3342  position += length - prev;
3343  }
3344 
3345  if (position == 0) {
3346  return isolate->heap()->empty_string();
3347  }
3348 
3349  // Shorten string and fill
3350  int string_size = ResultSeqString::SizeFor(position);
3351  int allocated_string_size = ResultSeqString::SizeFor(new_length);
3352  int delta = allocated_string_size - string_size;
3353 
3354  answer->set_length(position);
3355  if (delta == 0) return *answer;
3356 
3357  Address end_of_string = answer->address() + string_size;
3358  isolate->heap()->CreateFillerObjectAt(end_of_string, delta);
3359  if (Marking::IsBlack(Marking::MarkBitFrom(*answer))) {
3360  MemoryChunk::IncrementLiveBytesFromMutator(answer->address(), -delta);
3361  }
3362 
3363  return *answer;
3364 }
3365 
3366 
3367 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceRegExpWithString) {
3368  ASSERT(args.length() == 4);
3369 
3370  CONVERT_ARG_CHECKED(String, subject, 0);
3371  if (!subject->IsFlat()) {
3372  Object* flat_subject;
3373  { MaybeObject* maybe_flat_subject = subject->TryFlatten();
3374  if (!maybe_flat_subject->ToObject(&flat_subject)) {
3375  return maybe_flat_subject;
3376  }
3377  }
3378  subject = String::cast(flat_subject);
3379  }
3380 
3381  CONVERT_ARG_CHECKED(String, replacement, 2);
3382  if (!replacement->IsFlat()) {
3383  Object* flat_replacement;
3384  { MaybeObject* maybe_flat_replacement = replacement->TryFlatten();
3385  if (!maybe_flat_replacement->ToObject(&flat_replacement)) {
3386  return maybe_flat_replacement;
3387  }
3388  }
3389  replacement = String::cast(flat_replacement);
3390  }
3391 
3392  CONVERT_ARG_CHECKED(JSRegExp, regexp, 1);
3393  CONVERT_ARG_CHECKED(JSArray, last_match_info, 3);
3394 
3395  ASSERT(last_match_info->HasFastObjectElements());
3396 
3397  Zone* zone = isolate->zone();
3398  if (replacement->length() == 0) {
3399  if (subject->HasOnlyAsciiChars()) {
3400  return StringReplaceRegExpWithEmptyString<SeqAsciiString>(
3401  isolate, subject, regexp, last_match_info, zone);
3402  } else {
3403  return StringReplaceRegExpWithEmptyString<SeqTwoByteString>(
3404  isolate, subject, regexp, last_match_info, zone);
3405  }
3406  }
3407 
3408  return StringReplaceRegExpWithString(isolate,
3409  subject,
3410  regexp,
3411  replacement,
3412  last_match_info,
3413  zone);
3414 }
3415 
3416 
3418  Handle<String> subject,
3419  Handle<String> search,
3420  Handle<String> replace,
3421  bool* found,
3422  int recursion_limit) {
3423  if (recursion_limit == 0) return Handle<String>::null();
3424  if (subject->IsConsString()) {
3425  ConsString* cons = ConsString::cast(*subject);
3426  Handle<String> first = Handle<String>(cons->first());
3427  Handle<String> second = Handle<String>(cons->second());
3428  Handle<String> new_first =
3430  first,
3431  search,
3432  replace,
3433  found,
3434  recursion_limit - 1);
3435  if (*found) return isolate->factory()->NewConsString(new_first, second);
3436  if (new_first.is_null()) return new_first;
3437 
3438  Handle<String> new_second =
3440  second,
3441  search,
3442  replace,
3443  found,
3444  recursion_limit - 1);
3445  if (*found) return isolate->factory()->NewConsString(first, new_second);
3446  if (new_second.is_null()) return new_second;
3447 
3448  return subject;
3449  } else {
3450  int index = StringMatch(isolate, subject, search, 0);
3451  if (index == -1) return subject;
3452  *found = true;
3453  Handle<String> first = isolate->factory()->NewSubString(subject, 0, index);
3454  Handle<String> cons1 = isolate->factory()->NewConsString(first, replace);
3455  Handle<String> second =
3456  isolate->factory()->NewSubString(subject, index + 1, subject->length());
3457  return isolate->factory()->NewConsString(cons1, second);
3458  }
3459 }
3460 
3461 
3462 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) {
3463  ASSERT(args.length() == 3);
3464  HandleScope scope(isolate);
3465  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
3466  CONVERT_ARG_HANDLE_CHECKED(String, search, 1);
3467  CONVERT_ARG_HANDLE_CHECKED(String, replace, 2);
3468 
3469  // If the cons string tree is too deep, we simply abort the recursion and
3470  // retry with a flattened subject string.
3471  const int kRecursionLimit = 0x1000;
3472  bool found = false;
3473  Handle<String> result =
3475  subject,
3476  search,
3477  replace,
3478  &found,
3479  kRecursionLimit);
3480  if (!result.is_null()) return *result;
3482  FlattenGetString(subject),
3483  search,
3484  replace,
3485  &found,
3486  kRecursionLimit);
3487 }
3488 
3489 
3490 // Perform string match of pattern on subject, starting at start index.
3491 // Caller must ensure that 0 <= start_index <= sub->length(),
3492 // and should check that pat->length() + start_index <= sub->length().
3494  Handle<String> sub,
3495  Handle<String> pat,
3496  int start_index) {
3497  ASSERT(0 <= start_index);
3498  ASSERT(start_index <= sub->length());
3499 
3500  int pattern_length = pat->length();
3501  if (pattern_length == 0) return start_index;
3502 
3503  int subject_length = sub->length();
3504  if (start_index + pattern_length > subject_length) return -1;
3505 
3506  if (!sub->IsFlat()) FlattenString(sub);
3507  if (!pat->IsFlat()) FlattenString(pat);
3508 
3509  AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
3510  // Extract flattened substrings of cons strings before determining asciiness.
3511  String::FlatContent seq_sub = sub->GetFlatContent();
3512  String::FlatContent seq_pat = pat->GetFlatContent();
3513 
3514  // dispatch on type of strings
3515  if (seq_pat.IsAscii()) {
3516  Vector<const char> pat_vector = seq_pat.ToAsciiVector();
3517  if (seq_sub.IsAscii()) {
3518  return SearchString(isolate,
3519  seq_sub.ToAsciiVector(),
3520  pat_vector,
3521  start_index);
3522  }
3523  return SearchString(isolate,
3524  seq_sub.ToUC16Vector(),
3525  pat_vector,
3526  start_index);
3527  }
3528  Vector<const uc16> pat_vector = seq_pat.ToUC16Vector();
3529  if (seq_sub.IsAscii()) {
3530  return SearchString(isolate,
3531  seq_sub.ToAsciiVector(),
3532  pat_vector,
3533  start_index);
3534  }
3535  return SearchString(isolate,
3536  seq_sub.ToUC16Vector(),
3537  pat_vector,
3538  start_index);
3539 }
3540 
3541 
3542 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringIndexOf) {
3543  HandleScope scope(isolate); // create a new handle scope
3544  ASSERT(args.length() == 3);
3545 
3548 
3549  Object* index = args[2];
3550  uint32_t start_index;
3551  if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
3552 
3553  RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
3554  int position =
3555  Runtime::StringMatch(isolate, sub, pat, start_index);
3556  return Smi::FromInt(position);
3557 }
3558 
3559 
3560 template <typename schar, typename pchar>
3561 static int StringMatchBackwards(Vector<const schar> subject,
3562  Vector<const pchar> pattern,
3563  int idx) {
3564  int pattern_length = pattern.length();
3565  ASSERT(pattern_length >= 1);
3566  ASSERT(idx + pattern_length <= subject.length());
3567 
3568  if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
3569  for (int i = 0; i < pattern_length; i++) {
3570  uc16 c = pattern[i];
3571  if (c > String::kMaxAsciiCharCode) {
3572  return -1;
3573  }
3574  }
3575  }
3576 
3577  pchar pattern_first_char = pattern[0];
3578  for (int i = idx; i >= 0; i--) {
3579  if (subject[i] != pattern_first_char) continue;
3580  int j = 1;
3581  while (j < pattern_length) {
3582  if (pattern[j] != subject[i+j]) {
3583  break;
3584  }
3585  j++;
3586  }
3587  if (j == pattern_length) {
3588  return i;
3589  }
3590  }
3591  return -1;
3592 }
3593 
3594 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
3595  HandleScope scope(isolate); // create a new handle scope
3596  ASSERT(args.length() == 3);
3597 
3600 
3601  Object* index = args[2];
3602  uint32_t start_index;
3603  if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
3604 
3605  uint32_t pat_length = pat->length();
3606  uint32_t sub_length = sub->length();
3607 
3608  if (start_index + pat_length > sub_length) {
3609  start_index = sub_length - pat_length;
3610  }
3611 
3612  if (pat_length == 0) {
3613  return Smi::FromInt(start_index);
3614  }
3615 
3616  if (!sub->IsFlat()) FlattenString(sub);
3617  if (!pat->IsFlat()) FlattenString(pat);
3618 
3619  int position = -1;
3620  AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
3621 
3622  String::FlatContent sub_content = sub->GetFlatContent();
3623  String::FlatContent pat_content = pat->GetFlatContent();
3624 
3625  if (pat_content.IsAscii()) {
3626  Vector<const char> pat_vector = pat_content.ToAsciiVector();
3627  if (sub_content.IsAscii()) {
3628  position = StringMatchBackwards(sub_content.ToAsciiVector(),
3629  pat_vector,
3630  start_index);
3631  } else {
3632  position = StringMatchBackwards(sub_content.ToUC16Vector(),
3633  pat_vector,
3634  start_index);
3635  }
3636  } else {
3637  Vector<const uc16> pat_vector = pat_content.ToUC16Vector();
3638  if (sub_content.IsAscii()) {
3639  position = StringMatchBackwards(sub_content.ToAsciiVector(),
3640  pat_vector,
3641  start_index);
3642  } else {
3643  position = StringMatchBackwards(sub_content.ToUC16Vector(),
3644  pat_vector,
3645  start_index);
3646  }
3647  }
3648 
3649  return Smi::FromInt(position);
3650 }
3651 
3652 
3653 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
3654  NoHandleAllocation ha;
3655  ASSERT(args.length() == 2);
3656 
3657  CONVERT_ARG_CHECKED(String, str1, 0);
3658  CONVERT_ARG_CHECKED(String, str2, 1);
3659 
3660  if (str1 == str2) return Smi::FromInt(0); // Equal.
3661  int str1_length = str1->length();
3662  int str2_length = str2->length();
3663 
3664  // Decide trivial cases without flattening.
3665  if (str1_length == 0) {
3666  if (str2_length == 0) return Smi::FromInt(0); // Equal.
3667  return Smi::FromInt(-str2_length);
3668  } else {
3669  if (str2_length == 0) return Smi::FromInt(str1_length);
3670  }
3671 
3672  int end = str1_length < str2_length ? str1_length : str2_length;
3673 
3674  // No need to flatten if we are going to find the answer on the first
3675  // character. At this point we know there is at least one character
3676  // in each string, due to the trivial case handling above.
3677  int d = str1->Get(0) - str2->Get(0);
3678  if (d != 0) return Smi::FromInt(d);
3679 
3680  str1->TryFlatten();
3681  str2->TryFlatten();
3682 
3683  StringInputBuffer& buf1 =
3684  *isolate->runtime_state()->string_locale_compare_buf1();
3685  StringInputBuffer& buf2 =
3686  *isolate->runtime_state()->string_locale_compare_buf2();
3687 
3688  buf1.Reset(str1);
3689  buf2.Reset(str2);
3690 
3691  for (int i = 0; i < end; i++) {
3692  uint16_t char1 = buf1.GetNext();
3693  uint16_t char2 = buf2.GetNext();
3694  if (char1 != char2) return Smi::FromInt(char1 - char2);
3695  }
3696 
3697  return Smi::FromInt(str1_length - str2_length);
3698 }
3699 
3700 
3701 RUNTIME_FUNCTION(MaybeObject*, Runtime_SubString) {
3702  NoHandleAllocation ha;
3703  ASSERT(args.length() == 3);
3704 
3705  CONVERT_ARG_CHECKED(String, value, 0);
3706  int start, end;
3707  // We have a fast integer-only case here to avoid a conversion to double in
3708  // the common case where from and to are Smis.
3709  if (args[1]->IsSmi() && args[2]->IsSmi()) {
3710  CONVERT_SMI_ARG_CHECKED(from_number, 1);
3711  CONVERT_SMI_ARG_CHECKED(to_number, 2);
3712  start = from_number;
3713  end = to_number;
3714  } else {
3715  CONVERT_DOUBLE_ARG_CHECKED(from_number, 1);
3716  CONVERT_DOUBLE_ARG_CHECKED(to_number, 2);
3717  start = FastD2I(from_number);
3718  end = FastD2I(to_number);
3719  }
3720  RUNTIME_ASSERT(end >= start);
3721  RUNTIME_ASSERT(start >= 0);
3722  RUNTIME_ASSERT(end <= value->length());
3723  isolate->counters()->sub_string_runtime()->Increment();
3724  return value->SubString(start, end);
3725 }
3726 
3727 
3728 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) {
3729  ASSERT_EQ(3, args.length());
3730 
3731  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
3733  CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2);
3734  HandleScope handles;
3735 
3736  Handle<Object> match = RegExpImpl::Exec(regexp, subject, 0, regexp_info,
3737  isolate->zone());
3738 
3739  if (match.is_null()) {
3740  return Failure::Exception();
3741  }
3742  if (match->IsNull()) {
3743  return isolate->heap()->null_value();
3744  }
3745  int length = subject->length();
3746 
3747  Zone* zone = isolate->zone();
3748  ZoneScope zone_space(isolate, DELETE_ON_EXIT);
3749  ZoneList<int> offsets(8, zone);
3750  int start;
3751  int end;
3752  do {
3753  {
3754  AssertNoAllocation no_alloc;
3755  FixedArray* elements = FixedArray::cast(regexp_info->elements());
3756  start = Smi::cast(elements->get(RegExpImpl::kFirstCapture))->value();
3757  end = Smi::cast(elements->get(RegExpImpl::kFirstCapture + 1))->value();
3758  }
3759  offsets.Add(start, zone);
3760  offsets.Add(end, zone);
3761  if (start == end) if (++end > length) break;
3762  match = RegExpImpl::Exec(regexp, subject, end, regexp_info,
3763  isolate->zone());
3764  if (match.is_null()) {
3765  return Failure::Exception();
3766  }
3767  } while (!match->IsNull());
3768  int matches = offsets.length() / 2;
3769  Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches);
3770  Handle<String> substring = isolate->factory()->
3771  NewSubString(subject, offsets.at(0), offsets.at(1));
3772  elements->set(0, *substring);
3773  for (int i = 1; i < matches ; i++) {
3774  int from = offsets.at(i * 2);
3775  int to = offsets.at(i * 2 + 1);
3776  Handle<String> substring = isolate->factory()->
3777  NewProperSubString(subject, from, to);
3778  elements->set(i, *substring);
3779  }
3780  Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements);
3781  result->set_length(Smi::FromInt(matches));
3782  return *result;
3783 }
3784 
3785 
3786 static bool SearchStringMultiple(Isolate* isolate,
3787  Handle<String> subject,
3788  Handle<String> pattern,
3789  Handle<JSArray> last_match_info,
3790  FixedArrayBuilder* builder) {
3791  ASSERT(subject->IsFlat());
3792  ASSERT(pattern->IsFlat());
3793 
3794  // Treating as if a previous match was before first character.
3795  int match_pos = -pattern->length();
3796 
3797  for (;;) { // Break when search complete.
3798  builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3799  AssertNoAllocation no_gc;
3800  String::FlatContent subject_content = subject->GetFlatContent();
3801  String::FlatContent pattern_content = pattern->GetFlatContent();
3802  if (subject_content.IsAscii()) {
3803  Vector<const char> subject_vector = subject_content.ToAsciiVector();
3804  if (pattern_content.IsAscii()) {
3805  if (SearchStringMultiple(isolate,
3806  subject_vector,
3807  pattern_content.ToAsciiVector(),
3808  *pattern,
3809  builder,
3810  &match_pos)) break;
3811  } else {
3812  if (SearchStringMultiple(isolate,
3813  subject_vector,
3814  pattern_content.ToUC16Vector(),
3815  *pattern,
3816  builder,
3817  &match_pos)) break;
3818  }
3819  } else {
3820  Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
3821  if (pattern_content.IsAscii()) {
3822  if (SearchStringMultiple(isolate,
3823  subject_vector,
3824  pattern_content.ToAsciiVector(),
3825  *pattern,
3826  builder,
3827  &match_pos)) break;
3828  } else {
3829  if (SearchStringMultiple(isolate,
3830  subject_vector,
3831  pattern_content.ToUC16Vector(),
3832  *pattern,
3833  builder,
3834  &match_pos)) break;
3835  }
3836  }
3837  }
3838 
3839  if (match_pos >= 0) {
3840  SetLastMatchInfoNoCaptures(subject,
3841  last_match_info,
3842  match_pos,
3843  match_pos + pattern->length());
3844  return true;
3845  }
3846  return false; // No matches at all.
3847 }
3848 
3849 
3850 static int SearchRegExpNoCaptureMultiple(
3851  Isolate* isolate,
3852  Handle<String> subject,
3853  Handle<JSRegExp> regexp,
3854  Handle<JSArray> last_match_array,
3855  FixedArrayBuilder* builder) {
3856  ASSERT(subject->IsFlat());
3857  ASSERT(regexp->CaptureCount() == 0);
3858  int match_start = -1;
3859  int match_end = 0;
3860  int pos = 0;
3861  int registers_per_match = RegExpImpl::IrregexpPrepare(regexp, subject,
3862  isolate->zone());
3863  if (registers_per_match < 0) return RegExpImpl::RE_EXCEPTION;
3864 
3865  int max_matches;
3866  int num_registers = RegExpImpl::GlobalOffsetsVectorSize(regexp,
3867  registers_per_match,
3868  &max_matches);
3869  OffsetsVector registers(num_registers, isolate);
3870  Vector<int32_t> register_vector(registers.vector(), registers.length());
3871  int subject_length = subject->length();
3872  bool first = true;
3873  for (;;) { // Break on failure, return on exception.
3874  int num_matches = RegExpImpl::IrregexpExecRaw(regexp,
3875  subject,
3876  pos,
3877  register_vector,
3878  isolate->zone());
3879  if (num_matches > 0) {
3880  for (int match_index = 0; match_index < num_matches; match_index++) {
3881  int32_t* current_match = &register_vector[match_index * 2];
3882  match_start = current_match[0];
3883  builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3884  if (match_end < match_start) {
3886  match_end,
3887  match_start);
3888  }
3889  match_end = current_match[1];
3890  HandleScope loop_scope(isolate);
3891  if (!first) {
3892  builder->Add(*isolate->factory()->NewProperSubString(subject,
3893  match_start,
3894  match_end));
3895  } else {
3896  builder->Add(*isolate->factory()->NewSubString(subject,
3897  match_start,
3898  match_end));
3899  first = false;
3900  }
3901  }
3902 
3903  // If we did not get the maximum number of matches, we can stop here
3904  // since there are no matches left.
3905  if (num_matches < max_matches) break;
3906 
3907  if (match_start != match_end) {
3908  pos = match_end;
3909  } else {
3910  pos = match_end + 1;
3911  if (pos > subject_length) break;
3912  }
3913  } else if (num_matches == 0) {
3914  break;
3915  } else {
3916  ASSERT_EQ(num_matches, RegExpImpl::RE_EXCEPTION);
3917  return RegExpImpl::RE_EXCEPTION;
3918  }
3919  }
3920 
3921  if (match_start >= 0) {
3922  if (match_end < subject_length) {
3924  match_end,
3925  subject_length);
3926  }
3927  SetLastMatchInfoNoCaptures(subject,
3928  last_match_array,
3929  match_start,
3930  match_end);
3931  return RegExpImpl::RE_SUCCESS;
3932  } else {
3933  return RegExpImpl::RE_FAILURE; // No matches at all.
3934  }
3935 }
3936 
3937 
3938 // Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain
3939 // separate last match info. See comment on that function.
3940 static int SearchRegExpMultiple(
3941  Isolate* isolate,
3942  Handle<String> subject,
3943  Handle<JSRegExp> regexp,
3944  Handle<JSArray> last_match_array,
3945  FixedArrayBuilder* builder) {
3946 
3947  ASSERT(subject->IsFlat());
3948  int registers_per_match = RegExpImpl::IrregexpPrepare(regexp, subject,
3949  isolate->zone());
3950  if (registers_per_match < 0) return RegExpImpl::RE_EXCEPTION;
3951 
3952  int max_matches;
3953  int num_registers = RegExpImpl::GlobalOffsetsVectorSize(regexp,
3954  registers_per_match,
3955  &max_matches);
3956  OffsetsVector registers(num_registers, isolate);
3957  Vector<int32_t> register_vector(registers.vector(), registers.length());
3958 
3959  int num_matches = RegExpImpl::IrregexpExecRaw(regexp,
3960  subject,
3961  0,
3962  register_vector,
3963  isolate->zone());
3964 
3965  int capture_count = regexp->CaptureCount();
3966  int subject_length = subject->length();
3967 
3968  // Position to search from.
3969  int pos = 0;
3970  // End of previous match. Differs from pos if match was empty.
3971  int match_end = 0;
3972  bool first = true;
3973 
3974  if (num_matches > 0) {
3975  do {
3976  int match_start = 0;
3977  for (int match_index = 0; match_index < num_matches; match_index++) {
3978  int32_t* current_match =
3979  &register_vector[match_index * registers_per_match];
3980  match_start = current_match[0];
3981  builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3982  if (match_end < match_start) {
3984  match_end,
3985  match_start);
3986  }
3987  match_end = current_match[1];
3988 
3989  {
3990  // Avoid accumulating new handles inside loop.
3991  HandleScope temp_scope(isolate);
3992  // Arguments array to replace function is match, captures, index and
3993  // subject, i.e., 3 + capture count in total.
3994  Handle<FixedArray> elements =
3995  isolate->factory()->NewFixedArray(3 + capture_count);
3996  Handle<String> match;
3997  if (!first) {
3998  match = isolate->factory()->NewProperSubString(subject,
3999  match_start,
4000  match_end);
4001  } else {
4002  match = isolate->factory()->NewSubString(subject,
4003  match_start,
4004  match_end);
4005  }
4006  elements->set(0, *match);
4007  for (int i = 1; i <= capture_count; i++) {
4008  int start = current_match[i * 2];
4009  if (start >= 0) {
4010  int end = current_match[i * 2 + 1];
4011  ASSERT(start <= end);
4012  Handle<String> substring;
4013  if (!first) {
4014  substring =
4015  isolate->factory()->NewProperSubString(subject, start, end);
4016  } else {
4017  substring =
4018  isolate->factory()->NewSubString(subject, start, end);
4019  }
4020  elements->set(i, *substring);
4021  } else {
4022  ASSERT(current_match[i * 2 + 1] < 0);
4023  elements->set(i, isolate->heap()->undefined_value());
4024  }
4025  }
4026  elements->set(capture_count + 1, Smi::FromInt(match_start));
4027  elements->set(capture_count + 2, *subject);
4028  builder->Add(*isolate->factory()->NewJSArrayWithElements(elements));
4029  }
4030  first = false;
4031  }
4032 
4033  // If we did not get the maximum number of matches, we can stop here
4034  // since there are no matches left.
4035  if (num_matches < max_matches) break;
4036 
4037  if (match_end > match_start) {
4038  pos = match_end;
4039  } else {
4040  pos = match_end + 1;
4041  if (pos > subject_length) {
4042  break;
4043  }
4044  }
4045 
4046  num_matches = RegExpImpl::IrregexpExecRaw(regexp,
4047  subject,
4048  pos,
4049  register_vector,
4050  isolate->zone());
4051  } while (num_matches > 0);
4052 
4053  if (num_matches != RegExpImpl::RE_EXCEPTION) {
4054  // Finished matching, with at least one match.
4055  if (match_end < subject_length) {
4057  match_end,
4058  subject_length);
4059  }
4060 
4061  int last_match_capture_count = (capture_count + 1) * 2;
4062  int last_match_array_size =
4063  last_match_capture_count + RegExpImpl::kLastMatchOverhead;
4064  last_match_array->EnsureSize(last_match_array_size);
4065  AssertNoAllocation no_gc;
4066  FixedArray* elements = FixedArray::cast(last_match_array->elements());
4067  // We have to set this even though the rest of the last match array is
4068  // ignored.
4069  RegExpImpl::SetLastCaptureCount(elements, last_match_capture_count);
4070  // These are also read without consulting the override.
4071  RegExpImpl::SetLastSubject(elements, *subject);
4072  RegExpImpl::SetLastInput(elements, *subject);
4073  return RegExpImpl::RE_SUCCESS;
4074  }
4075  }
4076  // No matches at all, return failure or exception result directly.
4077  return num_matches;
4078 }
4079 
4080 
4081 // This is only called for StringReplaceGlobalRegExpWithFunction. This sets
4082 // lastMatchInfoOverride to maintain the last match info, so we don't need to
4083 // set any other last match array info.
4084 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) {
4085  ASSERT(args.length() == 4);
4086  HandleScope handles(isolate);
4087 
4088  CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
4089  if (!subject->IsFlat()) FlattenString(subject);
4091  CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2);
4092  CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3);
4093 
4094  ASSERT(last_match_info->HasFastObjectElements());
4095  ASSERT(regexp->GetFlags().is_global());
4096  Handle<FixedArray> result_elements;
4097  if (result_array->HasFastObjectElements()) {
4098  result_elements =
4099  Handle<FixedArray>(FixedArray::cast(result_array->elements()));
4100  }
4101  if (result_elements.is_null() || result_elements->length() < 16) {
4102  result_elements = isolate->factory()->NewFixedArrayWithHoles(16);
4103  }
4104  FixedArrayBuilder builder(result_elements);
4105 
4106  if (regexp->TypeTag() == JSRegExp::ATOM) {
4107  Handle<String> pattern(
4108  String::cast(regexp->DataAt(JSRegExp::kAtomPatternIndex)));
4109  ASSERT(pattern->IsFlat());
4110  if (SearchStringMultiple(isolate, subject, pattern,
4111  last_match_info, &builder)) {
4112  return *builder.ToJSArray(result_array);
4113  }
4114  return isolate->heap()->null_value();
4115  }
4116 
4117  ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP);
4118 
4119  int result;
4120  if (regexp->CaptureCount() == 0) {
4121  result = SearchRegExpNoCaptureMultiple(isolate,
4122  subject,
4123  regexp,
4124  last_match_info,
4125  &builder);
4126  } else {
4127  result = SearchRegExpMultiple(isolate,
4128  subject,
4129  regexp,
4130  last_match_info,
4131  &builder);
4132  }
4133  if (result == RegExpImpl::RE_SUCCESS) return *builder.ToJSArray(result_array);
4134  if (result == RegExpImpl::RE_FAILURE) return isolate->heap()->null_value();
4136  return Failure::Exception();
4137 }
4138 
4139 
4140 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) {
4141  NoHandleAllocation ha;
4142  ASSERT(args.length() == 2);
4143  CONVERT_SMI_ARG_CHECKED(radix, 1);
4144  RUNTIME_ASSERT(2 <= radix && radix <= 36);
4145 
4146  // Fast case where the result is a one character string.
4147  if (args[0]->IsSmi()) {
4148  int value = args.smi_at(0);
4149  if (value >= 0 && value < radix) {
4150  // Character array used for conversion.
4151  static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
4152  return isolate->heap()->
4153  LookupSingleCharacterStringFromCode(kCharTable[value]);
4154  }
4155  }
4156 
4157  // Slow case.
4158  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4159  if (isnan(value)) {
4160  return *isolate->factory()->nan_symbol();
4161  }
4162  if (isinf(value)) {
4163  if (value < 0) {
4164  return *isolate->factory()->minus_infinity_symbol();
4165  }
4166  return *isolate->factory()->infinity_symbol();
4167  }
4168  char* str = DoubleToRadixCString(value, radix);
4169  MaybeObject* result =
4170  isolate->heap()->AllocateStringFromAscii(CStrVector(str));
4171  DeleteArray(str);
4172  return result;
4173 }
4174 
4175 
4176 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) {
4177  NoHandleAllocation ha;
4178  ASSERT(args.length() == 2);
4179 
4180  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4181  if (isnan(value)) {
4182  return *isolate->factory()->nan_symbol();
4183  }
4184  if (isinf(value)) {
4185  if (value < 0) {
4186  return *isolate->factory()->minus_infinity_symbol();
4187  }
4188  return *isolate->factory()->infinity_symbol();
4189  }
4190  CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4191  int f = FastD2I(f_number);
4192  RUNTIME_ASSERT(f >= 0);
4193  char* str = DoubleToFixedCString(value, f);
4194  MaybeObject* res =
4195  isolate->heap()->AllocateStringFromAscii(CStrVector(str));
4196  DeleteArray(str);
4197  return res;
4198 }
4199 
4200 
4201 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) {
4202  NoHandleAllocation ha;
4203  ASSERT(args.length() == 2);
4204 
4205  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4206  if (isnan(value)) {
4207  return *isolate->factory()->nan_symbol();
4208  }
4209  if (isinf(value)) {
4210  if (value < 0) {
4211  return *isolate->factory()->minus_infinity_symbol();
4212  }
4213  return *isolate->factory()->infinity_symbol();
4214  }
4215  CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4216  int f = FastD2I(f_number);
4217  RUNTIME_ASSERT(f >= -1 && f <= 20);
4218  char* str = DoubleToExponentialCString(value, f);
4219  MaybeObject* res =
4220  isolate->heap()->AllocateStringFromAscii(CStrVector(str));
4221  DeleteArray(str);
4222  return res;
4223 }
4224 
4225 
4226 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) {
4227  NoHandleAllocation ha;
4228  ASSERT(args.length() == 2);
4229 
4230  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4231  if (isnan(value)) {
4232  return *isolate->factory()->nan_symbol();
4233  }
4234  if (isinf(value)) {
4235  if (value < 0) {
4236  return *isolate->factory()->minus_infinity_symbol();
4237  }
4238  return *isolate->factory()->infinity_symbol();
4239  }
4240  CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4241  int f = FastD2I(f_number);
4242  RUNTIME_ASSERT(f >= 1 && f <= 21);
4243  char* str = DoubleToPrecisionCString(value, f);
4244  MaybeObject* res =
4245  isolate->heap()->AllocateStringFromAscii(CStrVector(str));
4246  DeleteArray(str);
4247  return res;
4248 }
4249 
4250 
4251 // Returns a single character string where first character equals
4252 // string->Get(index).
4253 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
4254  if (index < static_cast<uint32_t>(string->length())) {
4255  string->TryFlatten();
4257  string->Get(index));
4258  }
4259  return Execution::CharAt(string, index);
4260 }
4261 
4262 
4263 MaybeObject* Runtime::GetElementOrCharAt(Isolate* isolate,
4264  Handle<Object> object,
4265  uint32_t index) {
4266  // Handle [] indexing on Strings
4267  if (object->IsString()) {
4268  Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
4269  if (!result->IsUndefined()) return *result;
4270  }
4271 
4272  // Handle [] indexing on String objects
4273  if (object->IsStringObjectWithCharacterAt(index)) {
4274  Handle<JSValue> js_value = Handle<JSValue>::cast(object);
4275  Handle<Object> result =
4276  GetCharAt(Handle<String>(String::cast(js_value->value())), index);
4277  if (!result->IsUndefined()) return *result;
4278  }
4279 
4280  if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
4281  return object->GetPrototype()->GetElement(index);
4282  }
4283 
4284  return object->GetElement(index);
4285 }
4286 
4287 
4288 MaybeObject* Runtime::GetObjectProperty(Isolate* isolate,
4289  Handle<Object> object,
4290  Handle<Object> key) {
4291  HandleScope scope(isolate);
4292 
4293  if (object->IsUndefined() || object->IsNull()) {
4294  Handle<Object> args[2] = { key, object };
4295  Handle<Object> error =
4296  isolate->factory()->NewTypeError("non_object_property_load",
4297  HandleVector(args, 2));
4298  return isolate->Throw(*error);
4299  }
4300 
4301  // Check if the given key is an array index.
4302  uint32_t index;
4303  if (key->ToArrayIndex(&index)) {
4304  return GetElementOrCharAt(isolate, object, index);
4305  }
4306 
4307  // Convert the key to a string - possibly by calling back into JavaScript.
4309  if (key->IsString()) {
4310  name = Handle<String>::cast(key);
4311  } else {
4312  bool has_pending_exception = false;
4313  Handle<Object> converted =
4314  Execution::ToString(key, &has_pending_exception);
4315  if (has_pending_exception) return Failure::Exception();
4316  name = Handle<String>::cast(converted);
4317  }
4318 
4319  // Check if the name is trivially convertible to an index and get
4320  // the element if so.
4321  if (name->AsArrayIndex(&index)) {
4322  return GetElementOrCharAt(isolate, object, index);
4323  } else {
4324  return object->GetProperty(*name);
4325  }
4326 }
4327 
4328 
4329 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetProperty) {
4330  NoHandleAllocation ha;
4331  ASSERT(args.length() == 2);
4332 
4333  Handle<Object> object = args.at<Object>(0);
4334  Handle<Object> key = args.at<Object>(1);
4335 
4336  return Runtime::GetObjectProperty(isolate, object, key);
4337 }
4338 
4339 
4340 // KeyedStringGetProperty is called from KeyedLoadIC::GenerateGeneric.
4341 RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
4342  NoHandleAllocation ha;
4343  ASSERT(args.length() == 2);
4344 
4345  // Fast cases for getting named properties of the receiver JSObject
4346  // itself.
4347  //
4348  // The global proxy objects has to be excluded since LocalLookup on
4349  // the global proxy object can return a valid result even though the
4350  // global proxy object never has properties. This is the case
4351  // because the global proxy object forwards everything to its hidden
4352  // prototype including local lookups.
4353  //
4354  // Additionally, we need to make sure that we do not cache results
4355  // for objects that require access checks.
4356  if (args[0]->IsJSObject()) {
4357  if (!args[0]->IsJSGlobalProxy() &&
4358  !args[0]->IsAccessCheckNeeded() &&
4359  args[1]->IsString()) {
4360  JSObject* receiver = JSObject::cast(args[0]);
4361  String* key = String::cast(args[1]);
4362  if (receiver->HasFastProperties()) {
4363  // Attempt to use lookup cache.
4364  Map* receiver_map = receiver->map();
4365  KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache();
4366  int offset = keyed_lookup_cache->Lookup(receiver_map, key);
4367  if (offset != -1) {
4368  Object* value = receiver->FastPropertyAt(offset);
4369  return value->IsTheHole()
4370  ? isolate->heap()->undefined_value()
4371  : value;
4372  }
4373  // Lookup cache miss. Perform lookup and update the cache if
4374  // appropriate.
4375  LookupResult result(isolate);
4376  receiver->LocalLookup(key, &result);
4377  if (result.IsFound() && result.type() == FIELD) {
4378  int offset = result.GetFieldIndex();
4379  keyed_lookup_cache->Update(receiver_map, key, offset);
4380  return receiver->FastPropertyAt(offset);
4381  }
4382  } else {
4383  // Attempt dictionary lookup.
4384  StringDictionary* dictionary = receiver->property_dictionary();
4385  int entry = dictionary->FindEntry(key);
4386  if ((entry != StringDictionary::kNotFound) &&
4387  (dictionary->DetailsAt(entry).type() == NORMAL)) {
4388  Object* value = dictionary->ValueAt(entry);
4389  if (!receiver->IsGlobalObject()) return value;
4390  value = JSGlobalPropertyCell::cast(value)->value();
4391  if (!value->IsTheHole()) return value;
4392  // If value is the hole do the general lookup.
4393  }
4394  }
4395  } else if (FLAG_smi_only_arrays && args.at<Object>(1)->IsSmi()) {
4396  // JSObject without a string key. If the key is a Smi, check for a
4397  // definite out-of-bounds access to elements, which is a strong indicator
4398  // that subsequent accesses will also call the runtime. Proactively
4399  // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
4400  // doubles for those future calls in the case that the elements would
4401  // become FAST_DOUBLE_ELEMENTS.
4402  Handle<JSObject> js_object(args.at<JSObject>(0));
4403  ElementsKind elements_kind = js_object->GetElementsKind();
4404  if (IsFastElementsKind(elements_kind) &&
4405  !IsFastObjectElementsKind(elements_kind)) {
4406  FixedArrayBase* elements = js_object->elements();
4407  if (args.at<Smi>(1)->value() >= elements->length()) {
4408  if (IsFastHoleyElementsKind(elements_kind)) {
4409  elements_kind = FAST_HOLEY_ELEMENTS;
4410  } else {
4411  elements_kind = FAST_ELEMENTS;
4412  }
4413  MaybeObject* maybe_object = TransitionElements(js_object,
4414  elements_kind,
4415  isolate);
4416  if (maybe_object->IsFailure()) return maybe_object;
4417  }
4418  }
4419  }
4420  } else if (args[0]->IsString() && args[1]->IsSmi()) {
4421  // Fast case for string indexing using [] with a smi index.
4422  HandleScope scope(isolate);
4423  Handle<String> str = args.at<String>(0);
4424  int index = args.smi_at(1);
4425  if (index >= 0 && index < str->length()) {
4426  Handle<Object> result = GetCharAt(str, index);
4427  return *result;
4428  }
4429  }
4430 
4431  // Fall back to GetObjectProperty.
4432  return Runtime::GetObjectProperty(isolate,
4433  args.at<Object>(0),
4434  args.at<Object>(1));
4435 }
4436 
4437 
4438 static bool IsValidAccessor(Handle<Object> obj) {
4439  return obj->IsUndefined() || obj->IsSpecFunction() || obj->IsNull();
4440 }
4441 
4442 
4443 // Implements part of 8.12.9 DefineOwnProperty.
4444 // There are 3 cases that lead here:
4445 // Step 4b - define a new accessor property.
4446 // Steps 9c & 12 - replace an existing data property with an accessor property.
4447 // Step 12 - update an existing accessor property with an accessor or generic
4448 // descriptor.
4449 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) {
4450  ASSERT(args.length() == 5);
4451  HandleScope scope(isolate);
4453  RUNTIME_ASSERT(!obj->IsNull());
4455  CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
4456  RUNTIME_ASSERT(IsValidAccessor(getter));
4457  CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
4458  RUNTIME_ASSERT(IsValidAccessor(setter));
4459  CONVERT_SMI_ARG_CHECKED(unchecked, 4);
4460  RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4461  PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
4462 
4463  bool fast = obj->HasFastProperties();
4464  JSObject::DefineAccessor(obj, name, getter, setter, attr);
4465  if (fast) JSObject::TransformToFastProperties(obj, 0);
4466  return isolate->heap()->undefined_value();
4467 }
4468 
4469 // Implements part of 8.12.9 DefineOwnProperty.
4470 // There are 3 cases that lead here:
4471 // Step 4a - define a new data property.
4472 // Steps 9b & 12 - replace an existing accessor property with a data property.
4473 // Step 12 - update an existing data property with a data or generic
4474 // descriptor.
4475 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
4476  ASSERT(args.length() == 4);
4477  HandleScope scope(isolate);
4478  CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
4480  CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2);
4481  CONVERT_SMI_ARG_CHECKED(unchecked, 3);
4482  RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4483  PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
4484 
4485  LookupResult result(isolate);
4486  js_object->LocalLookupRealNamedProperty(*name, &result);
4487 
4488  // Special case for callback properties.
4489  if (result.IsFound() && result.type() == CALLBACKS) {
4490  Object* callback = result.GetCallbackObject();
4491  // To be compatible with Safari we do not change the value on API objects
4492  // in Object.defineProperty(). Firefox disagrees here, and actually changes
4493  // the value.
4494  if (callback->IsAccessorInfo()) {
4495  return isolate->heap()->undefined_value();
4496  }
4497  // Avoid redefining foreign callback as data property, just use the stored
4498  // setter to update the value instead.
4499  // TODO(mstarzinger): So far this only works if property attributes don't
4500  // change, this should be fixed once we cleanup the underlying code.
4501  if (callback->IsForeign() && result.GetAttributes() == attr) {
4502  return js_object->SetPropertyWithCallback(callback,
4503  *name,
4504  *obj_value,
4505  result.holder(),
4506  kStrictMode);
4507  }
4508  }
4509 
4510  // Take special care when attributes are different and there is already
4511  // a property. For simplicity we normalize the property which enables us
4512  // to not worry about changing the instance_descriptor and creating a new
4513  // map. The current version of SetObjectProperty does not handle attributes
4514  // correctly in the case where a property is a field and is reset with
4515  // new attributes.
4516  if (result.IsProperty() &&
4517  (attr != result.GetAttributes() || result.type() == CALLBACKS)) {
4518  // New attributes - normalize to avoid writing to instance descriptor
4519  if (js_object->IsJSGlobalProxy()) {
4520  // Since the result is a property, the prototype will exist so
4521  // we don't have to check for null.
4522  js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype()));
4523  }
4525  // Use IgnoreAttributes version since a readonly property may be
4526  // overridden and SetProperty does not allow this.
4527  return js_object->SetLocalPropertyIgnoreAttributes(*name,
4528  *obj_value,
4529  attr);
4530  }
4531 
4532  return Runtime::ForceSetObjectProperty(isolate,
4533  js_object,
4534  name,
4535  obj_value,
4536  attr);
4537 }
4538 
4539 
4540 MaybeObject* Runtime::SetObjectProperty(Isolate* isolate,
4541  Handle<Object> object,
4542  Handle<Object> key,
4543  Handle<Object> value,
4544  PropertyAttributes attr,
4545  StrictModeFlag strict_mode) {
4546  SetPropertyMode set_mode = attr == NONE ? SET_PROPERTY : DEFINE_PROPERTY;
4547  HandleScope scope(isolate);
4548 
4549  if (object->IsUndefined() || object->IsNull()) {
4550  Handle<Object> args[2] = { key, object };
4551  Handle<Object> error =
4552  isolate->factory()->NewTypeError("non_object_property_store",
4553  HandleVector(args, 2));
4554  return isolate->Throw(*error);
4555  }
4556 
4557  if (object->IsJSProxy()) {
4558  bool has_pending_exception = false;
4559  Handle<Object> name = Execution::ToString(key, &has_pending_exception);
4560  if (has_pending_exception) return Failure::Exception();
4561  return JSProxy::cast(*object)->SetProperty(
4562  String::cast(*name), *value, attr, strict_mode);
4563  }
4564 
4565  // If the object isn't a JavaScript object, we ignore the store.
4566  if (!object->IsJSObject()) return *value;
4567 
4568  Handle<JSObject> js_object = Handle<JSObject>::cast(object);
4569 
4570  // Check if the given key is an array index.
4571  uint32_t index;
4572  if (key->ToArrayIndex(&index)) {
4573  // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
4574  // of a string using [] notation. We need to support this too in
4575  // JavaScript.
4576  // In the case of a String object we just need to redirect the assignment to
4577  // the underlying string if the index is in range. Since the underlying
4578  // string does nothing with the assignment then we can ignore such
4579  // assignments.
4580  if (js_object->IsStringObjectWithCharacterAt(index)) {
4581  return *value;
4582  }
4583 
4584  js_object->ValidateElements();
4586  js_object, index, value, attr, strict_mode, set_mode);
4587  js_object->ValidateElements();
4588  if (result.is_null()) return Failure::Exception();
4589  return *value;
4590  }
4591 
4592  if (key->IsString()) {
4593  Handle<Object> result;
4594  if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
4595  result = JSObject::SetElement(
4596  js_object, index, value, attr, strict_mode, set_mode);
4597  } else {
4598  Handle<String> key_string = Handle<String>::cast(key);
4599  key_string->TryFlatten();
4600  result = JSReceiver::SetProperty(
4601  js_object, key_string, value, attr, strict_mode);
4602  }
4603  if (result.is_null()) return Failure::Exception();
4604  return *value;
4605  }
4606 
4607  // Call-back into JavaScript to convert the key to a string.
4608  bool has_pending_exception = false;
4609  Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
4610  if (has_pending_exception) return Failure::Exception();
4611  Handle<String> name = Handle<String>::cast(converted);
4612 
4613  if (name->AsArrayIndex(&index)) {
4614  return js_object->SetElement(
4615  index, *value, attr, strict_mode, true, set_mode);
4616  } else {
4617  return js_object->SetProperty(*name, *value, attr, strict_mode);
4618  }
4619 }
4620 
4621 
4623  Handle<JSObject> js_object,
4624  Handle<Object> key,
4625  Handle<Object> value,
4626  PropertyAttributes attr) {
4627  HandleScope scope(isolate);
4628 
4629  // Check if the given key is an array index.
4630  uint32_t index;
4631  if (key->ToArrayIndex(&index)) {
4632  // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
4633  // of a string using [] notation. We need to support this too in
4634  // JavaScript.
4635  // In the case of a String object we just need to redirect the assignment to
4636  // the underlying string if the index is in range. Since the underlying
4637  // string does nothing with the assignment then we can ignore such
4638  // assignments.
4639  if (js_object->IsStringObjectWithCharacterAt(index)) {
4640  return *value;
4641  }
4642 
4643  return js_object->SetElement(
4644  index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
4645  }
4646 
4647  if (key->IsString()) {
4648  if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
4649  return js_object->SetElement(
4650  index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
4651  } else {
4652  Handle<String> key_string = Handle<String>::cast(key);
4653  key_string->TryFlatten();
4654  return js_object->SetLocalPropertyIgnoreAttributes(*key_string,
4655  *value,
4656  attr);
4657  }
4658  }
4659 
4660  // Call-back into JavaScript to convert the key to a string.
4661  bool has_pending_exception = false;
4662  Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
4663  if (has_pending_exception) return Failure::Exception();
4664  Handle<String> name = Handle<String>::cast(converted);
4665 
4666  if (name->AsArrayIndex(&index)) {
4667  return js_object->SetElement(
4668  index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
4669  } else {
4670  return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr);
4671  }
4672 }
4673 
4674 
4676  Handle<JSReceiver> receiver,
4677  Handle<Object> key) {
4678  HandleScope scope(isolate);
4679 
4680  // Check if the given key is an array index.
4681  uint32_t index;
4682  if (key->ToArrayIndex(&index)) {
4683  // In Firefox/SpiderMonkey, Safari and Opera you can access the
4684  // characters of a string using [] notation. In the case of a
4685  // String object we just need to redirect the deletion to the
4686  // underlying string if the index is in range. Since the
4687  // underlying string does nothing with the deletion, we can ignore
4688  // such deletions.
4689  if (receiver->IsStringObjectWithCharacterAt(index)) {
4690  return isolate->heap()->true_value();
4691  }
4692 
4693  return receiver->DeleteElement(index, JSReceiver::FORCE_DELETION);
4694  }
4695 
4696  Handle<String> key_string;
4697  if (key->IsString()) {
4698  key_string = Handle<String>::cast(key);
4699  } else {
4700  // Call-back into JavaScript to convert the key to a string.
4701  bool has_pending_exception = false;
4702  Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
4703  if (has_pending_exception) return Failure::Exception();
4704  key_string = Handle<String>::cast(converted);
4705  }
4706 
4707  key_string->TryFlatten();
4708  return receiver->DeleteProperty(*key_string, JSReceiver::FORCE_DELETION);
4709 }
4710 
4711 
4712 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) {
4713  NoHandleAllocation ha;
4714  RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
4715 
4716  Handle<Object> object = args.at<Object>(0);
4717  Handle<Object> key = args.at<Object>(1);
4718  Handle<Object> value = args.at<Object>(2);
4719  CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3);
4721  (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4722  // Compute attributes.
4723  PropertyAttributes attributes =
4724  static_cast<PropertyAttributes>(unchecked_attributes);
4725 
4726  StrictModeFlag strict_mode = kNonStrictMode;
4727  if (args.length() == 5) {
4728  CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode_flag, 4);
4729  strict_mode = strict_mode_flag;
4730  }
4731 
4732  return Runtime::SetObjectProperty(isolate,
4733  object,
4734  key,
4735  value,
4736  attributes,
4737  strict_mode);
4738 }
4739 
4740 
4741 RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsSmiToDouble) {
4742  NoHandleAllocation ha;
4743  RUNTIME_ASSERT(args.length() == 1);
4744  Handle<Object> object = args.at<Object>(0);
4745  if (object->IsJSObject()) {
4746  Handle<JSObject> js_object(Handle<JSObject>::cast(object));
4747  ElementsKind new_kind = js_object->HasFastHoleyElements()
4750  return TransitionElements(object, new_kind, isolate);
4751  } else {
4752  return *object;
4753  }
4754 }
4755 
4756 
4757 RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsDoubleToObject) {
4758  NoHandleAllocation ha;
4759  RUNTIME_ASSERT(args.length() == 1);
4760  Handle<Object> object = args.at<Object>(0);
4761  if (object->IsJSObject()) {
4762  Handle<JSObject> js_object(Handle<JSObject>::cast(object));
4763  ElementsKind new_kind = js_object->HasFastHoleyElements()
4765  : FAST_ELEMENTS;
4766  return TransitionElements(object, new_kind, isolate);
4767  } else {
4768  return *object;
4769  }
4770 }
4771 
4772 
4773 // Set the native flag on the function.
4774 // This is used to decide if we should transform null and undefined
4775 // into the global object when doing call and apply.
4776 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) {
4777  NoHandleAllocation ha;
4778  RUNTIME_ASSERT(args.length() == 1);
4779 
4780  Handle<Object> object = args.at<Object>(0);
4781 
4782  if (object->IsJSFunction()) {
4783  JSFunction* func = JSFunction::cast(*object);
4784  func->shared()->set_native(true);
4785  }
4786  return isolate->heap()->undefined_value();
4787 }
4788 
4789 
4790 RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) {
4791  RUNTIME_ASSERT(args.length() == 5);
4793  CONVERT_SMI_ARG_CHECKED(store_index, 1);
4794  Handle<Object> value = args.at<Object>(2);
4795  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 3);
4796  CONVERT_SMI_ARG_CHECKED(literal_index, 4);
4797  HandleScope scope;
4798 
4799  Object* raw_boilerplate_object = literals->get(literal_index);
4800  Handle<JSArray> boilerplate_object(JSArray::cast(raw_boilerplate_object));
4801  ElementsKind elements_kind = object->GetElementsKind();
4802  ASSERT(IsFastElementsKind(elements_kind));
4803  // Smis should never trigger transitions.
4804  ASSERT(!value->IsSmi());
4805 
4806  if (value->IsNumber()) {
4807  ASSERT(IsFastSmiElementsKind(elements_kind));
4808  ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
4812  boilerplate_object->GetElementsKind(),
4813  transitioned_kind)) {
4814  JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
4815  }
4816  JSObject::TransitionElementsKind(object, transitioned_kind);
4817  ASSERT(IsFastDoubleElementsKind(object->GetElementsKind()));
4818  FixedDoubleArray* double_array = FixedDoubleArray::cast(object->elements());
4819  HeapNumber* number = HeapNumber::cast(*value);
4820  double_array->set(store_index, number->Number());
4821  } else {
4822  ASSERT(IsFastSmiElementsKind(elements_kind) ||
4823  IsFastDoubleElementsKind(elements_kind));
4824  ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
4826  : FAST_ELEMENTS;
4827  JSObject::TransitionElementsKind(object, transitioned_kind);
4829  boilerplate_object->GetElementsKind(),
4830  transitioned_kind)) {
4831  JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
4832  }
4833  FixedArray* object_array = FixedArray::cast(object->elements());
4834  object_array->set(store_index, *value);
4835  }
4836  return *object;
4837 }
4838 
4839 
4840 // Check whether debugger and is about to step into the callback that is passed
4841 // to a built-in function such as Array.forEach.
4842 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugCallbackSupportsStepping) {
4843  if (!isolate->IsDebuggerActive()) return isolate->heap()->false_value();
4844  CONVERT_ARG_CHECKED(Object, callback, 0);
4845  // We do not step into the callback if it's a builtin or not even a function.
4846  if (!callback->IsJSFunction() || JSFunction::cast(callback)->IsBuiltin()) {
4847  return isolate->heap()->false_value();
4848  }
4849  return isolate->heap()->true_value();
4850 }
4851 
4852 
4853 // Set one shot breakpoints for the callback function that is passed to a
4854 // built-in function such as Array.forEach to enable stepping into the callback.
4855 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrepareStepInIfStepping) {
4856  Debug* debug = isolate->debug();
4857  if (!debug->IsStepping()) return NULL;
4858  CONVERT_ARG_CHECKED(Object, callback, 0);
4859  HandleScope scope(isolate);
4860  Handle<SharedFunctionInfo> shared_info(JSFunction::cast(callback)->shared());
4861  // When leaving the callback, step out has been activated, but not performed
4862  // if we do not leave the builtin. To be able to step into the callback
4863  // again, we need to clear the step out at this point.
4864  debug->ClearStepOut();
4865  debug->FloodWithOneShot(shared_info);
4866  return NULL;
4867 }
4868 
4869 
4870 // Set a local property, even if it is READ_ONLY. If the property does not
4871 // exist, it will be added with attributes NONE.
4872 RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) {
4873  NoHandleAllocation ha;
4874  RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
4875  CONVERT_ARG_CHECKED(JSObject, object, 0);
4876  CONVERT_ARG_CHECKED(String, name, 1);
4877  // Compute attributes.
4878  PropertyAttributes attributes = NONE;
4879  if (args.length() == 4) {
4880  CONVERT_SMI_ARG_CHECKED(unchecked_value, 3);
4881  // Only attribute bits should be set.
4883  (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4884  attributes = static_cast<PropertyAttributes>(unchecked_value);
4885  }
4886 
4887  return object->
4888  SetLocalPropertyIgnoreAttributes(name, args[2], attributes);
4889 }
4890 
4891 
4892 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteProperty) {
4893  NoHandleAllocation ha;
4894  ASSERT(args.length() == 3);
4895 
4896  CONVERT_ARG_CHECKED(JSReceiver, object, 0);
4897  CONVERT_ARG_CHECKED(String, key, 1);
4898  CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2);
4899  return object->DeleteProperty(key, (strict_mode == kStrictMode)
4902 }
4903 
4904 
4905 static Object* HasLocalPropertyImplementation(Isolate* isolate,
4906  Handle<JSObject> object,
4907  Handle<String> key) {
4908  if (object->HasLocalProperty(*key)) return isolate->heap()->true_value();
4909  // Handle hidden prototypes. If there's a hidden prototype above this thing
4910  // then we have to check it for properties, because they are supposed to
4911  // look like they are on this object.
4912  Handle<Object> proto(object->GetPrototype());
4913  if (proto->IsJSObject() &&
4914  Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) {
4915  return HasLocalPropertyImplementation(isolate,
4916  Handle<JSObject>::cast(proto),
4917  key);
4918  }
4919  return isolate->heap()->false_value();
4920 }
4921 
4922 
4923 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) {
4924  NoHandleAllocation ha;
4925  ASSERT(args.length() == 2);
4926  CONVERT_ARG_CHECKED(String, key, 1);
4927 
4928  uint32_t index;
4929  const bool key_is_array_index = key->AsArrayIndex(&index);
4930 
4931  Object* obj = args[0];
4932  // Only JS objects can have properties.
4933  if (obj->IsJSObject()) {
4934  JSObject* object = JSObject::cast(obj);
4935  // Fast case: either the key is a real named property or it is not
4936  // an array index and there are no interceptors or hidden
4937  // prototypes.
4938  if (object->HasRealNamedProperty(key)) return isolate->heap()->true_value();
4939  Map* map = object->map();
4940  if (!key_is_array_index &&
4941  !map->has_named_interceptor() &&
4942  !HeapObject::cast(map->prototype())->map()->is_hidden_prototype()) {
4943  return isolate->heap()->false_value();
4944  }
4945  // Slow case.
4946  HandleScope scope(isolate);
4947  return HasLocalPropertyImplementation(isolate,
4948  Handle<JSObject>(object),
4949  Handle<String>(key));
4950  } else if (obj->IsString() && key_is_array_index) {
4951  // Well, there is one exception: Handle [] on strings.
4952  String* string = String::cast(obj);
4953  if (index < static_cast<uint32_t>(string->length())) {
4954  return isolate->heap()->true_value();
4955  }
4956  }
4957  return isolate->heap()->false_value();
4958 }
4959 
4960 
4961 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) {
4962  NoHandleAllocation na;
4963  ASSERT(args.length() == 2);
4964  CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
4965  CONVERT_ARG_CHECKED(String, key, 1);
4966 
4967  bool result = receiver->HasProperty(key);
4968  if (isolate->has_pending_exception()) return Failure::Exception();
4969  return isolate->heap()->ToBoolean(result);
4970 }
4971 
4972 
4973 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasElement) {
4974  NoHandleAllocation na;
4975  ASSERT(args.length() == 2);
4976  CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
4977  CONVERT_SMI_ARG_CHECKED(index, 1);
4978 
4979  bool result = receiver->HasElement(index);
4980  if (isolate->has_pending_exception()) return Failure::Exception();
4981  return isolate->heap()->ToBoolean(result);
4982 }
4983 
4984 
4985 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) {
4986  NoHandleAllocation ha;
4987  ASSERT(args.length() == 2);
4988 
4989  CONVERT_ARG_CHECKED(JSObject, object, 0);
4990  CONVERT_ARG_CHECKED(String, key, 1);
4991 
4992  uint32_t index;
4993  if (key->AsArrayIndex(&index)) {
4994  JSObject::LocalElementType type = object->HasLocalElement(index);
4995  switch (type) {
4998  return isolate->heap()->false_value();
5001  return isolate->heap()->true_value();
5003  if (object->IsJSGlobalProxy()) {
5004  Object* proto = object->GetPrototype();
5005  if (proto->IsNull()) {
5006  return isolate->heap()->false_value();
5007  }
5008  ASSERT(proto->IsJSGlobalObject());
5009  object = JSObject::cast(proto);
5010  }
5011  FixedArray* elements = FixedArray::cast(object->elements());
5012  SeededNumberDictionary* dictionary = NULL;
5013  if (elements->map() ==
5014  isolate->heap()->non_strict_arguments_elements_map()) {
5015  dictionary = SeededNumberDictionary::cast(elements->get(1));
5016  } else {
5017  dictionary = SeededNumberDictionary::cast(elements);
5018  }
5019  int entry = dictionary->FindEntry(index);
5021  PropertyDetails details = dictionary->DetailsAt(entry);
5022  return isolate->heap()->ToBoolean(!details.IsDontEnum());
5023  }
5024  }
5025  }
5026 
5027  PropertyAttributes att = object->GetLocalPropertyAttribute(key);
5028  return isolate->heap()->ToBoolean(att != ABSENT && (att & DONT_ENUM) == 0);
5029 }
5030 
5031 
5032 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNames) {
5033  HandleScope scope(isolate);
5034  ASSERT(args.length() == 1);
5036  bool threw = false;
5037  Handle<JSArray> result = GetKeysFor(object, &threw);
5038  if (threw) return Failure::Exception();
5039  return *result;
5040 }
5041 
5042 
5043 // Returns either a FixedArray as Runtime_GetPropertyNames,
5044 // or, if the given object has an enum cache that contains
5045 // all enumerable properties of the object and its prototypes
5046 // have none, the map of the object. This is used to speed up
5047 // the check for deletions during a for-in.
5048 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNamesFast) {
5049  ASSERT(args.length() == 1);
5050 
5051  CONVERT_ARG_CHECKED(JSReceiver, raw_object, 0);
5052 
5053  if (raw_object->IsSimpleEnum()) return raw_object->map();
5054 
5055  HandleScope scope(isolate);
5056  Handle<JSReceiver> object(raw_object);
5057  bool threw = false;
5058  Handle<FixedArray> content =
5059  GetKeysInFixedArrayFor(object, INCLUDE_PROTOS, &threw);
5060  if (threw) return Failure::Exception();
5061 
5062  // Test again, since cache may have been built by preceding call.
5063  if (object->IsSimpleEnum()) return object->map();
5064 
5065  return *content;
5066 }
5067 
5068 
5069 // Find the length of the prototype chain that is to to handled as one. If a
5070 // prototype object is hidden it is to be viewed as part of the the object it
5071 // is prototype for.
5072 static int LocalPrototypeChainLength(JSObject* obj) {
5073  int count = 1;
5074  Object* proto = obj->GetPrototype();
5075  while (proto->IsJSObject() &&
5076  JSObject::cast(proto)->map()->is_hidden_prototype()) {
5077  count++;
5078  proto = JSObject::cast(proto)->GetPrototype();
5079  }
5080  return count;
5081 }
5082 
5083 
5084 // Return the names of the local named properties.
5085 // args[0]: object
5086 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) {
5087  HandleScope scope(isolate);
5088  ASSERT(args.length() == 1);
5089  if (!args[0]->IsJSObject()) {
5090  return isolate->heap()->undefined_value();
5091  }
5093 
5094  // Skip the global proxy as it has no properties and always delegates to the
5095  // real global object.
5096  if (obj->IsJSGlobalProxy()) {
5097  // Only collect names if access is permitted.
5098  if (obj->IsAccessCheckNeeded() &&
5099  !isolate->MayNamedAccess(*obj,
5100  isolate->heap()->undefined_value(),
5101  v8::ACCESS_KEYS)) {
5102  isolate->ReportFailedAccessCheck(*obj, v8::ACCESS_KEYS);
5103  return *isolate->factory()->NewJSArray(0);
5104  }
5105  obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
5106  }
5107 
5108  // Find the number of objects making up this.
5109  int length = LocalPrototypeChainLength(*obj);
5110 
5111  // Find the number of local properties for each of the objects.
5112  ScopedVector<int> local_property_count(length);
5113  int total_property_count = 0;
5114  Handle<JSObject> jsproto = obj;
5115  for (int i = 0; i < length; i++) {
5116  // Only collect names if access is permitted.
5117  if (jsproto->IsAccessCheckNeeded() &&
5118  !isolate->MayNamedAccess(*jsproto,
5119  isolate->heap()->undefined_value(),
5120  v8::ACCESS_KEYS)) {
5121  isolate->ReportFailedAccessCheck(*jsproto, v8::ACCESS_KEYS);
5122  return *isolate->factory()->NewJSArray(0);
5123  }
5124  int n;
5125  n = jsproto->NumberOfLocalProperties();
5126  local_property_count[i] = n;
5127  total_property_count += n;
5128  if (i < length - 1) {
5129  jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
5130  }
5131  }
5132 
5133  // Allocate an array with storage for all the property names.
5134  Handle<FixedArray> names =
5135  isolate->factory()->NewFixedArray(total_property_count);
5136 
5137  // Get the property names.
5138  jsproto = obj;
5139  int proto_with_hidden_properties = 0;
5140  int next_copy_index = 0;
5141  for (int i = 0; i < length; i++) {
5142  jsproto->GetLocalPropertyNames(*names, next_copy_index);
5143  next_copy_index += local_property_count[i];
5144  if (jsproto->HasHiddenProperties()) {
5145  proto_with_hidden_properties++;
5146  }
5147  if (i < length - 1) {
5148  jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
5149  }
5150  }
5151 
5152  // Filter out name of hidden propeties object.
5153  if (proto_with_hidden_properties > 0) {
5154  Handle<FixedArray> old_names = names;
5155  names = isolate->factory()->NewFixedArray(
5156  names->length() - proto_with_hidden_properties);
5157  int dest_pos = 0;
5158  for (int i = 0; i < total_property_count; i++) {
5159  Object* name = old_names->get(i);
5160  if (name == isolate->heap()->hidden_symbol()) {
5161  continue;
5162  }
5163  names->set(dest_pos++, name);
5164  }
5165  }
5166 
5167  return *isolate->factory()->NewJSArrayWithElements(names);
5168 }
5169 
5170 
5171 // Return the names of the local indexed properties.
5172 // args[0]: object
5173 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalElementNames) {
5174  HandleScope scope(isolate);
5175  ASSERT(args.length() == 1);
5176  if (!args[0]->IsJSObject()) {
5177  return isolate->heap()->undefined_value();
5178  }
5180 
5181  int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
5182  Handle<FixedArray> names = isolate->factory()->NewFixedArray(n);
5183  obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
5184  return *isolate->factory()->NewJSArrayWithElements(names);
5185 }
5186 
5187 
5188 // Return information on whether an object has a named or indexed interceptor.
5189 // args[0]: object
5190 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetInterceptorInfo) {
5191  HandleScope scope(isolate);
5192  ASSERT(args.length() == 1);
5193  if (!args[0]->IsJSObject()) {
5194  return Smi::FromInt(0);
5195  }
5197 
5198  int result = 0;
5199  if (obj->HasNamedInterceptor()) result |= 2;
5200  if (obj->HasIndexedInterceptor()) result |= 1;
5201 
5202  return Smi::FromInt(result);
5203 }
5204 
5205 
5206 // Return property names from named interceptor.
5207 // args[0]: object
5208 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetNamedInterceptorPropertyNames) {
5209  HandleScope scope(isolate);
5210  ASSERT(args.length() == 1);
5212 
5213  if (obj->HasNamedInterceptor()) {
5215  if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
5216  }
5217  return isolate->heap()->undefined_value();
5218 }
5219 
5220 
5221 // Return element names from indexed interceptor.
5222 // args[0]: object
5223 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetIndexedInterceptorElementNames) {
5224  HandleScope scope(isolate);
5225  ASSERT(args.length() == 1);
5227 
5228  if (obj->HasIndexedInterceptor()) {
5230  if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
5231  }
5232  return isolate->heap()->undefined_value();
5233 }
5234 
5235 
5236 RUNTIME_FUNCTION(MaybeObject*, Runtime_LocalKeys) {
5237  ASSERT_EQ(args.length(), 1);
5238  CONVERT_ARG_CHECKED(JSObject, raw_object, 0);
5239  HandleScope scope(isolate);
5240  Handle<JSObject> object(raw_object);
5241 
5242  if (object->IsJSGlobalProxy()) {
5243  // Do access checks before going to the global object.
5244  if (object->IsAccessCheckNeeded() &&
5245  !isolate->MayNamedAccess(*object, isolate->heap()->undefined_value(),
5246  v8::ACCESS_KEYS)) {
5247  isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
5248  return *isolate->factory()->NewJSArray(0);
5249  }
5250 
5251  Handle<Object> proto(object->GetPrototype());
5252  // If proxy is detached we simply return an empty array.
5253  if (proto->IsNull()) return *isolate->factory()->NewJSArray(0);
5254  object = Handle<JSObject>::cast(proto);
5255  }
5256 
5257  bool threw = false;
5258  Handle<FixedArray> contents =
5259  GetKeysInFixedArrayFor(object, LOCAL_ONLY, &threw);
5260  if (threw) return Failure::Exception();
5261 
5262  // Some fast paths through GetKeysInFixedArrayFor reuse a cached
5263  // property array and since the result is mutable we have to create
5264  // a fresh clone on each invocation.
5265  int length = contents->length();
5266  Handle<FixedArray> copy = isolate->factory()->NewFixedArray(length);
5267  for (int i = 0; i < length; i++) {
5268  Object* entry = contents->get(i);
5269  if (entry->IsString()) {
5270  copy->set(i, entry);
5271  } else {
5272  ASSERT(entry->IsNumber());
5273  HandleScope scope(isolate);
5274  Handle<Object> entry_handle(entry, isolate);
5275  Handle<Object> entry_str =
5276  isolate->factory()->NumberToString(entry_handle);
5277  copy->set(i, *entry_str);
5278  }
5279  }
5280  return *isolate->factory()->NewJSArrayWithElements(copy);
5281 }
5282 
5283 
5284 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
5285  NoHandleAllocation ha;
5286  ASSERT(args.length() == 1);
5287 
5288  // Compute the frame holding the arguments.
5289  JavaScriptFrameIterator it(isolate);
5290  it.AdvanceToArgumentsFrame();
5291  JavaScriptFrame* frame = it.frame();
5292 
5293  // Get the actual number of provided arguments.
5294  const uint32_t n = frame->ComputeParametersCount();
5295 
5296  // Try to convert the key to an index. If successful and within
5297  // index return the the argument from the frame.
5298  uint32_t index;
5299  if (args[0]->ToArrayIndex(&index) && index < n) {
5300  return frame->GetParameter(index);
5301  }
5302 
5303  // Convert the key to a string.
5304  HandleScope scope(isolate);
5305  bool exception = false;
5306  Handle<Object> converted =
5307  Execution::ToString(args.at<Object>(0), &exception);
5308  if (exception) return Failure::Exception();
5309  Handle<String> key = Handle<String>::cast(converted);
5310 
5311  // Try to convert the string key into an array index.
5312  if (key->AsArrayIndex(&index)) {
5313  if (index < n) {
5314  return frame->GetParameter(index);
5315  } else {
5316  return isolate->initial_object_prototype()->GetElement(index);
5317  }
5318  }
5319 
5320  // Handle special arguments properties.
5321  if (key->Equals(isolate->heap()->length_symbol())) return Smi::FromInt(n);
5322  if (key->Equals(isolate->heap()->callee_symbol())) {
5323  Object* function = frame->function();
5324  if (function->IsJSFunction() &&
5325  !JSFunction::cast(function)->shared()->is_classic_mode()) {
5326  return isolate->Throw(*isolate->factory()->NewTypeError(
5327  "strict_arguments_callee", HandleVector<Object>(NULL, 0)));
5328  }
5329  return function;
5330  }
5331 
5332  // Lookup in the initial Object.prototype object.
5333  return isolate->initial_object_prototype()->GetProperty(*key);
5334 }
5335 
5336 
5337 RUNTIME_FUNCTION(MaybeObject*, Runtime_ToFastProperties) {
5338  ASSERT(args.length() == 1);
5339  Object* object = args[0];
5340  return (object->IsJSObject() && !object->IsGlobalObject())
5342  : object;
5343 }
5344 
5345 
5346 RUNTIME_FUNCTION(MaybeObject*, Runtime_ToSlowProperties) {
5347  ASSERT(args.length() == 1);
5348  Object* obj = args[0];
5349  return (obj->IsJSObject() && !obj->IsJSGlobalProxy())
5351  : obj;
5352 }
5353 
5354 
5355 RUNTIME_FUNCTION(MaybeObject*, Runtime_ToBool) {
5356  NoHandleAllocation ha;
5357  ASSERT(args.length() == 1);
5358 
5359  return args[0]->ToBoolean();
5360 }
5361 
5362 
5363 // Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
5364 // Possible optimizations: put the type string into the oddballs.
5365 RUNTIME_FUNCTION(MaybeObject*, Runtime_Typeof) {
5366  NoHandleAllocation ha;
5367 
5368  Object* obj = args[0];
5369  if (obj->IsNumber()) return isolate->heap()->number_symbol();
5370  HeapObject* heap_obj = HeapObject::cast(obj);
5371 
5372  // typeof an undetectable object is 'undefined'
5373  if (heap_obj->map()->is_undetectable()) {
5374  return isolate->heap()->undefined_symbol();
5375  }
5376 
5377  InstanceType instance_type = heap_obj->map()->instance_type();
5378  if (instance_type < FIRST_NONSTRING_TYPE) {
5379  return isolate->heap()->string_symbol();
5380  }
5381 
5382  switch (instance_type) {
5383  case ODDBALL_TYPE:
5384  if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
5385  return isolate->heap()->boolean_symbol();
5386  }
5387  if (heap_obj->IsNull()) {
5388  return FLAG_harmony_typeof
5389  ? isolate->heap()->null_symbol()
5390  : isolate->heap()->object_symbol();
5391  }
5392  ASSERT(heap_obj->IsUndefined());
5393  return isolate->heap()->undefined_symbol();
5394  case JS_FUNCTION_TYPE:
5396  return isolate->heap()->function_symbol();
5397  default:
5398  // For any kind of object not handled above, the spec rule for
5399  // host objects gives that it is okay to return "object"
5400  return isolate->heap()->object_symbol();
5401  }
5402 }
5403 
5404 
5405 static bool AreDigits(const char*s, int from, int to) {
5406  for (int i = from; i < to; i++) {
5407  if (s[i] < '0' || s[i] > '9') return false;
5408  }
5409 
5410  return true;
5411 }
5412 
5413 
5414 static int ParseDecimalInteger(const char*s, int from, int to) {
5415  ASSERT(to - from < 10); // Overflow is not possible.
5416  ASSERT(from < to);
5417  int d = s[from] - '0';
5418 
5419  for (int i = from + 1; i < to; i++) {
5420  d = 10 * d + (s[i] - '0');
5421  }
5422 
5423  return d;
5424 }
5425 
5426 
5427 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
5428  NoHandleAllocation ha;
5429  ASSERT(args.length() == 1);
5430  CONVERT_ARG_CHECKED(String, subject, 0);
5431  subject->TryFlatten();
5432 
5433  // Fast case: short integer or some sorts of junk values.
5434  int len = subject->length();
5435  if (subject->IsSeqAsciiString()) {
5436  if (len == 0) return Smi::FromInt(0);
5437 
5438  char const* data = SeqAsciiString::cast(subject)->GetChars();
5439  bool minus = (data[0] == '-');
5440  int start_pos = (minus ? 1 : 0);
5441 
5442  if (start_pos == len) {
5443  return isolate->heap()->nan_value();
5444  } else if (data[start_pos] > '9') {
5445  // Fast check for a junk value. A valid string may start from a
5446  // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit or
5447  // the 'I' character ('Infinity'). All of that have codes not greater than
5448  // '9' except 'I'.
5449  if (data[start_pos] != 'I') {
5450  return isolate->heap()->nan_value();
5451  }
5452  } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
5453  // The maximal/minimal smi has 10 digits. If the string has less digits we
5454  // know it will fit into the smi-data type.
5455  int d = ParseDecimalInteger(data, start_pos, len);
5456  if (minus) {
5457  if (d == 0) return isolate->heap()->minus_zero_value();
5458  d = -d;
5459  } else if (!subject->HasHashCode() &&
5460  len <= String::kMaxArrayIndexSize &&
5461  (len == 1 || data[0] != '0')) {
5462  // String hash is not calculated yet but all the data are present.
5463  // Update the hash field to speed up sequential convertions.
5464  uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
5465 #ifdef DEBUG
5466  subject->Hash(); // Force hash calculation.
5467  ASSERT_EQ(static_cast<int>(subject->hash_field()),
5468  static_cast<int>(hash));
5469 #endif
5470  subject->set_hash_field(hash);
5471  }
5472  return Smi::FromInt(d);
5473  }
5474  }
5475 
5476  // Slower case.
5477  return isolate->heap()->NumberFromDouble(
5478  StringToDouble(isolate->unicode_cache(), subject, ALLOW_HEX));
5479 }
5480 
5481 
5482 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringFromCharCodeArray) {
5483  NoHandleAllocation ha;
5484  ASSERT(args.length() == 1);
5485 
5486  CONVERT_ARG_CHECKED(JSArray, codes, 0);
5487  int length = Smi::cast(codes->length())->value();
5488 
5489  // Check if the string can be ASCII.
5490  int i;
5491  for (i = 0; i < length; i++) {
5492  Object* element;
5493  { MaybeObject* maybe_element = codes->GetElement(i);
5494  // We probably can't get an exception here, but just in order to enforce
5495  // the checking of inputs in the runtime calls we check here.
5496  if (!maybe_element->ToObject(&element)) return maybe_element;
5497  }
5498  CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
5499  if ((chr & 0xffff) > String::kMaxAsciiCharCode)
5500  break;
5501  }
5502 
5503  MaybeObject* maybe_object = NULL;
5504  if (i == length) { // The string is ASCII.
5505  maybe_object = isolate->heap()->AllocateRawAsciiString(length);
5506  } else { // The string is not ASCII.
5507  maybe_object = isolate->heap()->AllocateRawTwoByteString(length);
5508  }
5509 
5510  Object* object = NULL;
5511  if (!maybe_object->ToObject(&object)) return maybe_object;
5512  String* result = String::cast(object);
5513  for (int i = 0; i < length; i++) {
5514  Object* element;
5515  { MaybeObject* maybe_element = codes->GetElement(i);
5516  if (!maybe_element->ToObject(&element)) return maybe_element;
5517  }
5518  CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
5519  result->Set(i, chr & 0xffff);
5520  }
5521  return result;
5522 }
5523 
5524 
5525 // kNotEscaped is generated by the following:
5526 //
5527 // #!/bin/perl
5528 // for (my $i = 0; $i < 256; $i++) {
5529 // print "\n" if $i % 16 == 0;
5530 // my $c = chr($i);
5531 // my $escaped = 1;
5532 // $escaped = 0 if $c =~ m#[A-Za-z0-9@*_+./-]#;
5533 // print $escaped ? "0, " : "1, ";
5534 // }
5535 
5536 
5537 static bool IsNotEscaped(uint16_t character) {
5538  // Only for 8 bit characters, the rest are always escaped (in a different way)
5539  ASSERT(character < 256);
5540  static const char kNotEscaped[256] = {
5541  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5542  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5543  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
5544  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
5545  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5546  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
5547  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5548  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
5549  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5550  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5551  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5552  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5553  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5554  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5555  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5556  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
5557  };
5558  return kNotEscaped[character] != 0;
5559 }
5560 
5561 
5562 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIEscape) {
5563  const char hex_chars[] = "0123456789ABCDEF";
5564  NoHandleAllocation ha;
5565  ASSERT(args.length() == 1);
5566  CONVERT_ARG_CHECKED(String, source, 0);
5567 
5568  source->TryFlatten();
5569 
5570  int escaped_length = 0;
5571  int length = source->length();
5572  {
5574  isolate->runtime_state()->string_input_buffer());
5575  buffer->Reset(source);
5576  while (buffer->has_more()) {
5577  uint16_t character = buffer->GetNext();
5578  if (character >= 256) {
5579  escaped_length += 6;
5580  } else if (IsNotEscaped(character)) {
5581  escaped_length++;
5582  } else {
5583  escaped_length += 3;
5584  }
5585  // We don't allow strings that are longer than a maximal length.
5586  ASSERT(String::kMaxLength < 0x7fffffff - 6); // Cannot overflow.
5587  if (escaped_length > String::kMaxLength) {
5588  isolate->context()->mark_out_of_memory();
5590  }
5591  }
5592  }
5593  // No length change implies no change. Return original string if no change.
5594  if (escaped_length == length) {
5595  return source;
5596  }
5597  Object* o;
5598  { MaybeObject* maybe_o =
5599  isolate->heap()->AllocateRawAsciiString(escaped_length);
5600  if (!maybe_o->ToObject(&o)) return maybe_o;
5601  }
5602  String* destination = String::cast(o);
5603  int dest_position = 0;
5604 
5606  isolate->runtime_state()->string_input_buffer());
5607  buffer->Rewind();
5608  while (buffer->has_more()) {
5609  uint16_t chr = buffer->GetNext();
5610  if (chr >= 256) {
5611  destination->Set(dest_position, '%');
5612  destination->Set(dest_position+1, 'u');
5613  destination->Set(dest_position+2, hex_chars[chr >> 12]);
5614  destination->Set(dest_position+3, hex_chars[(chr >> 8) & 0xf]);
5615  destination->Set(dest_position+4, hex_chars[(chr >> 4) & 0xf]);
5616  destination->Set(dest_position+5, hex_chars[chr & 0xf]);
5617  dest_position += 6;
5618  } else if (IsNotEscaped(chr)) {
5619  destination->Set(dest_position, chr);
5620  dest_position++;
5621  } else {
5622  destination->Set(dest_position, '%');
5623  destination->Set(dest_position+1, hex_chars[chr >> 4]);
5624  destination->Set(dest_position+2, hex_chars[chr & 0xf]);
5625  dest_position += 3;
5626  }
5627  }
5628  return destination;
5629 }
5630 
5631 
5632 static inline int TwoDigitHex(uint16_t character1, uint16_t character2) {
5633  static const signed char kHexValue['g'] = {
5634  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5635  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5636  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5637  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
5638  -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5639  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
5640  -1, 10, 11, 12, 13, 14, 15 };
5641 
5642  if (character1 > 'f') return -1;
5643  int hi = kHexValue[character1];
5644  if (hi == -1) return -1;
5645  if (character2 > 'f') return -1;
5646  int lo = kHexValue[character2];
5647  if (lo == -1) return -1;
5648  return (hi << 4) + lo;
5649 }
5650 
5651 
5652 static inline int Unescape(String* source,
5653  int i,
5654  int length,
5655  int* step) {
5656  uint16_t character = source->Get(i);
5657  int32_t hi = 0;
5658  int32_t lo = 0;
5659  if (character == '%' &&
5660  i <= length - 6 &&
5661  source->Get(i + 1) == 'u' &&
5662  (hi = TwoDigitHex(source->Get(i + 2),
5663  source->Get(i + 3))) != -1 &&
5664  (lo = TwoDigitHex(source->Get(i + 4),
5665  source->Get(i + 5))) != -1) {
5666  *step = 6;
5667  return (hi << 8) + lo;
5668  } else if (character == '%' &&
5669  i <= length - 3 &&
5670  (lo = TwoDigitHex(source->Get(i + 1),
5671  source->Get(i + 2))) != -1) {
5672  *step = 3;
5673  return lo;
5674  } else {
5675  *step = 1;
5676  return character;
5677  }
5678 }
5679 
5680 
5681 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) {
5682  NoHandleAllocation ha;
5683  ASSERT(args.length() == 1);
5684  CONVERT_ARG_CHECKED(String, source, 0);
5685 
5686  source->TryFlatten();
5687 
5688  bool ascii = true;
5689  int length = source->length();
5690 
5691  int unescaped_length = 0;
5692  for (int i = 0; i < length; unescaped_length++) {
5693  int step;
5694  if (Unescape(source, i, length, &step) > String::kMaxAsciiCharCode) {
5695  ascii = false;
5696  }
5697  i += step;
5698  }
5699 
5700  // No length change implies no change. Return original string if no change.
5701  if (unescaped_length == length)
5702  return source;
5703 
5704  Object* o;
5705  { MaybeObject* maybe_o =
5706  ascii ?
5707  isolate->heap()->AllocateRawAsciiString(unescaped_length) :
5708  isolate->heap()->AllocateRawTwoByteString(unescaped_length);
5709  if (!maybe_o->ToObject(&o)) return maybe_o;
5710  }
5711  String* destination = String::cast(o);
5712 
5713  int dest_position = 0;
5714  for (int i = 0; i < length; dest_position++) {
5715  int step;
5716  destination->Set(dest_position, Unescape(source, i, length, &step));
5717  i += step;
5718  }
5719  return destination;
5720 }
5721 
5722 
5723 static const unsigned int kQuoteTableLength = 128u;
5724 
5725 static const int kJsonQuotesCharactersPerEntry = 8;
5726 static const char* const JsonQuotes =
5727  "\\u0000 \\u0001 \\u0002 \\u0003 "
5728  "\\u0004 \\u0005 \\u0006 \\u0007 "
5729  "\\b \\t \\n \\u000b "
5730  "\\f \\r \\u000e \\u000f "
5731  "\\u0010 \\u0011 \\u0012 \\u0013 "
5732  "\\u0014 \\u0015 \\u0016 \\u0017 "
5733  "\\u0018 \\u0019 \\u001a \\u001b "
5734  "\\u001c \\u001d \\u001e \\u001f "
5735  " ! \\\" # "
5736  "$ % & ' "
5737  "( ) * + "
5738  ", - . / "
5739  "0 1 2 3 "
5740  "4 5 6 7 "
5741  "8 9 : ; "
5742  "< = > ? "
5743  "@ A B C "
5744  "D E F G "
5745  "H I J K "
5746  "L M N O "
5747  "P Q R S "
5748  "T U V W "
5749  "X Y Z [ "
5750  "\\\\ ] ^ _ "
5751  "` a b c "
5752  "d e f g "
5753  "h i j k "
5754  "l m n o "
5755  "p q r s "
5756  "t u v w "
5757  "x y z { "
5758  "| } ~ \177 ";
5759 
5760 
5761 // For a string that is less than 32k characters it should always be
5762 // possible to allocate it in new space.
5763 static const int kMaxGuaranteedNewSpaceString = 32 * 1024;
5764 
5765 
5766 // Doing JSON quoting cannot make the string more than this many times larger.
5767 static const int kJsonQuoteWorstCaseBlowup = 6;
5768 
5769 static const int kSpaceForQuotesAndComma = 3;
5770 static const int kSpaceForBrackets = 2;
5771 
5772 // Covers the entire ASCII range (all other characters are unchanged by JSON
5773 // quoting).
5774 static const byte JsonQuoteLengths[kQuoteTableLength] = {
5775  6, 6, 6, 6, 6, 6, 6, 6,
5776  2, 2, 2, 6, 2, 2, 6, 6,
5777  6, 6, 6, 6, 6, 6, 6, 6,
5778  6, 6, 6, 6, 6, 6, 6, 6,
5779  1, 1, 2, 1, 1, 1, 1, 1,
5780  1, 1, 1, 1, 1, 1, 1, 1,
5781  1, 1, 1, 1, 1, 1, 1, 1,
5782  1, 1, 1, 1, 1, 1, 1, 1,
5783  1, 1, 1, 1, 1, 1, 1, 1,
5784  1, 1, 1, 1, 1, 1, 1, 1,
5785  1, 1, 1, 1, 1, 1, 1, 1,
5786  1, 1, 1, 1, 2, 1, 1, 1,
5787  1, 1, 1, 1, 1, 1, 1, 1,
5788  1, 1, 1, 1, 1, 1, 1, 1,
5789  1, 1, 1, 1, 1, 1, 1, 1,
5790  1, 1, 1, 1, 1, 1, 1, 1,
5791 };
5792 
5793 
5794 template <typename StringType>
5795 MaybeObject* AllocateRawString(Isolate* isolate, int length);
5796 
5797 
5798 template <>
5799 MaybeObject* AllocateRawString<SeqTwoByteString>(Isolate* isolate, int length) {
5800  return isolate->heap()->AllocateRawTwoByteString(length);
5801 }
5802 
5803 
5804 template <>
5805 MaybeObject* AllocateRawString<SeqAsciiString>(Isolate* isolate, int length) {
5806  return isolate->heap()->AllocateRawAsciiString(length);
5807 }
5808 
5809 
5810 template <typename Char, typename StringType, bool comma>
5811 static MaybeObject* SlowQuoteJsonString(Isolate* isolate,
5812  Vector<const Char> characters) {
5813  int length = characters.length();
5814  const Char* read_cursor = characters.start();
5815  const Char* end = read_cursor + length;
5816  const int kSpaceForQuotes = 2 + (comma ? 1 :0);
5817  int quoted_length = kSpaceForQuotes;
5818  while (read_cursor < end) {
5819  Char c = *(read_cursor++);
5820  if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) {
5821  quoted_length++;
5822  } else {
5823  quoted_length += JsonQuoteLengths[static_cast<unsigned>(c)];
5824  }
5825  }
5826  MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
5827  quoted_length);
5828  Object* new_object;
5829  if (!new_alloc->ToObject(&new_object)) {
5830  return new_alloc;
5831  }
5832  StringType* new_string = StringType::cast(new_object);
5833 
5834  Char* write_cursor = reinterpret_cast<Char*>(
5835  new_string->address() + SeqString::kHeaderSize);
5836  if (comma) *(write_cursor++) = ',';
5837  *(write_cursor++) = '"';
5838 
5839  read_cursor = characters.start();
5840  while (read_cursor < end) {
5841  Char c = *(read_cursor++);
5842  if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) {
5843  *(write_cursor++) = c;
5844  } else {
5845  int len = JsonQuoteLengths[static_cast<unsigned>(c)];
5846  const char* replacement = JsonQuotes +
5847  static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry;
5848  for (int i = 0; i < len; i++) {
5849  *write_cursor++ = *replacement++;
5850  }
5851  }
5852  }
5853  *(write_cursor++) = '"';
5854  return new_string;
5855 }
5856 
5857 
5858 template <typename SinkChar, typename SourceChar>
5859 static inline SinkChar* WriteQuoteJsonString(
5860  Isolate* isolate,
5861  SinkChar* write_cursor,
5862  Vector<const SourceChar> characters) {
5863  // SinkChar is only char if SourceChar is guaranteed to be char.
5864  ASSERT(sizeof(SinkChar) >= sizeof(SourceChar));
5865  const SourceChar* read_cursor = characters.start();
5866  const SourceChar* end = read_cursor + characters.length();
5867  *(write_cursor++) = '"';
5868  while (read_cursor < end) {
5869  SourceChar c = *(read_cursor++);
5870  if (sizeof(SourceChar) > 1u &&
5871  static_cast<unsigned>(c) >= kQuoteTableLength) {
5872  *(write_cursor++) = static_cast<SinkChar>(c);
5873  } else {
5874  int len = JsonQuoteLengths[static_cast<unsigned>(c)];
5875  const char* replacement = JsonQuotes +
5876  static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry;
5877  write_cursor[0] = replacement[0];
5878  if (len > 1) {
5879  write_cursor[1] = replacement[1];
5880  if (len > 2) {
5881  ASSERT(len == 6);
5882  write_cursor[2] = replacement[2];
5883  write_cursor[3] = replacement[3];
5884  write_cursor[4] = replacement[4];
5885  write_cursor[5] = replacement[5];
5886  }
5887  }
5888  write_cursor += len;
5889  }
5890  }
5891  *(write_cursor++) = '"';
5892  return write_cursor;
5893 }
5894 
5895 
5896 template <typename Char, typename StringType, bool comma>
5897 static MaybeObject* QuoteJsonString(Isolate* isolate,
5898  Vector<const Char> characters) {
5899  int length = characters.length();
5900  isolate->counters()->quote_json_char_count()->Increment(length);
5901  int worst_case_length =
5902  length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotesAndComma;
5903  if (worst_case_length > kMaxGuaranteedNewSpaceString) {
5904  return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters);
5905  }
5906 
5907  MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
5908  worst_case_length);
5909  Object* new_object;
5910  if (!new_alloc->ToObject(&new_object)) {
5911  return new_alloc;
5912  }
5913  if (!isolate->heap()->new_space()->Contains(new_object)) {
5914  // Even if our string is small enough to fit in new space we still have to
5915  // handle it being allocated in old space as may happen in the third
5916  // attempt. See CALL_AND_RETRY in heap-inl.h and similar code in
5917  // CEntryStub::GenerateCore.
5918  return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters);
5919  }
5920  StringType* new_string = StringType::cast(new_object);
5921  ASSERT(isolate->heap()->new_space()->Contains(new_string));
5922 
5923  Char* write_cursor = reinterpret_cast<Char*>(
5924  new_string->address() + SeqString::kHeaderSize);
5925  if (comma) *(write_cursor++) = ',';
5926  write_cursor = WriteQuoteJsonString<Char, Char>(isolate,
5927  write_cursor,
5928  characters);
5929  int final_length = static_cast<int>(
5930  write_cursor - reinterpret_cast<Char*>(
5931  new_string->address() + SeqString::kHeaderSize));
5932  isolate->heap()->new_space()->
5933  template ShrinkStringAtAllocationBoundary<StringType>(
5934  new_string, final_length);
5935  return new_string;
5936 }
5937 
5938 
5939 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONString) {
5940  NoHandleAllocation ha;
5941  CONVERT_ARG_CHECKED(String, str, 0);
5942  if (!str->IsFlat()) {
5943  MaybeObject* try_flatten = str->TryFlatten();
5944  Object* flat;
5945  if (!try_flatten->ToObject(&flat)) {
5946  return try_flatten;
5947  }
5948  str = String::cast(flat);
5949  ASSERT(str->IsFlat());
5950  }
5951  String::FlatContent flat = str->GetFlatContent();
5952  ASSERT(flat.IsFlat());
5953  if (flat.IsTwoByte()) {
5954  return QuoteJsonString<uc16, SeqTwoByteString, false>(isolate,
5955  flat.ToUC16Vector());
5956  } else {
5957  return QuoteJsonString<char, SeqAsciiString, false>(isolate,
5958  flat.ToAsciiVector());
5959  }
5960 }
5961 
5962 
5963 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringComma) {
5964  NoHandleAllocation ha;
5965  CONVERT_ARG_CHECKED(String, str, 0);
5966  if (!str->IsFlat()) {
5967  MaybeObject* try_flatten = str->TryFlatten();
5968  Object* flat;
5969  if (!try_flatten->ToObject(&flat)) {
5970  return try_flatten;
5971  }
5972  str = String::cast(flat);
5973  ASSERT(str->IsFlat());
5974  }
5975  String::FlatContent flat = str->GetFlatContent();
5976  if (flat.IsTwoByte()) {
5977  return QuoteJsonString<uc16, SeqTwoByteString, true>(isolate,
5978  flat.ToUC16Vector());
5979  } else {
5980  return QuoteJsonString<char, SeqAsciiString, true>(isolate,
5981  flat.ToAsciiVector());
5982  }
5983 }
5984 
5985 
5986 template <typename Char, typename StringType>
5987 static MaybeObject* QuoteJsonStringArray(Isolate* isolate,
5988  FixedArray* array,
5989  int worst_case_length) {
5990  int length = array->length();
5991 
5992  MaybeObject* new_alloc = AllocateRawString<StringType>(isolate,
5993  worst_case_length);
5994  Object* new_object;
5995  if (!new_alloc->ToObject(&new_object)) {
5996  return new_alloc;
5997  }
5998  if (!isolate->heap()->new_space()->Contains(new_object)) {
5999  // Even if our string is small enough to fit in new space we still have to
6000  // handle it being allocated in old space as may happen in the third
6001  // attempt. See CALL_AND_RETRY in heap-inl.h and similar code in
6002  // CEntryStub::GenerateCore.
6003  return isolate->heap()->undefined_value();
6004  }
6005  AssertNoAllocation no_gc;
6006  StringType* new_string = StringType::cast(new_object);
6007  ASSERT(isolate->heap()->new_space()->Contains(new_string));
6008 
6009  Char* write_cursor = reinterpret_cast<Char*>(
6010  new_string->address() + SeqString::kHeaderSize);
6011  *(write_cursor++) = '[';
6012  for (int i = 0; i < length; i++) {
6013  if (i != 0) *(write_cursor++) = ',';
6014  String* str = String::cast(array->get(i));
6015  String::FlatContent content = str->GetFlatContent();
6016  ASSERT(content.IsFlat());
6017  if (content.IsTwoByte()) {
6018  write_cursor = WriteQuoteJsonString<Char, uc16>(isolate,
6019  write_cursor,
6020  content.ToUC16Vector());
6021  } else {
6022  write_cursor = WriteQuoteJsonString<Char, char>(isolate,
6023  write_cursor,
6024  content.ToAsciiVector());
6025  }
6026  }
6027  *(write_cursor++) = ']';
6028 
6029  int final_length = static_cast<int>(
6030  write_cursor - reinterpret_cast<Char*>(
6031  new_string->address() + SeqString::kHeaderSize));
6032  isolate->heap()->new_space()->
6033  template ShrinkStringAtAllocationBoundary<StringType>(
6034  new_string, final_length);
6035  return new_string;
6036 }
6037 
6038 
6039 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringArray) {
6040  NoHandleAllocation ha;
6041  ASSERT(args.length() == 1);
6042  CONVERT_ARG_CHECKED(JSArray, array, 0);
6043 
6044  if (!array->HasFastObjectElements()) {
6045  return isolate->heap()->undefined_value();
6046  }
6047  FixedArray* elements = FixedArray::cast(array->elements());
6048  int n = elements->length();
6049  bool ascii = true;
6050  int total_length = 0;
6051 
6052  for (int i = 0; i < n; i++) {
6053  Object* elt = elements->get(i);
6054  if (!elt->IsString()) return isolate->heap()->undefined_value();
6055  String* element = String::cast(elt);
6056  if (!element->IsFlat()) return isolate->heap()->undefined_value();
6057  total_length += element->length();
6058  if (ascii && element->IsTwoByteRepresentation()) {
6059  ascii = false;
6060  }
6061  }
6062 
6063  int worst_case_length =
6064  kSpaceForBrackets + n * kSpaceForQuotesAndComma
6065  + total_length * kJsonQuoteWorstCaseBlowup;
6066 
6067  if (worst_case_length > kMaxGuaranteedNewSpaceString) {
6068  return isolate->heap()->undefined_value();
6069  }
6070 
6071  if (ascii) {
6072  return QuoteJsonStringArray<char, SeqAsciiString>(isolate,
6073  elements,
6074  worst_case_length);
6075  } else {
6076  return QuoteJsonStringArray<uc16, SeqTwoByteString>(isolate,
6077  elements,
6078  worst_case_length);
6079  }
6080 }
6081 
6082 
6083 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) {
6084  NoHandleAllocation ha;
6085 
6086  CONVERT_ARG_CHECKED(String, s, 0);
6087  CONVERT_SMI_ARG_CHECKED(radix, 1);
6088 
6089  s->TryFlatten();
6090 
6091  RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
6092  double value = StringToInt(isolate->unicode_cache(), s, radix);
6093  return isolate->heap()->NumberFromDouble(value);
6094 }
6095 
6096 
6097 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) {
6098  NoHandleAllocation ha;
6099  CONVERT_ARG_CHECKED(String, str, 0);
6100 
6101  // ECMA-262 section 15.1.2.3, empty string is NaN
6102  double value = StringToDouble(isolate->unicode_cache(),
6104 
6105  // Create a number object from the value.
6106  return isolate->heap()->NumberFromDouble(value);
6107 }
6108 
6109 
6110 template <class Converter>
6111 MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
6112  Isolate* isolate,
6113  String* s,
6114  int length,
6115  int input_string_length,
6117  // We try this twice, once with the assumption that the result is no longer
6118  // than the input and, if that assumption breaks, again with the exact
6119  // length. This may not be pretty, but it is nicer than what was here before
6120  // and I hereby claim my vaffel-is.
6121  //
6122  // Allocate the resulting string.
6123  //
6124  // NOTE: This assumes that the upper/lower case of an ASCII
6125  // character is also ASCII. This is currently the case, but it
6126  // might break in the future if we implement more context and locale
6127  // dependent upper/lower conversions.
6128  Object* o;
6129  { MaybeObject* maybe_o = s->IsAsciiRepresentation()
6130  ? isolate->heap()->AllocateRawAsciiString(length)
6131  : isolate->heap()->AllocateRawTwoByteString(length);
6132  if (!maybe_o->ToObject(&o)) return maybe_o;
6133  }
6134  String* result = String::cast(o);
6135  bool has_changed_character = false;
6136 
6137  // Convert all characters to upper case, assuming that they will fit
6138  // in the buffer
6139  Access<StringInputBuffer> buffer(
6140  isolate->runtime_state()->string_input_buffer());
6141  buffer->Reset(s);
6142  unibrow::uchar chars[Converter::kMaxWidth];
6143  // We can assume that the string is not empty
6144  uc32 current = buffer->GetNext();
6145  for (int i = 0; i < length;) {
6146  bool has_next = buffer->has_more();
6147  uc32 next = has_next ? buffer->GetNext() : 0;
6148  int char_length = mapping->get(current, next, chars);
6149  if (char_length == 0) {
6150  // The case conversion of this character is the character itself.
6151  result->Set(i, current);
6152  i++;
6153  } else if (char_length == 1) {
6154  // Common case: converting the letter resulted in one character.
6155  ASSERT(static_cast<uc32>(chars[0]) != current);
6156  result->Set(i, chars[0]);
6157  has_changed_character = true;
6158  i++;
6159  } else if (length == input_string_length) {
6160  // We've assumed that the result would be as long as the
6161  // input but here is a character that converts to several
6162  // characters. No matter, we calculate the exact length
6163  // of the result and try the whole thing again.
6164  //
6165  // Note that this leaves room for optimization. We could just
6166  // memcpy what we already have to the result string. Also,
6167  // the result string is the last object allocated we could
6168  // "realloc" it and probably, in the vast majority of cases,
6169  // extend the existing string to be able to hold the full
6170  // result.
6171  int next_length = 0;
6172  if (has_next) {
6173  next_length = mapping->get(next, 0, chars);
6174  if (next_length == 0) next_length = 1;
6175  }
6176  int current_length = i + char_length + next_length;
6177  while (buffer->has_more()) {
6178  current = buffer->GetNext();
6179  // NOTE: we use 0 as the next character here because, while
6180  // the next character may affect what a character converts to,
6181  // it does not in any case affect the length of what it convert
6182  // to.
6183  int char_length = mapping->get(current, 0, chars);
6184  if (char_length == 0) char_length = 1;
6185  current_length += char_length;
6186  if (current_length > Smi::kMaxValue) {
6187  isolate->context()->mark_out_of_memory();
6189  }
6190  }
6191  // Try again with the real length.
6192  return Smi::FromInt(current_length);
6193  } else {
6194  for (int j = 0; j < char_length; j++) {
6195  result->Set(i, chars[j]);
6196  i++;
6197  }
6198  has_changed_character = true;
6199  }
6200  current = next;
6201  }
6202  if (has_changed_character) {
6203  return result;
6204  } else {
6205  // If we didn't actually change anything in doing the conversion
6206  // we simple return the result and let the converted string
6207  // become garbage; there is no reason to keep two identical strings
6208  // alive.
6209  return s;
6210  }
6211 }
6212 
6213 
6214 namespace {
6215 
6216 static const uintptr_t kOneInEveryByte = kUintptrAllBitsSet / 0xFF;
6217 
6218 
6219 // Given a word and two range boundaries returns a word with high bit
6220 // set in every byte iff the corresponding input byte was strictly in
6221 // the range (m, n). All the other bits in the result are cleared.
6222 // This function is only useful when it can be inlined and the
6223 // boundaries are statically known.
6224 // Requires: all bytes in the input word and the boundaries must be
6225 // ASCII (less than 0x7F).
6226 static inline uintptr_t AsciiRangeMask(uintptr_t w, char m, char n) {
6227  // Every byte in an ASCII string is less than or equal to 0x7F.
6228  ASSERT((w & (kOneInEveryByte * 0x7F)) == w);
6229  // Use strict inequalities since in edge cases the function could be
6230  // further simplified.
6231  ASSERT(0 < m && m < n && n < 0x7F);
6232  // Has high bit set in every w byte less than n.
6233  uintptr_t tmp1 = kOneInEveryByte * (0x7F + n) - w;
6234  // Has high bit set in every w byte greater than m.
6235  uintptr_t tmp2 = w + kOneInEveryByte * (0x7F - m);
6236  return (tmp1 & tmp2 & (kOneInEveryByte * 0x80));
6237 }
6238 
6239 
6240 enum AsciiCaseConversion {
6241  ASCII_TO_LOWER,
6242  ASCII_TO_UPPER
6243 };
6244 
6245 
6246 template <AsciiCaseConversion dir>
6247 struct FastAsciiConverter {
6248  static bool Convert(char* dst, char* src, int length) {
6249 #ifdef DEBUG
6250  char* saved_dst = dst;
6251  char* saved_src = src;
6252 #endif
6253  // We rely on the distance between upper and lower case letters
6254  // being a known power of 2.
6255  ASSERT('a' - 'A' == (1 << 5));
6256  // Boundaries for the range of input characters than require conversion.
6257  const char lo = (dir == ASCII_TO_LOWER) ? 'A' - 1 : 'a' - 1;
6258  const char hi = (dir == ASCII_TO_LOWER) ? 'Z' + 1 : 'z' + 1;
6259  bool changed = false;
6260  char* const limit = src + length;
6261 #ifdef V8_HOST_CAN_READ_UNALIGNED
6262  // Process the prefix of the input that requires no conversion one
6263  // (machine) word at a time.
6264  while (src <= limit - sizeof(uintptr_t)) {
6265  uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
6266  if (AsciiRangeMask(w, lo, hi) != 0) {
6267  changed = true;
6268  break;
6269  }
6270  *reinterpret_cast<uintptr_t*>(dst) = w;
6271  src += sizeof(uintptr_t);
6272  dst += sizeof(uintptr_t);
6273  }
6274  // Process the remainder of the input performing conversion when
6275  // required one word at a time.
6276  while (src <= limit - sizeof(uintptr_t)) {
6277  uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
6278  uintptr_t m = AsciiRangeMask(w, lo, hi);
6279  // The mask has high (7th) bit set in every byte that needs
6280  // conversion and we know that the distance between cases is
6281  // 1 << 5.
6282  *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2);
6283  src += sizeof(uintptr_t);
6284  dst += sizeof(uintptr_t);
6285  }
6286 #endif
6287  // Process the last few bytes of the input (or the whole input if
6288  // unaligned access is not supported).
6289  while (src < limit) {
6290  char c = *src;
6291  if (lo < c && c < hi) {
6292  c ^= (1 << 5);
6293  changed = true;
6294  }
6295  *dst = c;
6296  ++src;
6297  ++dst;
6298  }
6299 #ifdef DEBUG
6300  CheckConvert(saved_dst, saved_src, length, changed);
6301 #endif
6302  return changed;
6303  }
6304 
6305 #ifdef DEBUG
6306  static void CheckConvert(char* dst, char* src, int length, bool changed) {
6307  bool expected_changed = false;
6308  for (int i = 0; i < length; i++) {
6309  if (dst[i] == src[i]) continue;
6310  expected_changed = true;
6311  if (dir == ASCII_TO_LOWER) {
6312  ASSERT('A' <= src[i] && src[i] <= 'Z');
6313  ASSERT(dst[i] == src[i] + ('a' - 'A'));
6314  } else {
6315  ASSERT(dir == ASCII_TO_UPPER);
6316  ASSERT('a' <= src[i] && src[i] <= 'z');
6317  ASSERT(dst[i] == src[i] - ('a' - 'A'));
6318  }
6319  }
6320  ASSERT(expected_changed == changed);
6321  }
6322 #endif
6323 };
6324 
6325 
6326 struct ToLowerTraits {
6327  typedef unibrow::ToLowercase UnibrowConverter;
6328 
6329  typedef FastAsciiConverter<ASCII_TO_LOWER> AsciiConverter;
6330 };
6331 
6332 
6333 struct ToUpperTraits {
6334  typedef unibrow::ToUppercase UnibrowConverter;
6335 
6336  typedef FastAsciiConverter<ASCII_TO_UPPER> AsciiConverter;
6337 };
6338 
6339 } // namespace
6340 
6341 
6342 template <typename ConvertTraits>
6343 MUST_USE_RESULT static MaybeObject* ConvertCase(
6344  Arguments args,
6345  Isolate* isolate,
6347  NoHandleAllocation ha;
6348  CONVERT_ARG_CHECKED(String, s, 0);
6349  s = s->TryFlattenGetString();
6350 
6351  const int length = s->length();
6352  // Assume that the string is not empty; we need this assumption later
6353  if (length == 0) return s;
6354 
6355  // Simpler handling of ASCII strings.
6356  //
6357  // NOTE: This assumes that the upper/lower case of an ASCII
6358  // character is also ASCII. This is currently the case, but it
6359  // might break in the future if we implement more context and locale
6360  // dependent upper/lower conversions.
6361  if (s->IsSeqAsciiString()) {
6362  Object* o;
6363  { MaybeObject* maybe_o = isolate->heap()->AllocateRawAsciiString(length);
6364  if (!maybe_o->ToObject(&o)) return maybe_o;
6365  }
6366  SeqAsciiString* result = SeqAsciiString::cast(o);
6367  bool has_changed_character = ConvertTraits::AsciiConverter::Convert(
6368  result->GetChars(), SeqAsciiString::cast(s)->GetChars(), length);
6369  return has_changed_character ? result : s;
6370  }
6371 
6372  Object* answer;
6373  { MaybeObject* maybe_answer =
6374  ConvertCaseHelper(isolate, s, length, length, mapping);
6375  if (!maybe_answer->ToObject(&answer)) return maybe_answer;
6376  }
6377  if (answer->IsSmi()) {
6378  // Retry with correct length.
6379  { MaybeObject* maybe_answer =
6380  ConvertCaseHelper(isolate,
6381  s, Smi::cast(answer)->value(), length, mapping);
6382  if (!maybe_answer->ToObject(&answer)) return maybe_answer;
6383  }
6384  }
6385  return answer;
6386 }
6387 
6388 
6389 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) {
6390  return ConvertCase<ToLowerTraits>(
6391  args, isolate, isolate->runtime_state()->to_lower_mapping());
6392 }
6393 
6394 
6395 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToUpperCase) {
6396  return ConvertCase<ToUpperTraits>(
6397  args, isolate, isolate->runtime_state()->to_upper_mapping());
6398 }
6399 
6400 
6401 static inline bool IsTrimWhiteSpace(unibrow::uchar c) {
6402  return unibrow::WhiteSpace::Is(c) || c == 0x200b || c == 0xfeff;
6403 }
6404 
6405 
6406 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringTrim) {
6407  NoHandleAllocation ha;
6408  ASSERT(args.length() == 3);
6409 
6410  CONVERT_ARG_CHECKED(String, s, 0);
6411  CONVERT_BOOLEAN_ARG_CHECKED(trimLeft, 1);
6412  CONVERT_BOOLEAN_ARG_CHECKED(trimRight, 2);
6413 
6414  s->TryFlatten();
6415  int length = s->length();
6416 
6417  int left = 0;
6418  if (trimLeft) {
6419  while (left < length && IsTrimWhiteSpace(s->Get(left))) {
6420  left++;
6421  }
6422  }
6423 
6424  int right = length;
6425  if (trimRight) {
6426  while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) {
6427  right--;
6428  }
6429  }
6430  return s->SubString(left, right);
6431 }
6432 
6433 
6434 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
6435  ASSERT(args.length() == 3);
6436  HandleScope handle_scope(isolate);
6437  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
6438  CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
6439  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]);
6440 
6441  int subject_length = subject->length();
6442  int pattern_length = pattern->length();
6443  RUNTIME_ASSERT(pattern_length > 0);
6444 
6445  if (limit == 0xffffffffu) {
6447  isolate->heap()->string_split_cache(),
6448  *subject,
6449  *pattern));
6450  if (*cached_answer != Smi::FromInt(0)) {
6451  Handle<JSArray> result =
6452  isolate->factory()->NewJSArrayWithElements(
6453  Handle<FixedArray>::cast(cached_answer));
6454  return *result;
6455  }
6456  }
6457 
6458  // The limit can be very large (0xffffffffu), but since the pattern
6459  // isn't empty, we can never create more parts than ~half the length
6460  // of the subject.
6461 
6462  if (!subject->IsFlat()) FlattenString(subject);
6463 
6464  static const int kMaxInitialListCapacity = 16;
6465 
6466  Zone* zone = isolate->zone();
6467  ZoneScope scope(isolate, DELETE_ON_EXIT);
6468 
6469  // Find (up to limit) indices of separator and end-of-string in subject
6470  int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit);
6471  ZoneList<int> indices(initial_capacity, zone);
6472  if (!pattern->IsFlat()) FlattenString(pattern);
6473 
6474  FindStringIndicesDispatch(isolate, *subject, *pattern, &indices, limit, zone);
6475 
6476  if (static_cast<uint32_t>(indices.length()) < limit) {
6477  indices.Add(subject_length, zone);
6478  }
6479 
6480  // The list indices now contains the end of each part to create.
6481 
6482  // Create JSArray of substrings separated by separator.
6483  int part_count = indices.length();
6484 
6485  Handle<JSArray> result = isolate->factory()->NewJSArray(part_count);
6486  MaybeObject* maybe_result = result->EnsureCanContainHeapObjectElements();
6487  if (maybe_result->IsFailure()) return maybe_result;
6488  result->set_length(Smi::FromInt(part_count));
6489 
6490  ASSERT(result->HasFastObjectElements());
6491 
6492  if (part_count == 1 && indices.at(0) == subject_length) {
6493  FixedArray::cast(result->elements())->set(0, *subject);
6494  return *result;
6495  }
6496 
6497  Handle<FixedArray> elements(FixedArray::cast(result->elements()));
6498  int part_start = 0;
6499  for (int i = 0; i < part_count; i++) {
6500  HandleScope local_loop_handle;
6501  int part_end = indices.at(i);
6502  Handle<String> substring =
6503  isolate->factory()->NewProperSubString(subject, part_start, part_end);
6504  elements->set(i, *substring);
6505  part_start = part_end + pattern_length;
6506  }
6507 
6508  if (limit == 0xffffffffu) {
6509  if (result->HasFastObjectElements()) {
6510  StringSplitCache::Enter(isolate->heap(),
6511  isolate->heap()->string_split_cache(),
6512  *subject,
6513  *pattern,
6514  *elements);
6515  }
6516  }
6517 
6518  return *result;
6519 }
6520 
6521 
6522 // Copies ASCII characters to the given fixed array looking up
6523 // one-char strings in the cache. Gives up on the first char that is
6524 // not in the cache and fills the remainder with smi zeros. Returns
6525 // the length of the successfully copied prefix.
6526 static int CopyCachedAsciiCharsToArray(Heap* heap,
6527  const char* chars,
6528  FixedArray* elements,
6529  int length) {
6530  AssertNoAllocation no_gc;
6531  FixedArray* ascii_cache = heap->single_character_string_cache();
6532  Object* undefined = heap->undefined_value();
6533  int i;
6534  WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
6535  for (i = 0; i < length; ++i) {
6536  Object* value = ascii_cache->get(chars[i]);
6537  if (value == undefined) break;
6538  elements->set(i, value, mode);
6539  }
6540  if (i < length) {
6541  ASSERT(Smi::FromInt(0) == 0);
6542  memset(elements->data_start() + i, 0, kPointerSize * (length - i));
6543  }
6544 #ifdef DEBUG
6545  for (int j = 0; j < length; ++j) {
6546  Object* element = elements->get(j);
6547  ASSERT(element == Smi::FromInt(0) ||
6548  (element->IsString() && String::cast(element)->LooksValid()));
6549  }
6550 #endif
6551  return i;
6552 }
6553 
6554 
6555 // Converts a String to JSArray.
6556 // For example, "foo" => ["f", "o", "o"].
6557 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToArray) {
6558  HandleScope scope(isolate);
6559  ASSERT(args.length() == 2);
6561  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
6562 
6563  s = FlattenGetString(s);
6564  const int length = static_cast<int>(Min<uint32_t>(s->length(), limit));
6565 
6566  Handle<FixedArray> elements;
6567  int position = 0;
6568  if (s->IsFlat() && s->IsAsciiRepresentation()) {
6569  // Try using cached chars where possible.
6570  Object* obj;
6571  { MaybeObject* maybe_obj =
6572  isolate->heap()->AllocateUninitializedFixedArray(length);
6573  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
6574  }
6575  elements = Handle<FixedArray>(FixedArray::cast(obj), isolate);
6576  String::FlatContent content = s->GetFlatContent();
6577  if (content.IsAscii()) {
6578  Vector<const char> chars = content.ToAsciiVector();
6579  // Note, this will initialize all elements (not only the prefix)
6580  // to prevent GC from seeing partially initialized array.
6581  position = CopyCachedAsciiCharsToArray(isolate->heap(),
6582  chars.start(),
6583  *elements,
6584  length);
6585  } else {
6586  MemsetPointer(elements->data_start(),
6587  isolate->heap()->undefined_value(),
6588  length);
6589  }
6590  } else {
6591  elements = isolate->factory()->NewFixedArray(length);
6592  }
6593  for (int i = position; i < length; ++i) {
6595  elements->set(i, *str);
6596  }
6597 
6598 #ifdef DEBUG
6599  for (int i = 0; i < length; ++i) {
6600  ASSERT(String::cast(elements->get(i))->length() == 1);
6601  }
6602 #endif
6603 
6604  return *isolate->factory()->NewJSArrayWithElements(elements);
6605 }
6606 
6607 
6608 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStringWrapper) {
6609  NoHandleAllocation ha;
6610  ASSERT(args.length() == 1);
6611  CONVERT_ARG_CHECKED(String, value, 0);
6612  return value->ToObject();
6613 }
6614 
6615 
6618  int char_length = runtime_state->to_upper_mapping()->get(ch, 0, chars);
6619  return char_length == 0;
6620 }
6621 
6622 
6623 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToString) {
6624  NoHandleAllocation ha;
6625  ASSERT(args.length() == 1);
6626 
6627  Object* number = args[0];
6628  RUNTIME_ASSERT(number->IsNumber());
6629 
6630  return isolate->heap()->NumberToString(number);
6631 }
6632 
6633 
6634 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToStringSkipCache) {
6635  NoHandleAllocation ha;
6636  ASSERT(args.length() == 1);
6637 
6638  Object* number = args[0];
6639  RUNTIME_ASSERT(number->IsNumber());
6640 
6641  return isolate->heap()->NumberToString(number, false);
6642 }
6643 
6644 
6645 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToInteger) {
6646  NoHandleAllocation ha;
6647  ASSERT(args.length() == 1);
6648 
6649  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6650 
6651  // We do not include 0 so that we don't have to treat +0 / -0 cases.
6652  if (number > 0 && number <= Smi::kMaxValue) {
6653  return Smi::FromInt(static_cast<int>(number));
6654  }
6655  return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
6656 }
6657 
6658 
6659 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToIntegerMapMinusZero) {
6660  NoHandleAllocation ha;
6661  ASSERT(args.length() == 1);
6662 
6663  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6664 
6665  // We do not include 0 so that we don't have to treat +0 / -0 cases.
6666  if (number > 0 && number <= Smi::kMaxValue) {
6667  return Smi::FromInt(static_cast<int>(number));
6668  }
6669 
6670  double double_value = DoubleToInteger(number);
6671  // Map both -0 and +0 to +0.
6672  if (double_value == 0) double_value = 0;
6673 
6674  return isolate->heap()->NumberFromDouble(double_value);
6675 }
6676 
6677 
6678 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSUint32) {
6679  NoHandleAllocation ha;
6680  ASSERT(args.length() == 1);
6681 
6682  CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]);
6683  return isolate->heap()->NumberFromUint32(number);
6684 }
6685 
6686 
6687 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSInt32) {
6688  NoHandleAllocation ha;
6689  ASSERT(args.length() == 1);
6690 
6691  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6692 
6693  // We do not include 0 so that we don't have to treat +0 / -0 cases.
6694  if (number > 0 && number <= Smi::kMaxValue) {
6695  return Smi::FromInt(static_cast<int>(number));
6696  }
6697  return isolate->heap()->NumberFromInt32(DoubleToInt32(number));
6698 }
6699 
6700 
6701 // Converts a Number to a Smi, if possible. Returns NaN if the number is not
6702 // a small integer.
6703 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToSmi) {
6704  NoHandleAllocation ha;
6705  ASSERT(args.length() == 1);
6706 
6707  Object* obj = args[0];
6708  if (obj->IsSmi()) {
6709  return obj;
6710  }
6711  if (obj->IsHeapNumber()) {
6712  double value = HeapNumber::cast(obj)->value();
6713  int int_value = FastD2I(value);
6714  if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
6715  return Smi::FromInt(int_value);
6716  }
6717  }
6718  return isolate->heap()->nan_value();
6719 }
6720 
6721 
6722 RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateHeapNumber) {
6723  NoHandleAllocation ha;
6724  ASSERT(args.length() == 0);
6725  return isolate->heap()->AllocateHeapNumber(0);
6726 }
6727 
6728 
6729 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAdd) {
6730  NoHandleAllocation ha;
6731  ASSERT(args.length() == 2);
6732 
6735  return isolate->heap()->NumberFromDouble(x + y);
6736 }
6737 
6738 
6739 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSub) {
6740  NoHandleAllocation ha;
6741  ASSERT(args.length() == 2);
6742 
6745  return isolate->heap()->NumberFromDouble(x - y);
6746 }
6747 
6748 
6749 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMul) {
6750  NoHandleAllocation ha;
6751  ASSERT(args.length() == 2);
6752 
6755  return isolate->heap()->NumberFromDouble(x * y);
6756 }
6757 
6758 
6759 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberUnaryMinus) {
6760  NoHandleAllocation ha;
6761  ASSERT(args.length() == 1);
6762 
6764  return isolate->heap()->NumberFromDouble(-x);
6765 }
6766 
6767 
6768 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAlloc) {
6769  NoHandleAllocation ha;
6770  ASSERT(args.length() == 0);
6771 
6772  return isolate->heap()->NumberFromDouble(9876543210.0);
6773 }
6774 
6775 
6776 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberDiv) {
6777  NoHandleAllocation ha;
6778  ASSERT(args.length() == 2);
6779 
6782  return isolate->heap()->NumberFromDouble(x / y);
6783 }
6784 
6785 
6786 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMod) {
6787  NoHandleAllocation ha;
6788  ASSERT(args.length() == 2);
6789 
6792 
6793  x = modulo(x, y);
6794  // NumberFromDouble may return a Smi instead of a Number object
6795  return isolate->heap()->NumberFromDouble(x);
6796 }
6797 
6798 
6799 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringAdd) {
6800  NoHandleAllocation ha;
6801  ASSERT(args.length() == 2);
6802  CONVERT_ARG_CHECKED(String, str1, 0);
6803  CONVERT_ARG_CHECKED(String, str2, 1);
6804  isolate->counters()->string_add_runtime()->Increment();
6805  return isolate->heap()->AllocateConsString(str1, str2);
6806 }
6807 
6808 
6809 template <typename sinkchar>
6810 static inline void StringBuilderConcatHelper(String* special,
6811  sinkchar* sink,
6812  FixedArray* fixed_array,
6813  int array_length) {
6814  int position = 0;
6815  for (int i = 0; i < array_length; i++) {
6816  Object* element = fixed_array->get(i);
6817  if (element->IsSmi()) {
6818  // Smi encoding of position and length.
6819  int encoded_slice = Smi::cast(element)->value();
6820  int pos;
6821  int len;
6822  if (encoded_slice > 0) {
6823  // Position and length encoded in one smi.
6824  pos = StringBuilderSubstringPosition::decode(encoded_slice);
6825  len = StringBuilderSubstringLength::decode(encoded_slice);
6826  } else {
6827  // Position and length encoded in two smis.
6828  Object* obj = fixed_array->get(++i);
6829  ASSERT(obj->IsSmi());
6830  pos = Smi::cast(obj)->value();
6831  len = -encoded_slice;
6832  }
6833  String::WriteToFlat(special,
6834  sink + position,
6835  pos,
6836  pos + len);
6837  position += len;
6838  } else {
6839  String* string = String::cast(element);
6840  int element_length = string->length();
6841  String::WriteToFlat(string, sink + position, 0, element_length);
6842  position += element_length;
6843  }
6844  }
6845 }
6846 
6847 
6848 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
6849  NoHandleAllocation ha;
6850  ASSERT(args.length() == 3);
6851  CONVERT_ARG_CHECKED(JSArray, array, 0);
6852  if (!args[1]->IsSmi()) {
6853  isolate->context()->mark_out_of_memory();
6855  }
6856  int array_length = args.smi_at(1);
6857  CONVERT_ARG_CHECKED(String, special, 2);
6858 
6859  // This assumption is used by the slice encoding in one or two smis.
6861 
6862  MaybeObject* maybe_result = array->EnsureCanContainHeapObjectElements();
6863  if (maybe_result->IsFailure()) return maybe_result;
6864 
6865  int special_length = special->length();
6866  if (!array->HasFastObjectElements()) {
6867  return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6868  }
6869  FixedArray* fixed_array = FixedArray::cast(array->elements());
6870  if (fixed_array->length() < array_length) {
6871  array_length = fixed_array->length();
6872  }
6873 
6874  if (array_length == 0) {
6875  return isolate->heap()->empty_string();
6876  } else if (array_length == 1) {
6877  Object* first = fixed_array->get(0);
6878  if (first->IsString()) return first;
6879  }
6880 
6881  bool ascii = special->HasOnlyAsciiChars();
6882  int position = 0;
6883  for (int i = 0; i < array_length; i++) {
6884  int increment = 0;
6885  Object* elt = fixed_array->get(i);
6886  if (elt->IsSmi()) {
6887  // Smi encoding of position and length.
6888  int smi_value = Smi::cast(elt)->value();
6889  int pos;
6890  int len;
6891  if (smi_value > 0) {
6892  // Position and length encoded in one smi.
6893  pos = StringBuilderSubstringPosition::decode(smi_value);
6894  len = StringBuilderSubstringLength::decode(smi_value);
6895  } else {
6896  // Position and length encoded in two smis.
6897  len = -smi_value;
6898  // Get the position and check that it is a positive smi.
6899  i++;
6900  if (i >= array_length) {
6901  return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6902  }
6903  Object* next_smi = fixed_array->get(i);
6904  if (!next_smi->IsSmi()) {
6905  return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6906  }
6907  pos = Smi::cast(next_smi)->value();
6908  if (pos < 0) {
6909  return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6910  }
6911  }
6912  ASSERT(pos >= 0);
6913  ASSERT(len >= 0);
6914  if (pos > special_length || len > special_length - pos) {
6915  return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6916  }
6917  increment = len;
6918  } else if (elt->IsString()) {
6919  String* element = String::cast(elt);
6920  int element_length = element->length();
6921  increment = element_length;
6922  if (ascii && !element->HasOnlyAsciiChars()) {
6923  ascii = false;
6924  }
6925  } else {
6926  ASSERT(!elt->IsTheHole());
6927  return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6928  }
6929  if (increment > String::kMaxLength - position) {
6930  isolate->context()->mark_out_of_memory();
6932  }
6933  position += increment;
6934  }
6935 
6936  int length = position;
6937  Object* object;
6938 
6939  if (ascii) {
6940  { MaybeObject* maybe_object =
6941  isolate->heap()->AllocateRawAsciiString(length);
6942  if (!maybe_object->ToObject(&object)) return maybe_object;
6943  }
6944  SeqAsciiString* answer = SeqAsciiString::cast(object);
6945  StringBuilderConcatHelper(special,
6946  answer->GetChars(),
6947  fixed_array,
6948  array_length);
6949  return answer;
6950  } else {
6951  { MaybeObject* maybe_object =
6952  isolate->heap()->AllocateRawTwoByteString(length);
6953  if (!maybe_object->ToObject(&object)) return maybe_object;
6954  }
6955  SeqTwoByteString* answer = SeqTwoByteString::cast(object);
6956  StringBuilderConcatHelper(special,
6957  answer->GetChars(),
6958  fixed_array,
6959  array_length);
6960  return answer;
6961  }
6962 }
6963 
6964 
6965 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
6966  NoHandleAllocation ha;
6967  ASSERT(args.length() == 3);
6968  CONVERT_ARG_CHECKED(JSArray, array, 0);
6969  if (!args[1]->IsSmi()) {
6970  isolate->context()->mark_out_of_memory();
6972  }
6973  int array_length = args.smi_at(1);
6974  CONVERT_ARG_CHECKED(String, separator, 2);
6975 
6976  if (!array->HasFastObjectElements()) {
6977  return isolate->Throw(isolate->heap()->illegal_argument_symbol());
6978  }
6979  FixedArray* fixed_array = FixedArray::cast(array->elements());
6980  if (fixed_array->length() < array_length) {
6981  array_length = fixed_array->length();
6982  }
6983 
6984  if (array_length == 0) {
6985  return isolate->heap()->empty_string();
6986  } else if (array_length == 1) {
6987  Object* first = fixed_array->get(0);
6988  if (first->IsString()) return first;
6989  }
6990 
6991  int separator_length = separator->length();
6992  int max_nof_separators =
6993  (String::kMaxLength + separator_length - 1) / separator_length;
6994  if (max_nof_separators < (array_length - 1)) {
6995  isolate->context()->mark_out_of_memory();
6997  }
6998  int length = (array_length - 1) * separator_length;
6999  for (int i = 0; i < array_length; i++) {
7000  Object* element_obj = fixed_array->get(i);
7001  if (!element_obj->IsString()) {
7002  // TODO(1161): handle this case.
7003  return isolate->Throw(isolate->heap()->illegal_argument_symbol());
7004  }
7005  String* element = String::cast(element_obj);
7006  int increment = element->length();
7007  if (increment > String::kMaxLength - length) {
7008  isolate->context()->mark_out_of_memory();
7010  }
7011  length += increment;
7012  }
7013 
7014  Object* object;
7015  { MaybeObject* maybe_object =
7016  isolate->heap()->AllocateRawTwoByteString(length);
7017  if (!maybe_object->ToObject(&object)) return maybe_object;
7018  }
7019  SeqTwoByteString* answer = SeqTwoByteString::cast(object);
7020 
7021  uc16* sink = answer->GetChars();
7022 #ifdef DEBUG
7023  uc16* end = sink + length;
7024 #endif
7025 
7026  String* first = String::cast(fixed_array->get(0));
7027  int first_length = first->length();
7028  String::WriteToFlat(first, sink, 0, first_length);
7029  sink += first_length;
7030 
7031  for (int i = 1; i < array_length; i++) {
7032  ASSERT(sink + separator_length <= end);
7033  String::WriteToFlat(separator, sink, 0, separator_length);
7034  sink += separator_length;
7035 
7036  String* element = String::cast(fixed_array->get(i));
7037  int element_length = element->length();
7038  ASSERT(sink + element_length <= end);
7039  String::WriteToFlat(element, sink, 0, element_length);
7040  sink += element_length;
7041  }
7042  ASSERT(sink == end);
7043 
7044  ASSERT(!answer->HasOnlyAsciiChars()); // Use %_FastAsciiArrayJoin instead.
7045  return answer;
7046 }
7047 
7048 template <typename Char>
7049 static void JoinSparseArrayWithSeparator(FixedArray* elements,
7050  int elements_length,
7051  uint32_t array_length,
7052  String* separator,
7053  Vector<Char> buffer) {
7054  int previous_separator_position = 0;
7055  int separator_length = separator->length();
7056  int cursor = 0;
7057  for (int i = 0; i < elements_length; i += 2) {
7058  int position = NumberToInt32(elements->get(i));
7059  String* string = String::cast(elements->get(i + 1));
7060  int string_length = string->length();
7061  if (string->length() > 0) {
7062  while (previous_separator_position < position) {
7063  String::WriteToFlat<Char>(separator, &buffer[cursor],
7064  0, separator_length);
7065  cursor += separator_length;
7066  previous_separator_position++;
7067  }
7068  String::WriteToFlat<Char>(string, &buffer[cursor],
7069  0, string_length);
7070  cursor += string->length();
7071  }
7072  }
7073  if (separator_length > 0) {
7074  // Array length must be representable as a signed 32-bit number,
7075  // otherwise the total string length would have been too large.
7076  ASSERT(array_length <= 0x7fffffff); // Is int32_t.
7077  int last_array_index = static_cast<int>(array_length - 1);
7078  while (previous_separator_position < last_array_index) {
7079  String::WriteToFlat<Char>(separator, &buffer[cursor],
7080  0, separator_length);
7081  cursor += separator_length;
7082  previous_separator_position++;
7083  }
7084  }
7085  ASSERT(cursor <= buffer.length());
7086 }
7087 
7088 
7089 RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) {
7090  NoHandleAllocation ha;
7091  ASSERT(args.length() == 3);
7092  CONVERT_ARG_CHECKED(JSArray, elements_array, 0);
7093  RUNTIME_ASSERT(elements_array->HasFastSmiOrObjectElements());
7094  CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]);
7095  CONVERT_ARG_CHECKED(String, separator, 2);
7096  // elements_array is fast-mode JSarray of alternating positions
7097  // (increasing order) and strings.
7098  // array_length is length of original array (used to add separators);
7099  // separator is string to put between elements. Assumed to be non-empty.
7100 
7101  // Find total length of join result.
7102  int string_length = 0;
7103  bool is_ascii = separator->IsAsciiRepresentation();
7104  int max_string_length;
7105  if (is_ascii) {
7106  max_string_length = SeqAsciiString::kMaxLength;
7107  } else {
7108  max_string_length = SeqTwoByteString::kMaxLength;
7109  }
7110  bool overflow = false;
7111  CONVERT_NUMBER_CHECKED(int, elements_length,
7112  Int32, elements_array->length());
7113  RUNTIME_ASSERT((elements_length & 1) == 0); // Even length.
7114  FixedArray* elements = FixedArray::cast(elements_array->elements());
7115  for (int i = 0; i < elements_length; i += 2) {
7116  RUNTIME_ASSERT(elements->get(i)->IsNumber());
7117  RUNTIME_ASSERT(elements->get(i + 1)->IsString());
7118  String* string = String::cast(elements->get(i + 1));
7119  int length = string->length();
7120  if (is_ascii && !string->IsAsciiRepresentation()) {
7121  is_ascii = false;
7122  max_string_length = SeqTwoByteString::kMaxLength;
7123  }
7124  if (length > max_string_length ||
7125  max_string_length - length < string_length) {
7126  overflow = true;
7127  break;
7128  }
7129  string_length += length;
7130  }
7131  int separator_length = separator->length();
7132  if (!overflow && separator_length > 0) {
7133  if (array_length <= 0x7fffffffu) {
7134  int separator_count = static_cast<int>(array_length) - 1;
7135  int remaining_length = max_string_length - string_length;
7136  if ((remaining_length / separator_length) >= separator_count) {
7137  string_length += separator_length * (array_length - 1);
7138  } else {
7139  // Not room for the separators within the maximal string length.
7140  overflow = true;
7141  }
7142  } else {
7143  // Nonempty separator and at least 2^31-1 separators necessary
7144  // means that the string is too large to create.
7145  STATIC_ASSERT(String::kMaxLength < 0x7fffffff);
7146  overflow = true;
7147  }
7148  }
7149  if (overflow) {
7150  // Throw OutOfMemory exception for creating too large a string.
7151  V8::FatalProcessOutOfMemory("Array join result too large.");
7152  }
7153 
7154  if (is_ascii) {
7155  MaybeObject* result_allocation =
7156  isolate->heap()->AllocateRawAsciiString(string_length);
7157  if (result_allocation->IsFailure()) return result_allocation;
7158  SeqAsciiString* result_string =
7159  SeqAsciiString::cast(result_allocation->ToObjectUnchecked());
7160  JoinSparseArrayWithSeparator<char>(elements,
7161  elements_length,
7162  array_length,
7163  separator,
7164  Vector<char>(result_string->GetChars(),
7165  string_length));
7166  return result_string;
7167  } else {
7168  MaybeObject* result_allocation =
7169  isolate->heap()->AllocateRawTwoByteString(string_length);
7170  if (result_allocation->IsFailure()) return result_allocation;
7171  SeqTwoByteString* result_string =
7172  SeqTwoByteString::cast(result_allocation->ToObjectUnchecked());
7173  JoinSparseArrayWithSeparator<uc16>(elements,
7174  elements_length,
7175  array_length,
7176  separator,
7177  Vector<uc16>(result_string->GetChars(),
7178  string_length));
7179  return result_string;
7180  }
7181 }
7182 
7183 
7184 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberOr) {
7185  NoHandleAllocation ha;
7186  ASSERT(args.length() == 2);
7187 
7188  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7189  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7190  return isolate->heap()->NumberFromInt32(x | y);
7191 }
7192 
7193 
7194 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAnd) {
7195  NoHandleAllocation ha;
7196  ASSERT(args.length() == 2);
7197 
7198  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7199  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7200  return isolate->heap()->NumberFromInt32(x & y);
7201 }
7202 
7203 
7204 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberXor) {
7205  NoHandleAllocation ha;
7206  ASSERT(args.length() == 2);
7207 
7208  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7209  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7210  return isolate->heap()->NumberFromInt32(x ^ y);
7211 }
7212 
7213 
7214 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberNot) {
7215  NoHandleAllocation ha;
7216  ASSERT(args.length() == 1);
7217 
7218  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7219  return isolate->heap()->NumberFromInt32(~x);
7220 }
7221 
7222 
7223 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShl) {
7224  NoHandleAllocation ha;
7225  ASSERT(args.length() == 2);
7226 
7227  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7228  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7229  return isolate->heap()->NumberFromInt32(x << (y & 0x1f));
7230 }
7231 
7232 
7233 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShr) {
7234  NoHandleAllocation ha;
7235  ASSERT(args.length() == 2);
7236 
7237  CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
7238  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7239  return isolate->heap()->NumberFromUint32(x >> (y & 0x1f));
7240 }
7241 
7242 
7243 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSar) {
7244  NoHandleAllocation ha;
7245  ASSERT(args.length() == 2);
7246 
7247  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7248  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7249  return isolate->heap()->NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f));
7250 }
7251 
7252 
7253 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberEquals) {
7254  NoHandleAllocation ha;
7255  ASSERT(args.length() == 2);
7256 
7259  if (isnan(x)) return Smi::FromInt(NOT_EQUAL);
7260  if (isnan(y)) return Smi::FromInt(NOT_EQUAL);
7261  if (x == y) return Smi::FromInt(EQUAL);
7262  Object* result;
7263  if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
7264  result = Smi::FromInt(EQUAL);
7265  } else {
7266  result = Smi::FromInt(NOT_EQUAL);
7267  }
7268  return result;
7269 }
7270 
7271 
7272 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) {
7273  NoHandleAllocation ha;
7274  ASSERT(args.length() == 2);
7275 
7276  CONVERT_ARG_CHECKED(String, x, 0);
7277  CONVERT_ARG_CHECKED(String, y, 1);
7278 
7279  bool not_equal = !x->Equals(y);
7280  // This is slightly convoluted because the value that signifies
7281  // equality is 0 and inequality is 1 so we have to negate the result
7282  // from String::Equals.
7283  ASSERT(not_equal == 0 || not_equal == 1);
7284  STATIC_CHECK(EQUAL == 0);
7285  STATIC_CHECK(NOT_EQUAL == 1);
7286  return Smi::FromInt(not_equal);
7287 }
7288 
7289 
7290 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberCompare) {
7291  NoHandleAllocation ha;
7292  ASSERT(args.length() == 3);
7293 
7296  if (isnan(x) || isnan(y)) return args[2];
7297  if (x == y) return Smi::FromInt(EQUAL);
7298  if (isless(x, y)) return Smi::FromInt(LESS);
7299  return Smi::FromInt(GREATER);
7300 }
7301 
7302 
7303 // Compare two Smis as if they were converted to strings and then
7304 // compared lexicographically.
7305 RUNTIME_FUNCTION(MaybeObject*, Runtime_SmiLexicographicCompare) {
7306  NoHandleAllocation ha;
7307  ASSERT(args.length() == 2);
7308  CONVERT_SMI_ARG_CHECKED(x_value, 0);
7309  CONVERT_SMI_ARG_CHECKED(y_value, 1);
7310 
7311  // If the integers are equal so are the string representations.
7312  if (x_value == y_value) return Smi::FromInt(EQUAL);
7313 
7314  // If one of the integers is zero the normal integer order is the
7315  // same as the lexicographic order of the string representations.
7316  if (x_value == 0 || y_value == 0)
7317  return Smi::FromInt(x_value < y_value ? LESS : GREATER);
7318 
7319  // If only one of the integers is negative the negative number is
7320  // smallest because the char code of '-' is less than the char code
7321  // of any digit. Otherwise, we make both values positive.
7322 
7323  // Use unsigned values otherwise the logic is incorrect for -MIN_INT on
7324  // architectures using 32-bit Smis.
7325  uint32_t x_scaled = x_value;
7326  uint32_t y_scaled = y_value;
7327  if (x_value < 0 || y_value < 0) {
7328  if (y_value >= 0) return Smi::FromInt(LESS);
7329  if (x_value >= 0) return Smi::FromInt(GREATER);
7330  x_scaled = -x_value;
7331  y_scaled = -y_value;
7332  }
7333 
7334  static const uint32_t kPowersOf10[] = {
7335  1, 10, 100, 1000, 10*1000, 100*1000,
7336  1000*1000, 10*1000*1000, 100*1000*1000,
7337  1000*1000*1000
7338  };
7339 
7340  // If the integers have the same number of decimal digits they can be
7341  // compared directly as the numeric order is the same as the
7342  // lexicographic order. If one integer has fewer digits, it is scaled
7343  // by some power of 10 to have the same number of digits as the longer
7344  // integer. If the scaled integers are equal it means the shorter
7345  // integer comes first in the lexicographic order.
7346 
7347  // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
7348  int x_log2 = IntegerLog2(x_scaled);
7349  int x_log10 = ((x_log2 + 1) * 1233) >> 12;
7350  x_log10 -= x_scaled < kPowersOf10[x_log10];
7351 
7352  int y_log2 = IntegerLog2(y_scaled);
7353  int y_log10 = ((y_log2 + 1) * 1233) >> 12;
7354  y_log10 -= y_scaled < kPowersOf10[y_log10];
7355 
7356  int tie = EQUAL;
7357 
7358  if (x_log10 < y_log10) {
7359  // X has fewer digits. We would like to simply scale up X but that
7360  // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would
7361  // be scaled up to 9_000_000_000. So we scale up by the next
7362  // smallest power and scale down Y to drop one digit. It is OK to
7363  // drop one digit from the longer integer since the final digit is
7364  // past the length of the shorter integer.
7365  x_scaled *= kPowersOf10[y_log10 - x_log10 - 1];
7366  y_scaled /= 10;
7367  tie = LESS;
7368  } else if (y_log10 < x_log10) {
7369  y_scaled *= kPowersOf10[x_log10 - y_log10 - 1];
7370  x_scaled /= 10;
7371  tie = GREATER;
7372  }
7373 
7374  if (x_scaled < y_scaled) return Smi::FromInt(LESS);
7375  if (x_scaled > y_scaled) return Smi::FromInt(GREATER);
7376  return Smi::FromInt(tie);
7377 }
7378 
7379 
7380 static Object* StringInputBufferCompare(RuntimeState* state,
7381  String* x,
7382  String* y) {
7383  StringInputBuffer& bufx = *state->string_input_buffer_compare_bufx();
7384  StringInputBuffer& bufy = *state->string_input_buffer_compare_bufy();
7385  bufx.Reset(x);
7386  bufy.Reset(y);
7387  while (bufx.has_more() && bufy.has_more()) {
7388  int d = bufx.GetNext() - bufy.GetNext();
7389  if (d < 0) return Smi::FromInt(LESS);
7390  else if (d > 0) return Smi::FromInt(GREATER);
7391  }
7392 
7393  // x is (non-trivial) prefix of y:
7394  if (bufy.has_more()) return Smi::FromInt(LESS);
7395  // y is prefix of x:
7396  return Smi::FromInt(bufx.has_more() ? GREATER : EQUAL);
7397 }
7398 
7399 
7400 static Object* FlatStringCompare(String* x, String* y) {
7401  ASSERT(x->IsFlat());
7402  ASSERT(y->IsFlat());
7403  Object* equal_prefix_result = Smi::FromInt(EQUAL);
7404  int prefix_length = x->length();
7405  if (y->length() < prefix_length) {
7406  prefix_length = y->length();
7407  equal_prefix_result = Smi::FromInt(GREATER);
7408  } else if (y->length() > prefix_length) {
7409  equal_prefix_result = Smi::FromInt(LESS);
7410  }
7411  int r;
7412  String::FlatContent x_content = x->GetFlatContent();
7413  String::FlatContent y_content = y->GetFlatContent();
7414  if (x_content.IsAscii()) {
7415  Vector<const char> x_chars = x_content.ToAsciiVector();
7416  if (y_content.IsAscii()) {
7417  Vector<const char> y_chars = y_content.ToAsciiVector();
7418  r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7419  } else {
7420  Vector<const uc16> y_chars = y_content.ToUC16Vector();
7421  r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7422  }
7423  } else {
7424  Vector<const uc16> x_chars = x_content.ToUC16Vector();
7425  if (y_content.IsAscii()) {
7426  Vector<const char> y_chars = y_content.ToAsciiVector();
7427  r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7428  } else {
7429  Vector<const uc16> y_chars = y_content.ToUC16Vector();
7430  r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7431  }
7432  }
7433  Object* result;
7434  if (r == 0) {
7435  result = equal_prefix_result;
7436  } else {
7437  result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
7438  }
7439  ASSERT(result ==
7440  StringInputBufferCompare(Isolate::Current()->runtime_state(), x, y));
7441  return result;
7442 }
7443 
7444 
7445 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCompare) {
7446  NoHandleAllocation ha;
7447  ASSERT(args.length() == 2);
7448 
7449  CONVERT_ARG_CHECKED(String, x, 0);
7450  CONVERT_ARG_CHECKED(String, y, 1);
7451 
7452  isolate->counters()->string_compare_runtime()->Increment();
7453 
7454  // A few fast case tests before we flatten.
7455  if (x == y) return Smi::FromInt(EQUAL);
7456  if (y->length() == 0) {
7457  if (x->length() == 0) return Smi::FromInt(EQUAL);
7458  return Smi::FromInt(GREATER);
7459  } else if (x->length() == 0) {
7460  return Smi::FromInt(LESS);
7461  }
7462 
7463  int d = x->Get(0) - y->Get(0);
7464  if (d < 0) return Smi::FromInt(LESS);
7465  else if (d > 0) return Smi::FromInt(GREATER);
7466 
7467  Object* obj;
7468  { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(x);
7469  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7470  }
7471  { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(y);
7472  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7473  }
7474 
7475  return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
7476  : StringInputBufferCompare(isolate->runtime_state(), x, y);
7477 }
7478 
7479 
7480 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_acos) {
7481  NoHandleAllocation ha;
7482  ASSERT(args.length() == 1);
7483  isolate->counters()->math_acos()->Increment();
7484 
7486  return isolate->transcendental_cache()->Get(TranscendentalCache::ACOS, x);
7487 }
7488 
7489 
7490 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_asin) {
7491  NoHandleAllocation ha;
7492  ASSERT(args.length() == 1);
7493  isolate->counters()->math_asin()->Increment();
7494 
7496  return isolate->transcendental_cache()->Get(TranscendentalCache::ASIN, x);
7497 }
7498 
7499 
7500 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan) {
7501  NoHandleAllocation ha;
7502  ASSERT(args.length() == 1);
7503  isolate->counters()->math_atan()->Increment();
7504 
7506  return isolate->transcendental_cache()->Get(TranscendentalCache::ATAN, x);
7507 }
7508 
7509 
7510 static const double kPiDividedBy4 = 0.78539816339744830962;
7511 
7512 
7513 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan2) {
7514  NoHandleAllocation ha;
7515  ASSERT(args.length() == 2);
7516  isolate->counters()->math_atan2()->Increment();
7517 
7520  double result;
7521  if (isinf(x) && isinf(y)) {
7522  // Make sure that the result in case of two infinite arguments
7523  // is a multiple of Pi / 4. The sign of the result is determined
7524  // by the first argument (x) and the sign of the second argument
7525  // determines the multiplier: one or three.
7526  int multiplier = (x < 0) ? -1 : 1;
7527  if (y < 0) multiplier *= 3;
7528  result = multiplier * kPiDividedBy4;
7529  } else {
7530  result = atan2(x, y);
7531  }
7532  return isolate->heap()->AllocateHeapNumber(result);
7533 }
7534 
7535 
7536 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_ceil) {
7537  NoHandleAllocation ha;
7538  ASSERT(args.length() == 1);
7539  isolate->counters()->math_ceil()->Increment();
7540 
7542  return isolate->heap()->NumberFromDouble(ceiling(x));
7543 }
7544 
7545 
7546 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_cos) {
7547  NoHandleAllocation ha;
7548  ASSERT(args.length() == 1);
7549  isolate->counters()->math_cos()->Increment();
7550 
7552  return isolate->transcendental_cache()->Get(TranscendentalCache::COS, x);
7553 }
7554 
7555 
7556 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_exp) {
7557  NoHandleAllocation ha;
7558  ASSERT(args.length() == 1);
7559  isolate->counters()->math_exp()->Increment();
7560 
7562  return isolate->transcendental_cache()->Get(TranscendentalCache::EXP, x);
7563 }
7564 
7565 
7566 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_floor) {
7567  NoHandleAllocation ha;
7568  ASSERT(args.length() == 1);
7569  isolate->counters()->math_floor()->Increment();
7570 
7572  return isolate->heap()->NumberFromDouble(floor(x));
7573 }
7574 
7575 
7576 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_log) {
7577  NoHandleAllocation ha;
7578  ASSERT(args.length() == 1);
7579  isolate->counters()->math_log()->Increment();
7580 
7582  return isolate->transcendental_cache()->Get(TranscendentalCache::LOG, x);
7583 }
7584 
7585 // Slow version of Math.pow. We check for fast paths for special cases.
7586 // Used if SSE2/VFP3 is not available.
7587 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow) {
7588  NoHandleAllocation ha;
7589  ASSERT(args.length() == 2);
7590  isolate->counters()->math_pow()->Increment();
7591 
7593 
7594  // If the second argument is a smi, it is much faster to call the
7595  // custom powi() function than the generic pow().
7596  if (args[1]->IsSmi()) {
7597  int y = args.smi_at(1);
7598  return isolate->heap()->NumberFromDouble(power_double_int(x, y));
7599  }
7600 
7602  int y_int = static_cast<int>(y);
7603  double result;
7604  if (y == y_int) {
7605  result = power_double_int(x, y_int); // Returns 1 if exponent is 0.
7606  } else if (y == 0.5) {
7607  result = (isinf(x)) ? V8_INFINITY
7608  : fast_sqrt(x + 0.0); // Convert -0 to +0.
7609  } else if (y == -0.5) {
7610  result = (isinf(x)) ? 0
7611  : 1.0 / fast_sqrt(x + 0.0); // Convert -0 to +0.
7612  } else {
7613  result = power_double_double(x, y);
7614  }
7615  if (isnan(result)) return isolate->heap()->nan_value();
7616  return isolate->heap()->AllocateHeapNumber(result);
7617 }
7618 
7619 // Fast version of Math.pow if we know that y is not an integer and y is not
7620 // -0.5 or 0.5. Used as slow case from full codegen.
7621 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow_cfunction) {
7622  NoHandleAllocation ha;
7623  ASSERT(args.length() == 2);
7624  isolate->counters()->math_pow()->Increment();
7625 
7628  if (y == 0) {
7629  return Smi::FromInt(1);
7630  } else {
7631  double result = power_double_double(x, y);
7632  if (isnan(result)) return isolate->heap()->nan_value();
7633  return isolate->heap()->AllocateHeapNumber(result);
7634  }
7635 }
7636 
7637 
7638 RUNTIME_FUNCTION(MaybeObject*, Runtime_RoundNumber) {
7639  NoHandleAllocation ha;
7640  ASSERT(args.length() == 1);
7641  isolate->counters()->math_round()->Increment();
7642 
7643  if (!args[0]->IsHeapNumber()) {
7644  // Must be smi. Return the argument unchanged for all the other types
7645  // to make fuzz-natives test happy.
7646  return args[0];
7647  }
7648 
7649  HeapNumber* number = reinterpret_cast<HeapNumber*>(args[0]);
7650 
7651  double value = number->value();
7652  int exponent = number->get_exponent();
7653  int sign = number->get_sign();
7654 
7655  if (exponent < -1) {
7656  // Number in range ]-0.5..0.5[. These always round to +/-zero.
7657  if (sign) return isolate->heap()->minus_zero_value();
7658  return Smi::FromInt(0);
7659  }
7660 
7661  // We compare with kSmiValueSize - 2 because (2^30 - 0.1) has exponent 29 and
7662  // should be rounded to 2^30, which is not smi (for 31-bit smis, similar
7663  // argument holds for 32-bit smis).
7664  if (!sign && exponent < kSmiValueSize - 2) {
7665  return Smi::FromInt(static_cast<int>(value + 0.5));
7666  }
7667 
7668  // If the magnitude is big enough, there's no place for fraction part. If we
7669  // try to add 0.5 to this number, 1.0 will be added instead.
7670  if (exponent >= 52) {
7671  return number;
7672  }
7673 
7674  if (sign && value >= -0.5) return isolate->heap()->minus_zero_value();
7675 
7676  // Do not call NumberFromDouble() to avoid extra checks.
7677  return isolate->heap()->AllocateHeapNumber(floor(value + 0.5));
7678 }
7679 
7680 
7681 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sin) {
7682  NoHandleAllocation ha;
7683  ASSERT(args.length() == 1);
7684  isolate->counters()->math_sin()->Increment();
7685 
7687  return isolate->transcendental_cache()->Get(TranscendentalCache::SIN, x);
7688 }
7689 
7690 
7691 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sqrt) {
7692  NoHandleAllocation ha;
7693  ASSERT(args.length() == 1);
7694  isolate->counters()->math_sqrt()->Increment();
7695 
7697  return isolate->heap()->AllocateHeapNumber(fast_sqrt(x));
7698 }
7699 
7700 
7701 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_tan) {
7702  NoHandleAllocation ha;
7703  ASSERT(args.length() == 1);
7704  isolate->counters()->math_tan()->Increment();
7705 
7707  return isolate->transcendental_cache()->Get(TranscendentalCache::TAN, x);
7708 }
7709 
7710 
7711 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateMakeDay) {
7712  NoHandleAllocation ha;
7713  ASSERT(args.length() == 2);
7714 
7715  CONVERT_SMI_ARG_CHECKED(year, 0);
7716  CONVERT_SMI_ARG_CHECKED(month, 1);
7717 
7718  return Smi::FromInt(isolate->date_cache()->DaysFromYearMonth(year, month));
7719 }
7720 
7721 
7722 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateSetValue) {
7723  HandleScope scope(isolate);
7724  ASSERT(args.length() == 3);
7725 
7727  CONVERT_DOUBLE_ARG_CHECKED(time, 1);
7728  CONVERT_SMI_ARG_CHECKED(is_utc, 2);
7729 
7730  DateCache* date_cache = isolate->date_cache();
7731 
7732  Object* value = NULL;
7733  bool is_value_nan = false;
7734  if (isnan(time)) {
7735  value = isolate->heap()->nan_value();
7736  is_value_nan = true;
7737  } else if (!is_utc &&
7740  value = isolate->heap()->nan_value();
7741  is_value_nan = true;
7742  } else {
7743  time = is_utc ? time : date_cache->ToUTC(static_cast<int64_t>(time));
7744  if (time < -DateCache::kMaxTimeInMs ||
7745  time > DateCache::kMaxTimeInMs) {
7746  value = isolate->heap()->nan_value();
7747  is_value_nan = true;
7748  } else {
7749  MaybeObject* maybe_result =
7750  isolate->heap()->AllocateHeapNumber(DoubleToInteger(time));
7751  if (!maybe_result->ToObject(&value)) return maybe_result;
7752  }
7753  }
7754  date->SetValue(value, is_value_nan);
7755  return value;
7756 }
7757 
7758 
7759 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewArgumentsFast) {
7760  HandleScope scope(isolate);
7761  ASSERT(args.length() == 3);
7762 
7763  Handle<JSFunction> callee = args.at<JSFunction>(0);
7764  Object** parameters = reinterpret_cast<Object**>(args[1]);
7765  const int argument_count = Smi::cast(args[2])->value();
7766 
7767  Handle<JSObject> result =
7768  isolate->factory()->NewArgumentsObject(callee, argument_count);
7769  // Allocate the elements if needed.
7770  int parameter_count = callee->shared()->formal_parameter_count();
7771  if (argument_count > 0) {
7772  if (parameter_count > 0) {
7773  int mapped_count = Min(argument_count, parameter_count);
7774  Handle<FixedArray> parameter_map =
7775  isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
7776  parameter_map->set_map(
7777  isolate->heap()->non_strict_arguments_elements_map());
7778 
7779  Handle<Map> old_map(result->map());
7780  Handle<Map> new_map =
7781  isolate->factory()->CopyMapDropTransitions(old_map);
7782  new_map->set_elements_kind(NON_STRICT_ARGUMENTS_ELEMENTS);
7783 
7784  result->set_map(*new_map);
7785  result->set_elements(*parameter_map);
7786 
7787  // Store the context and the arguments array at the beginning of the
7788  // parameter map.
7789  Handle<Context> context(isolate->context());
7790  Handle<FixedArray> arguments =
7791  isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
7792  parameter_map->set(0, *context);
7793  parameter_map->set(1, *arguments);
7794 
7795  // Loop over the actual parameters backwards.
7796  int index = argument_count - 1;
7797  while (index >= mapped_count) {
7798  // These go directly in the arguments array and have no
7799  // corresponding slot in the parameter map.
7800  arguments->set(index, *(parameters - index - 1));
7801  --index;
7802  }
7803 
7804  Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
7805  while (index >= 0) {
7806  // Detect duplicate names to the right in the parameter list.
7807  Handle<String> name(scope_info->ParameterName(index));
7808  int context_local_count = scope_info->ContextLocalCount();
7809  bool duplicate = false;
7810  for (int j = index + 1; j < parameter_count; ++j) {
7811  if (scope_info->ParameterName(j) == *name) {
7812  duplicate = true;
7813  break;
7814  }
7815  }
7816 
7817  if (duplicate) {
7818  // This goes directly in the arguments array with a hole in the
7819  // parameter map.
7820  arguments->set(index, *(parameters - index - 1));
7821  parameter_map->set_the_hole(index + 2);
7822  } else {
7823  // The context index goes in the parameter map with a hole in the
7824  // arguments array.
7825  int context_index = -1;
7826  for (int j = 0; j < context_local_count; ++j) {
7827  if (scope_info->ContextLocalName(j) == *name) {
7828  context_index = j;
7829  break;
7830  }
7831  }
7832  ASSERT(context_index >= 0);
7833  arguments->set_the_hole(index);
7834  parameter_map->set(index + 2, Smi::FromInt(
7835  Context::MIN_CONTEXT_SLOTS + context_index));
7836  }
7837 
7838  --index;
7839  }
7840  } else {
7841  // If there is no aliasing, the arguments object elements are not
7842  // special in any way.
7843  Handle<FixedArray> elements =
7844  isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
7845  result->set_elements(*elements);
7846  for (int i = 0; i < argument_count; ++i) {
7847  elements->set(i, *(parameters - i - 1));
7848  }
7849  }
7850  }
7851  return *result;
7852 }
7853 
7854 
7855 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStrictArgumentsFast) {
7856  NoHandleAllocation ha;
7857  ASSERT(args.length() == 3);
7858 
7859  JSFunction* callee = JSFunction::cast(args[0]);
7860  Object** parameters = reinterpret_cast<Object**>(args[1]);
7861  const int length = args.smi_at(2);
7862 
7863  Object* result;
7864  { MaybeObject* maybe_result =
7865  isolate->heap()->AllocateArgumentsObject(callee, length);
7866  if (!maybe_result->ToObject(&result)) return maybe_result;
7867  }
7868  // Allocate the elements if needed.
7869  if (length > 0) {
7870  // Allocate the fixed array.
7871  Object* obj;
7872  { MaybeObject* maybe_obj = isolate->heap()->AllocateRawFixedArray(length);
7873  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7874  }
7875 
7876  AssertNoAllocation no_gc;
7877  FixedArray* array = reinterpret_cast<FixedArray*>(obj);
7878  array->set_map_no_write_barrier(isolate->heap()->fixed_array_map());
7879  array->set_length(length);
7880 
7881  WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
7882  for (int i = 0; i < length; i++) {
7883  array->set(i, *--parameters, mode);
7884  }
7885  JSObject::cast(result)->set_elements(FixedArray::cast(obj));
7886  }
7887  return result;
7888 }
7889 
7890 
7891 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewClosure) {
7892  HandleScope scope(isolate);
7893  ASSERT(args.length() == 3);
7894  CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
7896  CONVERT_BOOLEAN_ARG_CHECKED(pretenure, 2);
7897 
7898  // The caller ensures that we pretenure closures that are assigned
7899  // directly to properties.
7900  PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
7901  Handle<JSFunction> result =
7902  isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
7903  context,
7904  pretenure_flag);
7905  return *result;
7906 }
7907 
7908 
7909 // Find the arguments of the JavaScript function invocation that called
7910 // into C++ code. Collect these in a newly allocated array of handles (possibly
7911 // prefixed by a number of empty handles).
7912 static SmartArrayPointer<Handle<Object> > GetCallerArguments(
7913  int prefix_argc,
7914  int* total_argc) {
7915  // Find frame containing arguments passed to the caller.
7917  JavaScriptFrame* frame = it.frame();
7918  List<JSFunction*> functions(2);
7919  frame->GetFunctions(&functions);
7920  if (functions.length() > 1) {
7921  int inlined_jsframe_index = functions.length() - 1;
7922  JSFunction* inlined_function = functions[inlined_jsframe_index];
7923  Vector<SlotRef> args_slots =
7924  SlotRef::ComputeSlotMappingForArguments(
7925  frame,
7926  inlined_jsframe_index,
7927  inlined_function->shared()->formal_parameter_count());
7928 
7929  int args_count = args_slots.length();
7930 
7931  *total_argc = prefix_argc + args_count;
7932  SmartArrayPointer<Handle<Object> > param_data(
7933  NewArray<Handle<Object> >(*total_argc));
7934  for (int i = 0; i < args_count; i++) {
7935  Handle<Object> val = args_slots[i].GetValue();
7936  param_data[prefix_argc + i] = val;
7937  }
7938 
7939  args_slots.Dispose();
7940 
7941  return param_data;
7942  } else {
7943  it.AdvanceToArgumentsFrame();
7944  frame = it.frame();
7945  int args_count = frame->ComputeParametersCount();
7946 
7947  *total_argc = prefix_argc + args_count;
7948  SmartArrayPointer<Handle<Object> > param_data(
7949  NewArray<Handle<Object> >(*total_argc));
7950  for (int i = 0; i < args_count; i++) {
7951  Handle<Object> val = Handle<Object>(frame->GetParameter(i));
7952  param_data[prefix_argc + i] = val;
7953  }
7954  return param_data;
7955  }
7956 }
7957 
7958 
7959 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionBindArguments) {
7960  HandleScope scope(isolate);
7961  ASSERT(args.length() == 4);
7962  CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0);
7963  RUNTIME_ASSERT(args[3]->IsNumber());
7964  Handle<Object> bindee = args.at<Object>(1);
7965 
7966  // TODO(lrn): Create bound function in C++ code from premade shared info.
7967  bound_function->shared()->set_bound(true);
7968  // Get all arguments of calling function (Function.prototype.bind).
7969  int argc = 0;
7970  SmartArrayPointer<Handle<Object> > arguments = GetCallerArguments(0, &argc);
7971  // Don't count the this-arg.
7972  if (argc > 0) {
7973  ASSERT(*arguments[0] == args[2]);
7974  argc--;
7975  } else {
7976  ASSERT(args[2]->IsUndefined());
7977  }
7978  // Initialize array of bindings (function, this, and any existing arguments
7979  // if the function was already bound).
7980  Handle<FixedArray> new_bindings;
7981  int i;
7982  if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) {
7983  Handle<FixedArray> old_bindings(
7984  JSFunction::cast(*bindee)->function_bindings());
7985  new_bindings =
7986  isolate->factory()->NewFixedArray(old_bindings->length() + argc);
7987  bindee = Handle<Object>(old_bindings->get(JSFunction::kBoundFunctionIndex));
7988  i = 0;
7989  for (int n = old_bindings->length(); i < n; i++) {
7990  new_bindings->set(i, old_bindings->get(i));
7991  }
7992  } else {
7993  int array_size = JSFunction::kBoundArgumentsStartIndex + argc;
7994  new_bindings = isolate->factory()->NewFixedArray(array_size);
7995  new_bindings->set(JSFunction::kBoundFunctionIndex, *bindee);
7996  new_bindings->set(JSFunction::kBoundThisIndex, args[2]);
7997  i = 2;
7998  }
7999  // Copy arguments, skipping the first which is "this_arg".
8000  for (int j = 0; j < argc; j++, i++) {
8001  new_bindings->set(i, *arguments[j + 1]);
8002  }
8003  new_bindings->set_map_no_write_barrier(
8004  isolate->heap()->fixed_cow_array_map());
8005  bound_function->set_function_bindings(*new_bindings);
8006 
8007  // Update length.
8008  Handle<String> length_symbol = isolate->factory()->length_symbol();
8009  Handle<Object> new_length(args.at<Object>(3));
8010  PropertyAttributes attr =
8012  ForceSetProperty(bound_function, length_symbol, new_length, attr);
8013  return *bound_function;
8014 }
8015 
8016 
8017 RUNTIME_FUNCTION(MaybeObject*, Runtime_BoundFunctionGetBindings) {
8018  HandleScope handles(isolate);
8019  ASSERT(args.length() == 1);
8020  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0);
8021  if (callable->IsJSFunction()) {
8022  Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
8023  if (function->shared()->bound()) {
8024  Handle<FixedArray> bindings(function->function_bindings());
8025  ASSERT(bindings->map() == isolate->heap()->fixed_cow_array_map());
8026  return *isolate->factory()->NewJSArrayWithElements(bindings);
8027  }
8028  }
8029  return isolate->heap()->undefined_value();
8030 }
8031 
8032 
8033 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObjectFromBound) {
8034  HandleScope scope(isolate);
8035  ASSERT(args.length() == 1);
8036  // First argument is a function to use as a constructor.
8037  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8038  RUNTIME_ASSERT(function->shared()->bound());
8039 
8040  // The argument is a bound function. Extract its bound arguments
8041  // and callable.
8042  Handle<FixedArray> bound_args =
8043  Handle<FixedArray>(FixedArray::cast(function->function_bindings()));
8044  int bound_argc = bound_args->length() - JSFunction::kBoundArgumentsStartIndex;
8045  Handle<Object> bound_function(
8047  ASSERT(!bound_function->IsJSFunction() ||
8048  !Handle<JSFunction>::cast(bound_function)->shared()->bound());
8049 
8050  int total_argc = 0;
8051  SmartArrayPointer<Handle<Object> > param_data =
8052  GetCallerArguments(bound_argc, &total_argc);
8053  for (int i = 0; i < bound_argc; i++) {
8054  param_data[i] = Handle<Object>(bound_args->get(
8056  }
8057 
8058  if (!bound_function->IsJSFunction()) {
8059  bool exception_thrown;
8060  bound_function = Execution::TryGetConstructorDelegate(bound_function,
8061  &exception_thrown);
8062  if (exception_thrown) return Failure::Exception();
8063  }
8064  ASSERT(bound_function->IsJSFunction());
8065 
8066  bool exception = false;
8067  Handle<Object> result =
8068  Execution::New(Handle<JSFunction>::cast(bound_function),
8069  total_argc, *param_data, &exception);
8070  if (exception) {
8071  return Failure::Exception();
8072  }
8073  ASSERT(!result.is_null());
8074  return *result;
8075 }
8076 
8077 
8078 static void TrySettingInlineConstructStub(Isolate* isolate,
8079  Handle<JSFunction> function) {
8080  Handle<Object> prototype = isolate->factory()->null_value();
8081  if (function->has_instance_prototype()) {
8082  prototype = Handle<Object>(function->instance_prototype(), isolate);
8083  }
8084  if (function->shared()->CanGenerateInlineConstructor(*prototype)) {
8085  ConstructStubCompiler compiler(isolate);
8086  Handle<Code> code = compiler.CompileConstructStub(function);
8087  function->shared()->set_construct_stub(*code);
8088  }
8089 }
8090 
8091 
8092 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObject) {
8093  HandleScope scope(isolate);
8094  ASSERT(args.length() == 1);
8095 
8096  Handle<Object> constructor = args.at<Object>(0);
8097 
8098  // If the constructor isn't a proper function we throw a type error.
8099  if (!constructor->IsJSFunction()) {
8100  Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
8101  Handle<Object> type_error =
8102  isolate->factory()->NewTypeError("not_constructor", arguments);
8103  return isolate->Throw(*type_error);
8104  }
8105 
8106  Handle<JSFunction> function = Handle<JSFunction>::cast(constructor);
8107 
8108  // If function should not have prototype, construction is not allowed. In this
8109  // case generated code bailouts here, since function has no initial_map.
8110  if (!function->should_have_prototype() && !function->shared()->bound()) {
8111  Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
8112  Handle<Object> type_error =
8113  isolate->factory()->NewTypeError("not_constructor", arguments);
8114  return isolate->Throw(*type_error);
8115  }
8116 
8117 #ifdef ENABLE_DEBUGGER_SUPPORT
8118  Debug* debug = isolate->debug();
8119  // Handle stepping into constructors if step into is active.
8120  if (debug->StepInActive()) {
8121  debug->HandleStepIn(function, Handle<Object>::null(), 0, true);
8122  }
8123 #endif
8124 
8125  if (function->has_initial_map()) {
8126  if (function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
8127  // The 'Function' function ignores the receiver object when
8128  // called using 'new' and creates a new JSFunction object that
8129  // is returned. The receiver object is only used for error
8130  // reporting if an error occurs when constructing the new
8131  // JSFunction. FACTORY->NewJSObject() should not be used to
8132  // allocate JSFunctions since it does not properly initialize
8133  // the shared part of the function. Since the receiver is
8134  // ignored anyway, we use the global object as the receiver
8135  // instead of a new JSFunction object. This way, errors are
8136  // reported the same way whether or not 'Function' is called
8137  // using 'new'.
8138  return isolate->context()->global();
8139  }
8140  }
8141 
8142  // The function should be compiled for the optimization hints to be
8143  // available. We cannot use EnsureCompiled because that forces a
8144  // compilation through the shared function info which makes it
8145  // impossible for us to optimize.
8146  if (!function->is_compiled()) {
8148  }
8149 
8150  Handle<SharedFunctionInfo> shared(function->shared(), isolate);
8151  if (!function->has_initial_map() &&
8152  shared->IsInobjectSlackTrackingInProgress()) {
8153  // The tracking is already in progress for another function. We can only
8154  // track one initial_map at a time, so we force the completion before the
8155  // function is called as a constructor for the first time.
8156  shared->CompleteInobjectSlackTracking();
8157  }
8158 
8159  bool first_allocation = !shared->live_objects_may_exist();
8160  Handle<JSObject> result = isolate->factory()->NewJSObject(function);
8161  RETURN_IF_EMPTY_HANDLE(isolate, result);
8162  // Delay setting the stub if inobject slack tracking is in progress.
8163  if (first_allocation && !shared->IsInobjectSlackTrackingInProgress()) {
8164  TrySettingInlineConstructStub(isolate, function);
8165  }
8166 
8167  isolate->counters()->constructed_objects()->Increment();
8168  isolate->counters()->constructed_objects_runtime()->Increment();
8169 
8170  return *result;
8171 }
8172 
8173 
8174 RUNTIME_FUNCTION(MaybeObject*, Runtime_FinalizeInstanceSize) {
8175  HandleScope scope(isolate);
8176  ASSERT(args.length() == 1);
8177 
8178  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8179  function->shared()->CompleteInobjectSlackTracking();
8180  TrySettingInlineConstructStub(isolate, function);
8181 
8182  return isolate->heap()->undefined_value();
8183 }
8184 
8185 
8186 RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyCompile) {
8187  HandleScope scope(isolate);
8188  ASSERT(args.length() == 1);
8189 
8190  Handle<JSFunction> function = args.at<JSFunction>(0);
8191 #ifdef DEBUG
8192  if (FLAG_trace_lazy && !function->shared()->is_compiled()) {
8193  PrintF("[lazy: ");
8194  function->PrintName();
8195  PrintF("]\n");
8196  }
8197 #endif
8198 
8199  // Compile the target function.
8200  ASSERT(!function->is_compiled());
8201  if (!JSFunction::CompileLazy(function, KEEP_EXCEPTION)) {
8202  return Failure::Exception();
8203  }
8204 
8205  // All done. Return the compiled code.
8206  ASSERT(function->is_compiled());
8207  return function->code();
8208 }
8209 
8210 
8211 RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyRecompile) {
8212  HandleScope scope(isolate);
8213  ASSERT(args.length() == 1);
8214  Handle<JSFunction> function = args.at<JSFunction>(0);
8215 
8216  // If the function is not compiled ignore the lazy
8217  // recompilation. This can happen if the debugger is activated and
8218  // the function is returned to the not compiled state.
8219  if (!function->shared()->is_compiled()) {
8220  function->ReplaceCode(function->shared()->code());
8221  return function->code();
8222  }
8223 
8224  // If the function is not optimizable or debugger is active continue using the
8225  // code from the full compiler.
8226  if (!function->shared()->code()->optimizable() ||
8227  isolate->DebuggerHasBreakPoints()) {
8228  if (FLAG_trace_opt) {
8229  PrintF("[failed to optimize ");
8230  function->PrintName();
8231  PrintF(": is code optimizable: %s, is debugger enabled: %s]\n",
8232  function->shared()->code()->optimizable() ? "T" : "F",
8233  isolate->DebuggerHasBreakPoints() ? "T" : "F");
8234  }
8235  function->ReplaceCode(function->shared()->code());
8236  return function->code();
8237  }
8238  function->shared()->code()->set_profiler_ticks(0);
8239  if (JSFunction::CompileOptimized(function,
8241  CLEAR_EXCEPTION)) {
8242  return function->code();
8243  }
8244  if (FLAG_trace_opt) {
8245  PrintF("[failed to optimize ");
8246  function->PrintName();
8247  PrintF(": optimized compilation failed]\n");
8248  }
8249  function->ReplaceCode(function->shared()->code());
8250  return function->code();
8251 }
8252 
8253 
8255  public:
8256  explicit ActivationsFinder(JSFunction* function)
8257  : function_(function), has_activations_(false) {}
8258 
8259  void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
8260  if (has_activations_) return;
8261 
8262  for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
8263  JavaScriptFrame* frame = it.frame();
8264  if (frame->is_optimized() && frame->function() == function_) {
8265  has_activations_ = true;
8266  return;
8267  }
8268  }
8269  }
8270 
8271  bool has_activations() { return has_activations_; }
8272 
8273  private:
8274  JSFunction* function_;
8275  bool has_activations_;
8276 };
8277 
8278 
8279 static void MaterializeArgumentsObjectInFrame(Isolate* isolate,
8280  JavaScriptFrame* frame) {
8281  Handle<JSFunction> function(JSFunction::cast(frame->function()), isolate);
8282  Handle<Object> arguments;
8283  for (int i = frame->ComputeExpressionsCount() - 1; i >= 0; --i) {
8284  if (frame->GetExpression(i) == isolate->heap()->arguments_marker()) {
8285  if (arguments.is_null()) {
8286  // FunctionGetArguments can't throw an exception, so cast away the
8287  // doubt with an assert.
8288  arguments = Handle<Object>(
8290  NULL)->ToObjectUnchecked());
8291  ASSERT(*arguments != isolate->heap()->null_value());
8292  ASSERT(*arguments != isolate->heap()->undefined_value());
8293  }
8294  frame->SetExpression(i, *arguments);
8295  if (FLAG_trace_deopt) {
8296  PrintF("Materializing arguments object for frame %p - %p: %p ",
8297  reinterpret_cast<void*>(frame->sp()),
8298  reinterpret_cast<void*>(frame->fp()),
8299  reinterpret_cast<void*>(*arguments));
8300  arguments->ShortPrint();
8301  PrintF("\n");
8302  }
8303  }
8304  }
8305 }
8306 
8307 
8308 RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyDeoptimized) {
8309  HandleScope scope(isolate);
8310  ASSERT(args.length() == 1);
8311  RUNTIME_ASSERT(args[0]->IsSmi());
8313  static_cast<Deoptimizer::BailoutType>(args.smi_at(0));
8314  Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8315  ASSERT(isolate->heap()->IsAllocationAllowed());
8316  int jsframes = deoptimizer->jsframe_count();
8317 
8318  deoptimizer->MaterializeHeapNumbers();
8319  delete deoptimizer;
8320 
8321  JavaScriptFrameIterator it(isolate);
8322  for (int i = 0; i < jsframes - 1; i++) {
8323  MaterializeArgumentsObjectInFrame(isolate, it.frame());
8324  it.Advance();
8325  }
8326 
8327  JavaScriptFrame* frame = it.frame();
8328  RUNTIME_ASSERT(frame->function()->IsJSFunction());
8329  Handle<JSFunction> function(JSFunction::cast(frame->function()), isolate);
8330  MaterializeArgumentsObjectInFrame(isolate, frame);
8331 
8332  if (type == Deoptimizer::EAGER) {
8333  RUNTIME_ASSERT(function->IsOptimized());
8334  }
8335 
8336  // Avoid doing too much work when running with --always-opt and keep
8337  // the optimized code around.
8338  if (FLAG_always_opt || type == Deoptimizer::LAZY) {
8339  return isolate->heap()->undefined_value();
8340  }
8341 
8342  // Find other optimized activations of the function.
8343  bool has_other_activations = false;
8344  while (!it.done()) {
8345  JavaScriptFrame* frame = it.frame();
8346  if (frame->is_optimized() && frame->function() == *function) {
8347  has_other_activations = true;
8348  break;
8349  }
8350  it.Advance();
8351  }
8352 
8353  if (!has_other_activations) {
8354  ActivationsFinder activations_finder(*function);
8355  isolate->thread_manager()->IterateArchivedThreads(&activations_finder);
8356  has_other_activations = activations_finder.has_activations();
8357  }
8358 
8359  if (!has_other_activations) {
8360  if (FLAG_trace_deopt) {
8361  PrintF("[removing optimized code for: ");
8362  function->PrintName();
8363  PrintF("]\n");
8364  }
8365  function->ReplaceCode(function->shared()->code());
8366  } else {
8368  }
8369  return isolate->heap()->undefined_value();
8370 }
8371 
8372 
8373 RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyOSR) {
8374  Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8375  delete deoptimizer;
8376  return isolate->heap()->undefined_value();
8377 }
8378 
8379 
8380 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeoptimizeFunction) {
8381  HandleScope scope(isolate);
8382  ASSERT(args.length() == 1);
8383  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8384  if (!function->IsOptimized()) return isolate->heap()->undefined_value();
8385 
8387 
8388  return isolate->heap()->undefined_value();
8389 }
8390 
8391 
8392 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearFunctionTypeFeedback) {
8393  HandleScope scope(isolate);
8394  ASSERT(args.length() == 1);
8395  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8396  Code* unoptimized = function->shared()->code();
8397  if (unoptimized->kind() == Code::FUNCTION) {
8398  unoptimized->ClearInlineCaches();
8399  unoptimized->ClearTypeFeedbackCells(isolate->heap());
8400  }
8401  return isolate->heap()->undefined_value();
8402 }
8403 
8404 
8405 RUNTIME_FUNCTION(MaybeObject*, Runtime_RunningInSimulator) {
8406 #if defined(USE_SIMULATOR)
8407  return isolate->heap()->true_value();
8408 #else
8409  return isolate->heap()->false_value();
8410 #endif
8411 }
8412 
8413 
8414 RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) {
8415  HandleScope scope(isolate);
8416  RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
8417  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8418 
8419  if (!function->IsOptimizable()) return isolate->heap()->undefined_value();
8420  function->MarkForLazyRecompilation();
8421 
8422  Code* unoptimized = function->shared()->code();
8423  if (args.length() == 2 &&
8424  unoptimized->kind() == Code::FUNCTION) {
8426  CHECK(type->IsEqualTo(CStrVector("osr")));
8427  isolate->runtime_profiler()->AttemptOnStackReplacement(*function);
8430  }
8431 
8432  return isolate->heap()->undefined_value();
8433 }
8434 
8435 
8436 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) {
8437  HandleScope scope(isolate);
8438  ASSERT(args.length() == 1);
8439  // The least significant bit (after untagging) indicates whether the
8440  // function is currently optimized, regardless of reason.
8441  if (!V8::UseCrankshaft()) {
8442  return Smi::FromInt(4); // 4 == "never".
8443  }
8444  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8445  if (FLAG_always_opt) {
8446  // We may have always opt, but that is more best-effort than a real
8447  // promise, so we still say "no" if it is not optimized.
8448  return function->IsOptimized() ? Smi::FromInt(3) // 3 == "always".
8449  : Smi::FromInt(2); // 2 == "no".
8450  }
8451  return function->IsOptimized() ? Smi::FromInt(1) // 1 == "yes".
8452  : Smi::FromInt(2); // 2 == "no".
8453 }
8454 
8455 
8456 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationCount) {
8457  HandleScope scope(isolate);
8458  ASSERT(args.length() == 1);
8459  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8460  return Smi::FromInt(function->shared()->opt_count());
8461 }
8462 
8463 
8464 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
8465  HandleScope scope(isolate);
8466  ASSERT(args.length() == 1);
8467  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8468 
8469  // We're not prepared to handle a function with arguments object.
8470  ASSERT(!function->shared()->uses_arguments());
8471 
8472  // We have hit a back edge in an unoptimized frame for a function that was
8473  // selected for on-stack replacement. Find the unoptimized code object.
8474  Handle<Code> unoptimized(function->shared()->code(), isolate);
8475  // Keep track of whether we've succeeded in optimizing.
8476  bool succeeded = unoptimized->optimizable();
8477  if (succeeded) {
8478  // If we are trying to do OSR when there are already optimized
8479  // activations of the function, it means (a) the function is directly or
8480  // indirectly recursive and (b) an optimized invocation has been
8481  // deoptimized so that we are currently in an unoptimized activation.
8482  // Check for optimized activations of this function.
8483  JavaScriptFrameIterator it(isolate);
8484  while (succeeded && !it.done()) {
8485  JavaScriptFrame* frame = it.frame();
8486  succeeded = !frame->is_optimized() || frame->function() != *function;
8487  it.Advance();
8488  }
8489  }
8490 
8491  int ast_id = AstNode::kNoNumber;
8492  if (succeeded) {
8493  // The top JS function is this one, the PC is somewhere in the
8494  // unoptimized code.
8495  JavaScriptFrameIterator it(isolate);
8496  JavaScriptFrame* frame = it.frame();
8497  ASSERT(frame->function() == *function);
8498  ASSERT(frame->LookupCode() == *unoptimized);
8499  ASSERT(unoptimized->contains(frame->pc()));
8500 
8501  // Use linear search of the unoptimized code's stack check table to find
8502  // the AST id matching the PC.
8503  Address start = unoptimized->instruction_start();
8504  unsigned target_pc_offset = static_cast<unsigned>(frame->pc() - start);
8505  Address table_cursor = start + unoptimized->stack_check_table_offset();
8506  uint32_t table_length = Memory::uint32_at(table_cursor);
8507  table_cursor += kIntSize;
8508  for (unsigned i = 0; i < table_length; ++i) {
8509  // Table entries are (AST id, pc offset) pairs.
8510  uint32_t pc_offset = Memory::uint32_at(table_cursor + kIntSize);
8511  if (pc_offset == target_pc_offset) {
8512  ast_id = static_cast<int>(Memory::uint32_at(table_cursor));
8513  break;
8514  }
8515  table_cursor += 2 * kIntSize;
8516  }
8517  ASSERT(ast_id != AstNode::kNoNumber);
8518  if (FLAG_trace_osr) {
8519  PrintF("[replacing on-stack at AST id %d in ", ast_id);
8520  function->PrintName();
8521  PrintF("]\n");
8522  }
8523 
8524  // Try to compile the optimized code. A true return value from
8525  // CompileOptimized means that compilation succeeded, not necessarily
8526  // that optimization succeeded.
8527  if (JSFunction::CompileOptimized(function, ast_id, CLEAR_EXCEPTION) &&
8528  function->IsOptimized()) {
8530  function->code()->deoptimization_data());
8531  if (data->OsrPcOffset()->value() >= 0) {
8532  if (FLAG_trace_osr) {
8533  PrintF("[on-stack replacement offset %d in optimized code]\n",
8534  data->OsrPcOffset()->value());
8535  }
8536  ASSERT(data->OsrAstId()->value() == ast_id);
8537  } else {
8538  // We may never generate the desired OSR entry if we emit an
8539  // early deoptimize.
8540  succeeded = false;
8541  }
8542  } else {
8543  succeeded = false;
8544  }
8545  }
8546 
8547  // Revert to the original stack checks in the original unoptimized code.
8548  if (FLAG_trace_osr) {
8549  PrintF("[restoring original stack checks in ");
8550  function->PrintName();
8551  PrintF("]\n");
8552  }
8553  Handle<Code> check_code;
8554  if (FLAG_count_based_interrupts) {
8555  InterruptStub interrupt_stub;
8556  check_code = interrupt_stub.GetCode();
8557  } else // NOLINT
8558  { // NOLINT
8559  StackCheckStub check_stub;
8560  check_code = check_stub.GetCode();
8561  }
8562  Handle<Code> replacement_code = isolate->builtins()->OnStackReplacement();
8563  Deoptimizer::RevertStackCheckCode(*unoptimized,
8564  *check_code,
8565  *replacement_code);
8566 
8567  // Allow OSR only at nesting level zero again.
8568  unoptimized->set_allow_osr_at_loop_nesting_level(0);
8569 
8570  // If the optimization attempt succeeded, return the AST id tagged as a
8571  // smi. This tells the builtin that we need to translate the unoptimized
8572  // frame to an optimized one.
8573  if (succeeded) {
8574  ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION);
8575  return Smi::FromInt(ast_id);
8576  } else {
8577  if (function->IsMarkedForLazyRecompilation()) {
8578  function->ReplaceCode(function->shared()->code());
8579  }
8580  return Smi::FromInt(-1);
8581  }
8582 }
8583 
8584 
8585 RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckIsBootstrapping) {
8586  RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8587  return isolate->heap()->undefined_value();
8588 }
8589 
8590 
8591 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetRootNaN) {
8592  RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8593  return isolate->heap()->nan_value();
8594 }
8595 
8596 
8597 RUNTIME_FUNCTION(MaybeObject*, Runtime_Call) {
8598  HandleScope scope(isolate);
8599  ASSERT(args.length() >= 2);
8600  int argc = args.length() - 2;
8601  CONVERT_ARG_CHECKED(JSReceiver, fun, argc + 1);
8602  Object* receiver = args[0];
8603 
8604  // If there are too many arguments, allocate argv via malloc.
8605  const int argv_small_size = 10;
8606  Handle<Object> argv_small_buffer[argv_small_size];
8607  SmartArrayPointer<Handle<Object> > argv_large_buffer;
8608  Handle<Object>* argv = argv_small_buffer;
8609  if (argc > argv_small_size) {
8610  argv = new Handle<Object>[argc];
8611  if (argv == NULL) return isolate->StackOverflow();
8612  argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8613  }
8614 
8615  for (int i = 0; i < argc; ++i) {
8616  MaybeObject* maybe = args[1 + i];
8617  Object* object;
8618  if (!maybe->To<Object>(&object)) return maybe;
8619  argv[i] = Handle<Object>(object);
8620  }
8621 
8622  bool threw;
8623  Handle<JSReceiver> hfun(fun);
8624  Handle<Object> hreceiver(receiver);
8625  Handle<Object> result =
8626  Execution::Call(hfun, hreceiver, argc, argv, &threw, true);
8627 
8628  if (threw) return Failure::Exception();
8629  return *result;
8630 }
8631 
8632 
8633 RUNTIME_FUNCTION(MaybeObject*, Runtime_Apply) {
8634  HandleScope scope(isolate);
8635  ASSERT(args.length() == 5);
8637  Handle<Object> receiver = args.at<Object>(1);
8638  CONVERT_ARG_HANDLE_CHECKED(JSObject, arguments, 2);
8639  CONVERT_SMI_ARG_CHECKED(offset, 3);
8640  CONVERT_SMI_ARG_CHECKED(argc, 4);
8641  ASSERT(offset >= 0);
8642  ASSERT(argc >= 0);
8643 
8644  // If there are too many arguments, allocate argv via malloc.
8645  const int argv_small_size = 10;
8646  Handle<Object> argv_small_buffer[argv_small_size];
8647  SmartArrayPointer<Handle<Object> > argv_large_buffer;
8648  Handle<Object>* argv = argv_small_buffer;
8649  if (argc > argv_small_size) {
8650  argv = new Handle<Object>[argc];
8651  if (argv == NULL) return isolate->StackOverflow();
8652  argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8653  }
8654 
8655  for (int i = 0; i < argc; ++i) {
8656  argv[i] = Object::GetElement(arguments, offset + i);
8657  }
8658 
8659  bool threw;
8660  Handle<Object> result =
8661  Execution::Call(fun, receiver, argc, argv, &threw, true);
8662 
8663  if (threw) return Failure::Exception();
8664  return *result;
8665 }
8666 
8667 
8668 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionDelegate) {
8669  HandleScope scope(isolate);
8670  ASSERT(args.length() == 1);
8671  RUNTIME_ASSERT(!args[0]->IsJSFunction());
8672  return *Execution::GetFunctionDelegate(args.at<Object>(0));
8673 }
8674 
8675 
8676 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) {
8677  HandleScope scope(isolate);
8678  ASSERT(args.length() == 1);
8679  RUNTIME_ASSERT(!args[0]->IsJSFunction());
8680  return *Execution::GetConstructorDelegate(args.at<Object>(0));
8681 }
8682 
8683 
8684 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewFunctionContext) {
8685  NoHandleAllocation ha;
8686  ASSERT(args.length() == 1);
8687 
8688  CONVERT_ARG_CHECKED(JSFunction, function, 0);
8689  int length = function->shared()->scope_info()->ContextLength();
8690  Object* result;
8691  { MaybeObject* maybe_result =
8692  isolate->heap()->AllocateFunctionContext(length, function);
8693  if (!maybe_result->ToObject(&result)) return maybe_result;
8694  }
8695 
8696  isolate->set_context(Context::cast(result));
8697 
8698  return result; // non-failure
8699 }
8700 
8701 
8702 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushWithContext) {
8703  NoHandleAllocation ha;
8704  ASSERT(args.length() == 2);
8705  JSObject* extension_object;
8706  if (args[0]->IsJSObject()) {
8707  extension_object = JSObject::cast(args[0]);
8708  } else {
8709  // Convert the object to a proper JavaScript object.
8710  MaybeObject* maybe_js_object = args[0]->ToObject();
8711  if (!maybe_js_object->To(&extension_object)) {
8712  if (Failure::cast(maybe_js_object)->IsInternalError()) {
8713  HandleScope scope(isolate);
8714  Handle<Object> handle = args.at<Object>(0);
8715  Handle<Object> result =
8716  isolate->factory()->NewTypeError("with_expression",
8717  HandleVector(&handle, 1));
8718  return isolate->Throw(*result);
8719  } else {
8720  return maybe_js_object;
8721  }
8722  }
8723  }
8724 
8725  JSFunction* function;
8726  if (args[1]->IsSmi()) {
8727  // A smi sentinel indicates a context nested inside global code rather
8728  // than some function. There is a canonical empty function that can be
8729  // gotten from the global context.
8730  function = isolate->context()->global_context()->closure();
8731  } else {
8732  function = JSFunction::cast(args[1]);
8733  }
8734 
8735  Context* context;
8736  MaybeObject* maybe_context =
8737  isolate->heap()->AllocateWithContext(function,
8738  isolate->context(),
8739  extension_object);
8740  if (!maybe_context->To(&context)) return maybe_context;
8741  isolate->set_context(context);
8742  return context;
8743 }
8744 
8745 
8746 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushCatchContext) {
8747  NoHandleAllocation ha;
8748  ASSERT(args.length() == 3);
8749  String* name = String::cast(args[0]);
8750  Object* thrown_object = args[1];
8751  JSFunction* function;
8752  if (args[2]->IsSmi()) {
8753  // A smi sentinel indicates a context nested inside global code rather
8754  // than some function. There is a canonical empty function that can be
8755  // gotten from the global context.
8756  function = isolate->context()->global_context()->closure();
8757  } else {
8758  function = JSFunction::cast(args[2]);
8759  }
8760  Context* context;
8761  MaybeObject* maybe_context =
8762  isolate->heap()->AllocateCatchContext(function,
8763  isolate->context(),
8764  name,
8765  thrown_object);
8766  if (!maybe_context->To(&context)) return maybe_context;
8767  isolate->set_context(context);
8768  return context;
8769 }
8770 
8771 
8772 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushBlockContext) {
8773  NoHandleAllocation ha;
8774  ASSERT(args.length() == 2);
8775  ScopeInfo* scope_info = ScopeInfo::cast(args[0]);
8776  JSFunction* function;
8777  if (args[1]->IsSmi()) {
8778  // A smi sentinel indicates a context nested inside global code rather
8779  // than some function. There is a canonical empty function that can be
8780  // gotten from the global context.
8781  function = isolate->context()->global_context()->closure();
8782  } else {
8783  function = JSFunction::cast(args[1]);
8784  }
8785  Context* context;
8786  MaybeObject* maybe_context =
8787  isolate->heap()->AllocateBlockContext(function,
8788  isolate->context(),
8789  scope_info);
8790  if (!maybe_context->To(&context)) return maybe_context;
8791  isolate->set_context(context);
8792  return context;
8793 }
8794 
8795 
8796 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushModuleContext) {
8797  NoHandleAllocation ha;
8798  ASSERT(args.length() == 2);
8799  CONVERT_ARG_CHECKED(ScopeInfo, scope_info, 0);
8800  CONVERT_ARG_HANDLE_CHECKED(JSModule, instance, 1);
8801 
8802  Context* context;
8803  MaybeObject* maybe_context =
8804  isolate->heap()->AllocateModuleContext(isolate->context(),
8805  scope_info);
8806  if (!maybe_context->To(&context)) return maybe_context;
8807  // Also initialize the context slot of the instance object.
8808  instance->set_context(context);
8809  isolate->set_context(context);
8810 
8811  return context;
8812 }
8813 
8814 
8815 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteContextSlot) {
8816  HandleScope scope(isolate);
8817  ASSERT(args.length() == 2);
8818 
8819  CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
8821 
8822  int index;
8823  PropertyAttributes attributes;
8825  BindingFlags binding_flags;
8826  Handle<Object> holder = context->Lookup(name,
8827  flags,
8828  &index,
8829  &attributes,
8830  &binding_flags);
8831 
8832  // If the slot was not found the result is true.
8833  if (holder.is_null()) {
8834  return isolate->heap()->true_value();
8835  }
8836 
8837  // If the slot was found in a context, it should be DONT_DELETE.
8838  if (holder->IsContext()) {
8839  return isolate->heap()->false_value();
8840  }
8841 
8842  // The slot was found in a JSObject, either a context extension object,
8843  // the global object, or the subject of a with. Try to delete it
8844  // (respecting DONT_DELETE).
8845  Handle<JSObject> object = Handle<JSObject>::cast(holder);
8846  return object->DeleteProperty(*name, JSReceiver::NORMAL_DELETION);
8847 }
8848 
8849 
8850 // A mechanism to return a pair of Object pointers in registers (if possible).
8851 // How this is achieved is calling convention-dependent.
8852 // All currently supported x86 compiles uses calling conventions that are cdecl
8853 // variants where a 64-bit value is returned in two 32-bit registers
8854 // (edx:eax on ia32, r1:r0 on ARM).
8855 // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax.
8856 // In Win64 calling convention, a struct of two pointers is returned in memory,
8857 // allocated by the caller, and passed as a pointer in a hidden first parameter.
8858 #ifdef V8_HOST_ARCH_64_BIT
8859 struct ObjectPair {
8860  MaybeObject* x;
8861  MaybeObject* y;
8862 };
8863 
8864 static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
8865  ObjectPair result = {x, y};
8866  // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
8867  // In Win64 they are assigned to a hidden first argument.
8868  return result;
8869 }
8870 #else
8871 typedef uint64_t ObjectPair;
8872 static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
8873  return reinterpret_cast<uint32_t>(x) |
8874  (reinterpret_cast<ObjectPair>(y) << 32);
8875 }
8876 #endif
8877 
8878 
8879 static inline MaybeObject* Unhole(Heap* heap,
8880  MaybeObject* x,
8881  PropertyAttributes attributes) {
8882  ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
8883  USE(attributes);
8884  return x->IsTheHole() ? heap->undefined_value() : x;
8885 }
8886 
8887 
8888 static Object* ComputeReceiverForNonGlobal(Isolate* isolate,
8889  JSObject* holder) {
8890  ASSERT(!holder->IsGlobalObject());
8891  Context* top = isolate->context();
8892  // Get the context extension function.
8893  JSFunction* context_extension_function =
8894  top->global_context()->context_extension_function();
8895  // If the holder isn't a context extension object, we just return it
8896  // as the receiver. This allows arguments objects to be used as
8897  // receivers, but only if they are put in the context scope chain
8898  // explicitly via a with-statement.
8899  Object* constructor = holder->map()->constructor();
8900  if (constructor != context_extension_function) return holder;
8901  // Fall back to using the global object as the implicit receiver if
8902  // the property turns out to be a local variable allocated in a
8903  // context extension object - introduced via eval. Implicit global
8904  // receivers are indicated with the hole value.
8905  return isolate->heap()->the_hole_value();
8906 }
8907 
8908 
8909 static ObjectPair LoadContextSlotHelper(Arguments args,
8910  Isolate* isolate,
8911  bool throw_error) {
8912  HandleScope scope(isolate);
8913  ASSERT_EQ(2, args.length());
8914 
8915  if (!args[0]->IsContext() || !args[1]->IsString()) {
8916  return MakePair(isolate->ThrowIllegalOperation(), NULL);
8917  }
8918  Handle<Context> context = args.at<Context>(0);
8919  Handle<String> name = args.at<String>(1);
8920 
8921  int index;
8922  PropertyAttributes attributes;
8924  BindingFlags binding_flags;
8925  Handle<Object> holder = context->Lookup(name,
8926  flags,
8927  &index,
8928  &attributes,
8929  &binding_flags);
8930 
8931  // If the index is non-negative, the slot has been found in a context.
8932  if (index >= 0) {
8933  ASSERT(holder->IsContext());
8934  // If the "property" we were looking for is a local variable, the
8935  // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
8936  //
8937  // Use the hole as the receiver to signal that the receiver is implicit
8938  // and that the global receiver should be used (as distinguished from an
8939  // explicit receiver that happens to be a global object).
8940  Handle<Object> receiver = isolate->factory()->the_hole_value();
8941  Object* value = Context::cast(*holder)->get(index);
8942  // Check for uninitialized bindings.
8943  switch (binding_flags) {
8946  if (value->IsTheHole()) {
8947  Handle<Object> reference_error =
8948  isolate->factory()->NewReferenceError("not_defined",
8949  HandleVector(&name, 1));
8950  return MakePair(isolate->Throw(*reference_error), NULL);
8951  }
8952  // FALLTHROUGH
8956  ASSERT(!value->IsTheHole());
8957  return MakePair(value, *receiver);
8959  return MakePair(Unhole(isolate->heap(), value, attributes), *receiver);
8960  case MISSING_BINDING:
8961  UNREACHABLE();
8962  return MakePair(NULL, NULL);
8963  }
8964  }
8965 
8966  // Otherwise, if the slot was found the holder is a context extension
8967  // object, subject of a with, or a global object. We read the named
8968  // property from it.
8969  if (!holder.is_null()) {
8970  Handle<JSObject> object = Handle<JSObject>::cast(holder);
8971  ASSERT(object->HasProperty(*name));
8972  // GetProperty below can cause GC.
8973  Handle<Object> receiver_handle(object->IsGlobalObject()
8974  ? GlobalObject::cast(*object)->global_receiver()
8975  : ComputeReceiverForNonGlobal(isolate, *object));
8976 
8977  // No need to unhole the value here. This is taken care of by the
8978  // GetProperty function.
8979  MaybeObject* value = object->GetProperty(*name);
8980  return MakePair(value, *receiver_handle);
8981  }
8982 
8983  if (throw_error) {
8984  // The property doesn't exist - throw exception.
8985  Handle<Object> reference_error =
8986  isolate->factory()->NewReferenceError("not_defined",
8987  HandleVector(&name, 1));
8988  return MakePair(isolate->Throw(*reference_error), NULL);
8989  } else {
8990  // The property doesn't exist - return undefined.
8991  return MakePair(isolate->heap()->undefined_value(),
8992  isolate->heap()->undefined_value());
8993  }
8994 }
8995 
8996 
8997 RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlot) {
8998  return LoadContextSlotHelper(args, isolate, true);
8999 }
9000 
9001 
9002 RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlotNoReferenceError) {
9003  return LoadContextSlotHelper(args, isolate, false);
9004 }
9005 
9006 
9007 RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreContextSlot) {
9008  HandleScope scope(isolate);
9009  ASSERT(args.length() == 4);
9010 
9011  Handle<Object> value(args[0], isolate);
9012  CONVERT_ARG_HANDLE_CHECKED(Context, context, 1);
9014  CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
9015  StrictModeFlag strict_mode = (language_mode == CLASSIC_MODE)
9017 
9018  int index;
9019  PropertyAttributes attributes;
9021  BindingFlags binding_flags;
9022  Handle<Object> holder = context->Lookup(name,
9023  flags,
9024  &index,
9025  &attributes,
9026  &binding_flags);
9027 
9028  if (index >= 0) {
9029  // The property was found in a context slot.
9030  Handle<Context> context = Handle<Context>::cast(holder);
9031  if (binding_flags == MUTABLE_CHECK_INITIALIZED &&
9032  context->get(index)->IsTheHole()) {
9033  Handle<Object> error =
9034  isolate->factory()->NewReferenceError("not_defined",
9035  HandleVector(&name, 1));
9036  return isolate->Throw(*error);
9037  }
9038  // Ignore if read_only variable.
9039  if ((attributes & READ_ONLY) == 0) {
9040  // Context is a fixed array and set cannot fail.
9041  context->set(index, *value);
9042  } else if (strict_mode == kStrictMode) {
9043  // Setting read only property in strict mode.
9044  Handle<Object> error =
9045  isolate->factory()->NewTypeError("strict_cannot_assign",
9046  HandleVector(&name, 1));
9047  return isolate->Throw(*error);
9048  }
9049  return *value;
9050  }
9051 
9052  // Slow case: The property is not in a context slot. It is either in a
9053  // context extension object, a property of the subject of a with, or a
9054  // property of the global object.
9055  Handle<JSObject> object;
9056 
9057  if (!holder.is_null()) {
9058  // The property exists on the holder.
9059  object = Handle<JSObject>::cast(holder);
9060  } else {
9061  // The property was not found.
9062  ASSERT(attributes == ABSENT);
9063 
9064  if (strict_mode == kStrictMode) {
9065  // Throw in strict mode (assignment to undefined variable).
9066  Handle<Object> error =
9067  isolate->factory()->NewReferenceError(
9068  "not_defined", HandleVector(&name, 1));
9069  return isolate->Throw(*error);
9070  }
9071  // In non-strict mode, the property is added to the global object.
9072  attributes = NONE;
9073  object = Handle<JSObject>(isolate->context()->global());
9074  }
9075 
9076  // Set the property if it's not read only or doesn't yet exist.
9077  if ((attributes & READ_ONLY) == 0 ||
9078  (object->GetLocalPropertyAttribute(*name) == ABSENT)) {
9080  isolate,
9081  JSReceiver::SetProperty(object, name, value, NONE, strict_mode));
9082  } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) {
9083  // Setting read only property in strict mode.
9084  Handle<Object> error =
9085  isolate->factory()->NewTypeError(
9086  "strict_cannot_assign", HandleVector(&name, 1));
9087  return isolate->Throw(*error);
9088  }
9089  return *value;
9090 }
9091 
9092 
9093 RUNTIME_FUNCTION(MaybeObject*, Runtime_Throw) {
9094  HandleScope scope(isolate);
9095  ASSERT(args.length() == 1);
9096 
9097  return isolate->Throw(args[0]);
9098 }
9099 
9100 
9101 RUNTIME_FUNCTION(MaybeObject*, Runtime_ReThrow) {
9102  HandleScope scope(isolate);
9103  ASSERT(args.length() == 1);
9104 
9105  return isolate->ReThrow(args[0]);
9106 }
9107 
9108 
9109 RUNTIME_FUNCTION(MaybeObject*, Runtime_PromoteScheduledException) {
9110  ASSERT_EQ(0, args.length());
9111  return isolate->PromoteScheduledException();
9112 }
9113 
9114 
9115 RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowReferenceError) {
9116  HandleScope scope(isolate);
9117  ASSERT(args.length() == 1);
9118 
9119  Handle<Object> name(args[0], isolate);
9120  Handle<Object> reference_error =
9121  isolate->factory()->NewReferenceError("not_defined",
9122  HandleVector(&name, 1));
9123  return isolate->Throw(*reference_error);
9124 }
9125 
9126 
9127 RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) {
9128  ASSERT(args.length() == 0);
9129 
9130  // First check if this is a real stack overflow.
9131  if (isolate->stack_guard()->IsStackOverflow()) {
9132  NoHandleAllocation na;
9133  return isolate->StackOverflow();
9134  }
9135 
9136  return Execution::HandleStackGuardInterrupt(isolate);
9137 }
9138 
9139 
9140 RUNTIME_FUNCTION(MaybeObject*, Runtime_Interrupt) {
9141  ASSERT(args.length() == 0);
9142  return Execution::HandleStackGuardInterrupt(isolate);
9143 }
9144 
9145 
9146 static int StackSize() {
9147  int n = 0;
9148  for (JavaScriptFrameIterator it; !it.done(); it.Advance()) n++;
9149  return n;
9150 }
9151 
9152 
9153 static void PrintTransition(Object* result) {
9154  // indentation
9155  { const int nmax = 80;
9156  int n = StackSize();
9157  if (n <= nmax)
9158  PrintF("%4d:%*s", n, n, "");
9159  else
9160  PrintF("%4d:%*s", n, nmax, "...");
9161  }
9162 
9163  if (result == NULL) {
9164  JavaScriptFrame::PrintTop(stdout, true, false);
9165  PrintF(" {\n");
9166  } else {
9167  // function result
9168  PrintF("} -> ");
9169  result->ShortPrint();
9170  PrintF("\n");
9171  }
9172 }
9173 
9174 
9175 RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceEnter) {
9176  ASSERT(args.length() == 0);
9177  NoHandleAllocation ha;
9178  PrintTransition(NULL);
9179  return isolate->heap()->undefined_value();
9180 }
9181 
9182 
9183 RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceExit) {
9184  NoHandleAllocation ha;
9185  PrintTransition(args[0]);
9186  return args[0]; // return TOS
9187 }
9188 
9189 
9190 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrint) {
9191  NoHandleAllocation ha;
9192  ASSERT(args.length() == 1);
9193 
9194 #ifdef DEBUG
9195  if (args[0]->IsString()) {
9196  // If we have a string, assume it's a code "marker"
9197  // and print some interesting cpu debugging info.
9198  JavaScriptFrameIterator it(isolate);
9199  JavaScriptFrame* frame = it.frame();
9200  PrintF("fp = %p, sp = %p, caller_sp = %p: ",
9201  frame->fp(), frame->sp(), frame->caller_sp());
9202  } else {
9203  PrintF("DebugPrint: ");
9204  }
9205  args[0]->Print();
9206  if (args[0]->IsHeapObject()) {
9207  PrintF("\n");
9208  HeapObject::cast(args[0])->map()->Print();
9209  }
9210 #else
9211  // ShortPrint is available in release mode. Print is not.
9212  args[0]->ShortPrint();
9213 #endif
9214  PrintF("\n");
9215  Flush();
9216 
9217  return args[0]; // return TOS
9218 }
9219 
9220 
9221 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugTrace) {
9222  ASSERT(args.length() == 0);
9223  NoHandleAllocation ha;
9224  isolate->PrintStack();
9225  return isolate->heap()->undefined_value();
9226 }
9227 
9228 
9229 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateCurrentTime) {
9230  NoHandleAllocation ha;
9231  ASSERT(args.length() == 0);
9232 
9233  // According to ECMA-262, section 15.9.1, page 117, the precision of
9234  // the number in a Date object representing a particular instant in
9235  // time is milliseconds. Therefore, we floor the result of getting
9236  // the OS time.
9237  double millis = floor(OS::TimeCurrentMillis());
9238  return isolate->heap()->NumberFromDouble(millis);
9239 }
9240 
9241 
9242 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateParseString) {
9243  HandleScope scope(isolate);
9244  ASSERT(args.length() == 2);
9245 
9247  FlattenString(str);
9248 
9249  CONVERT_ARG_HANDLE_CHECKED(JSArray, output, 1);
9250 
9251  MaybeObject* maybe_result_array =
9252  output->EnsureCanContainHeapObjectElements();
9253  if (maybe_result_array->IsFailure()) return maybe_result_array;
9254  RUNTIME_ASSERT(output->HasFastObjectElements());
9255 
9256  AssertNoAllocation no_allocation;
9257 
9258  FixedArray* output_array = FixedArray::cast(output->elements());
9259  RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
9260  bool result;
9261  String::FlatContent str_content = str->GetFlatContent();
9262  if (str_content.IsAscii()) {
9263  result = DateParser::Parse(str_content.ToAsciiVector(),
9264  output_array,
9265  isolate->unicode_cache());
9266  } else {
9267  ASSERT(str_content.IsTwoByte());
9268  result = DateParser::Parse(str_content.ToUC16Vector(),
9269  output_array,
9270  isolate->unicode_cache());
9271  }
9272 
9273  if (result) {
9274  return *output;
9275  } else {
9276  return isolate->heap()->null_value();
9277  }
9278 }
9279 
9280 
9281 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateLocalTimezone) {
9282  NoHandleAllocation ha;
9283  ASSERT(args.length() == 1);
9284 
9286  int64_t time = isolate->date_cache()->EquivalentTime(static_cast<int64_t>(x));
9287  const char* zone = OS::LocalTimezone(static_cast<double>(time));
9288  return isolate->heap()->AllocateStringFromUtf8(CStrVector(zone));
9289 }
9290 
9291 
9292 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateToUTC) {
9293  NoHandleAllocation ha;
9294  ASSERT(args.length() == 1);
9295 
9297  int64_t time = isolate->date_cache()->ToUTC(static_cast<int64_t>(x));
9298 
9299  return isolate->heap()->NumberFromDouble(static_cast<double>(time));
9300 }
9301 
9302 
9303 RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalReceiver) {
9304  ASSERT(args.length() == 1);
9305  Object* global = args[0];
9306  if (!global->IsJSGlobalObject()) return isolate->heap()->null_value();
9307  return JSGlobalObject::cast(global)->global_receiver();
9308 }
9309 
9310 
9311 RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) {
9312  HandleScope scope(isolate);
9313  ASSERT_EQ(1, args.length());
9314  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9315 
9316  Zone* zone = isolate->zone();
9317  source = Handle<String>(source->TryFlattenGetString());
9318  // Optimized fast case where we only have ASCII characters.
9319  Handle<Object> result;
9320  if (source->IsSeqAsciiString()) {
9321  result = JsonParser<true>::Parse(source, zone);
9322  } else {
9323  result = JsonParser<false>::Parse(source, zone);
9324  }
9325  if (result.is_null()) {
9326  // Syntax error or stack overflow in scanner.
9327  ASSERT(isolate->has_pending_exception());
9328  return Failure::Exception();
9329  }
9330  return *result;
9331 }
9332 
9333 
9335  Handle<Context> context) {
9336  ASSERT(context->allow_code_gen_from_strings()->IsFalse());
9337  // Check with callback if set.
9339  isolate->allow_code_gen_callback();
9340  if (callback == NULL) {
9341  // No callback set and code generation disallowed.
9342  return false;
9343  } else {
9344  // Callback set. Let it decide if code generation is allowed.
9345  VMState state(isolate, EXTERNAL);
9346  return callback(v8::Utils::ToLocal(context));
9347  }
9348 }
9349 
9350 
9351 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
9352  HandleScope scope(isolate);
9353  ASSERT_EQ(1, args.length());
9354  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9355 
9356  // Extract global context.
9357  Handle<Context> context(isolate->context()->global_context());
9358 
9359  // Check if global context allows code generation from
9360  // strings. Throw an exception if it doesn't.
9361  if (context->allow_code_gen_from_strings()->IsFalse() &&
9362  !CodeGenerationFromStringsAllowed(isolate, context)) {
9363  return isolate->Throw(*isolate->factory()->NewError(
9364  "code_gen_from_strings", HandleVector<Object>(NULL, 0)));
9365  }
9366 
9367  // Compile source string in the global context.
9369  source, context, true, CLASSIC_MODE, RelocInfo::kNoPosition);
9370  if (shared.is_null()) return Failure::Exception();
9371  Handle<JSFunction> fun =
9372  isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
9373  context,
9374  NOT_TENURED);
9375  return *fun;
9376 }
9377 
9378 
9379 static ObjectPair CompileGlobalEval(Isolate* isolate,
9380  Handle<String> source,
9381  Handle<Object> receiver,
9382  LanguageMode language_mode,
9383  int scope_position) {
9384  Handle<Context> context = Handle<Context>(isolate->context());
9385  Handle<Context> global_context = Handle<Context>(context->global_context());
9386 
9387  // Check if global context allows code generation from
9388  // strings. Throw an exception if it doesn't.
9389  if (global_context->allow_code_gen_from_strings()->IsFalse() &&
9390  !CodeGenerationFromStringsAllowed(isolate, global_context)) {
9391  isolate->Throw(*isolate->factory()->NewError(
9392  "code_gen_from_strings", HandleVector<Object>(NULL, 0)));
9393  return MakePair(Failure::Exception(), NULL);
9394  }
9395 
9396  // Deal with a normal eval call with a string argument. Compile it
9397  // and return the compiled function bound in the local context.
9398  Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
9399  source,
9400  Handle<Context>(isolate->context()),
9401  context->IsGlobalContext(),
9402  language_mode,
9403  scope_position);
9404  if (shared.is_null()) return MakePair(Failure::Exception(), NULL);
9405  Handle<JSFunction> compiled =
9406  isolate->factory()->NewFunctionFromSharedFunctionInfo(
9407  shared, context, NOT_TENURED);
9408  return MakePair(*compiled, *receiver);
9409 }
9410 
9411 
9412 RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
9413  ASSERT(args.length() == 5);
9414 
9415  HandleScope scope(isolate);
9416  Handle<Object> callee = args.at<Object>(0);
9417 
9418  // If "eval" didn't refer to the original GlobalEval, it's not a
9419  // direct call to eval.
9420  // (And even if it is, but the first argument isn't a string, just let
9421  // execution default to an indirect call to eval, which will also return
9422  // the first argument without doing anything).
9423  if (*callee != isolate->global_context()->global_eval_fun() ||
9424  !args[1]->IsString()) {
9425  return MakePair(*callee, isolate->heap()->the_hole_value());
9426  }
9427 
9428  CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
9429  ASSERT(args[4]->IsSmi());
9430  return CompileGlobalEval(isolate,
9431  args.at<String>(1),
9432  args.at<Object>(2),
9433  language_mode,
9434  args.smi_at(4));
9435 }
9436 
9437 
9438 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNewFunctionAttributes) {
9439  // This utility adjusts the property attributes for newly created Function
9440  // object ("new Function(...)") by changing the map.
9441  // All it does is changing the prototype property to enumerable
9442  // as specified in ECMA262, 15.3.5.2.
9443  HandleScope scope(isolate);
9444  ASSERT(args.length() == 1);
9446 
9447  Handle<Map> map = func->shared()->is_classic_mode()
9448  ? isolate->function_instance_map()
9449  : isolate->strict_mode_function_instance_map();
9450 
9451  ASSERT(func->map()->instance_type() == map->instance_type());
9452  ASSERT(func->map()->instance_size() == map->instance_size());
9453  func->set_map(*map);
9454  return *func;
9455 }
9456 
9457 
9458 RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInNewSpace) {
9459  // Allocate a block of memory in NewSpace (filled with a filler).
9460  // Use as fallback for allocation in generated code when NewSpace
9461  // is full.
9462  ASSERT(args.length() == 1);
9463  CONVERT_ARG_HANDLE_CHECKED(Smi, size_smi, 0);
9464  int size = size_smi->value();
9466  RUNTIME_ASSERT(size > 0);
9467  Heap* heap = isolate->heap();
9468  const int kMinFreeNewSpaceAfterGC = heap->InitialSemiSpaceSize() * 3/4;
9469  RUNTIME_ASSERT(size <= kMinFreeNewSpaceAfterGC);
9470  Object* allocation;
9471  { MaybeObject* maybe_allocation = heap->new_space()->AllocateRaw(size);
9472  if (maybe_allocation->ToObject(&allocation)) {
9473  heap->CreateFillerObjectAt(HeapObject::cast(allocation)->address(), size);
9474  }
9475  return maybe_allocation;
9476  }
9477 }
9478 
9479 
9480 // Push an object unto an array of objects if it is not already in the
9481 // array. Returns true if the element was pushed on the stack and
9482 // false otherwise.
9483 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) {
9484  ASSERT(args.length() == 2);
9485  CONVERT_ARG_CHECKED(JSArray, array, 0);
9486  CONVERT_ARG_CHECKED(JSObject, element, 1);
9487  RUNTIME_ASSERT(array->HasFastSmiOrObjectElements());
9488  int length = Smi::cast(array->length())->value();
9489  FixedArray* elements = FixedArray::cast(array->elements());
9490  for (int i = 0; i < length; i++) {
9491  if (elements->get(i) == element) return isolate->heap()->false_value();
9492  }
9493  Object* obj;
9494  // Strict not needed. Used for cycle detection in Array join implementation.
9495  { MaybeObject* maybe_obj =
9496  array->SetFastElement(length, element, kNonStrictMode, true);
9497  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9498  }
9499  return isolate->heap()->true_value();
9500 }
9501 
9502 
9515  public:
9517  Handle<FixedArray> storage,
9518  bool fast_elements) :
9519  isolate_(isolate),
9520  storage_(Handle<FixedArray>::cast(
9521  isolate->global_handles()->Create(*storage))),
9522  index_offset_(0u),
9523  fast_elements_(fast_elements) { }
9524 
9526  clear_storage();
9527  }
9528 
9529  void visit(uint32_t i, Handle<Object> elm) {
9530  if (i >= JSObject::kMaxElementCount - index_offset_) return;
9531  uint32_t index = index_offset_ + i;
9532 
9533  if (fast_elements_) {
9534  if (index < static_cast<uint32_t>(storage_->length())) {
9535  storage_->set(index, *elm);
9536  return;
9537  }
9538  // Our initial estimate of length was foiled, possibly by
9539  // getters on the arrays increasing the length of later arrays
9540  // during iteration.
9541  // This shouldn't happen in anything but pathological cases.
9542  SetDictionaryMode(index);
9543  // Fall-through to dictionary mode.
9544  }
9545  ASSERT(!fast_elements_);
9547  SeededNumberDictionary::cast(*storage_));
9549  isolate_->factory()->DictionaryAtNumberPut(dict, index, elm);
9550  if (!result.is_identical_to(dict)) {
9551  // Dictionary needed to grow.
9552  clear_storage();
9553  set_storage(*result);
9554  }
9555 }
9556 
9557  void increase_index_offset(uint32_t delta) {
9558  if (JSObject::kMaxElementCount - index_offset_ < delta) {
9559  index_offset_ = JSObject::kMaxElementCount;
9560  } else {
9561  index_offset_ += delta;
9562  }
9563  }
9564 
9566  Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
9567  Handle<Object> length =
9568  isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
9569  Handle<Map> map;
9570  if (fast_elements_) {
9571  map = isolate_->factory()->GetElementsTransitionMap(array,
9573  } else {
9574  map = isolate_->factory()->GetElementsTransitionMap(array,
9576  }
9577  array->set_map(*map);
9578  array->set_length(*length);
9579  array->set_elements(*storage_);
9580  return array;
9581  }
9582 
9583  private:
9584  // Convert storage to dictionary mode.
9585  void SetDictionaryMode(uint32_t index) {
9586  ASSERT(fast_elements_);
9587  Handle<FixedArray> current_storage(*storage_);
9588  Handle<SeededNumberDictionary> slow_storage(
9589  isolate_->factory()->NewSeededNumberDictionary(
9590  current_storage->length()));
9591  uint32_t current_length = static_cast<uint32_t>(current_storage->length());
9592  for (uint32_t i = 0; i < current_length; i++) {
9593  HandleScope loop_scope;
9594  Handle<Object> element(current_storage->get(i));
9595  if (!element->IsTheHole()) {
9596  Handle<SeededNumberDictionary> new_storage =
9597  isolate_->factory()->DictionaryAtNumberPut(slow_storage, i, element);
9598  if (!new_storage.is_identical_to(slow_storage)) {
9599  slow_storage = loop_scope.CloseAndEscape(new_storage);
9600  }
9601  }
9602  }
9603  clear_storage();
9604  set_storage(*slow_storage);
9605  fast_elements_ = false;
9606  }
9607 
9608  inline void clear_storage() {
9609  isolate_->global_handles()->Destroy(
9610  Handle<Object>::cast(storage_).location());
9611  }
9612 
9613  inline void set_storage(FixedArray* storage) {
9614  storage_ = Handle<FixedArray>::cast(
9615  isolate_->global_handles()->Create(storage));
9616  }
9617 
9618  Isolate* isolate_;
9619  Handle<FixedArray> storage_; // Always a global handle.
9620  // Index after last seen index. Always less than or equal to
9621  // JSObject::kMaxElementCount.
9622  uint32_t index_offset_;
9623  bool fast_elements_;
9624 };
9625 
9626 
9627 static uint32_t EstimateElementCount(Handle<JSArray> array) {
9628  uint32_t length = static_cast<uint32_t>(array->length()->Number());
9629  int element_count = 0;
9630  switch (array->GetElementsKind()) {
9631  case FAST_SMI_ELEMENTS:
9633  case FAST_ELEMENTS:
9634  case FAST_HOLEY_ELEMENTS: {
9635  // Fast elements can't have lengths that are not representable by
9636  // a 32-bit signed integer.
9637  ASSERT(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
9638  int fast_length = static_cast<int>(length);
9639  Handle<FixedArray> elements(FixedArray::cast(array->elements()));
9640  for (int i = 0; i < fast_length; i++) {
9641  if (!elements->get(i)->IsTheHole()) element_count++;
9642  }
9643  break;
9644  }
9645  case FAST_DOUBLE_ELEMENTS:
9647  // TODO(1810): Decide if it's worthwhile to implement this.
9648  UNREACHABLE();
9649  break;
9650  case DICTIONARY_ELEMENTS: {
9651  Handle<SeededNumberDictionary> dictionary(
9652  SeededNumberDictionary::cast(array->elements()));
9653  int capacity = dictionary->Capacity();
9654  for (int i = 0; i < capacity; i++) {
9655  Handle<Object> key(dictionary->KeyAt(i));
9656  if (dictionary->IsKey(*key)) {
9657  element_count++;
9658  }
9659  }
9660  break;
9661  }
9667  case EXTERNAL_INT_ELEMENTS:
9672  // External arrays are always dense.
9673  return length;
9674  }
9675  // As an estimate, we assume that the prototype doesn't contain any
9676  // inherited elements.
9677  return element_count;
9678 }
9679 
9680 
9681 
9682 template<class ExternalArrayClass, class ElementType>
9683 static void IterateExternalArrayElements(Isolate* isolate,
9684  Handle<JSObject> receiver,
9685  bool elements_are_ints,
9686  bool elements_are_guaranteed_smis,
9687  ArrayConcatVisitor* visitor) {
9688  Handle<ExternalArrayClass> array(
9689  ExternalArrayClass::cast(receiver->elements()));
9690  uint32_t len = static_cast<uint32_t>(array->length());
9691 
9692  ASSERT(visitor != NULL);
9693  if (elements_are_ints) {
9694  if (elements_are_guaranteed_smis) {
9695  for (uint32_t j = 0; j < len; j++) {
9696  HandleScope loop_scope;
9697  Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get_scalar(j))));
9698  visitor->visit(j, e);
9699  }
9700  } else {
9701  for (uint32_t j = 0; j < len; j++) {
9702  HandleScope loop_scope;
9703  int64_t val = static_cast<int64_t>(array->get_scalar(j));
9704  if (Smi::IsValid(static_cast<intptr_t>(val))) {
9705  Handle<Smi> e(Smi::FromInt(static_cast<int>(val)));
9706  visitor->visit(j, e);
9707  } else {
9708  Handle<Object> e =
9709  isolate->factory()->NewNumber(static_cast<ElementType>(val));
9710  visitor->visit(j, e);
9711  }
9712  }
9713  }
9714  } else {
9715  for (uint32_t j = 0; j < len; j++) {
9716  HandleScope loop_scope(isolate);
9717  Handle<Object> e = isolate->factory()->NewNumber(array->get_scalar(j));
9718  visitor->visit(j, e);
9719  }
9720  }
9721 }
9722 
9723 
9724 // Used for sorting indices in a List<uint32_t>.
9725 static int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
9726  uint32_t a = *ap;
9727  uint32_t b = *bp;
9728  return (a == b) ? 0 : (a < b) ? -1 : 1;
9729 }
9730 
9731 
9732 static void CollectElementIndices(Handle<JSObject> object,
9733  uint32_t range,
9734  List<uint32_t>* indices) {
9735  ElementsKind kind = object->GetElementsKind();
9736  switch (kind) {
9737  case FAST_SMI_ELEMENTS:
9738  case FAST_ELEMENTS:
9740  case FAST_HOLEY_ELEMENTS: {
9741  Handle<FixedArray> elements(FixedArray::cast(object->elements()));
9742  uint32_t length = static_cast<uint32_t>(elements->length());
9743  if (range < length) length = range;
9744  for (uint32_t i = 0; i < length; i++) {
9745  if (!elements->get(i)->IsTheHole()) {
9746  indices->Add(i);
9747  }
9748  }
9749  break;
9750  }
9752  case FAST_DOUBLE_ELEMENTS: {
9753  // TODO(1810): Decide if it's worthwhile to implement this.
9754  UNREACHABLE();
9755  break;
9756  }
9757  case DICTIONARY_ELEMENTS: {
9758  Handle<SeededNumberDictionary> dict(
9759  SeededNumberDictionary::cast(object->elements()));
9760  uint32_t capacity = dict->Capacity();
9761  for (uint32_t j = 0; j < capacity; j++) {
9762  HandleScope loop_scope;
9763  Handle<Object> k(dict->KeyAt(j));
9764  if (dict->IsKey(*k)) {
9765  ASSERT(k->IsNumber());
9766  uint32_t index = static_cast<uint32_t>(k->Number());
9767  if (index < range) {
9768  indices->Add(index);
9769  }
9770  }
9771  }
9772  break;
9773  }
9774  default: {
9775  int dense_elements_length;
9776  switch (kind) {
9777  case EXTERNAL_PIXEL_ELEMENTS: {
9778  dense_elements_length =
9779  ExternalPixelArray::cast(object->elements())->length();
9780  break;
9781  }
9782  case EXTERNAL_BYTE_ELEMENTS: {
9783  dense_elements_length =
9784  ExternalByteArray::cast(object->elements())->length();
9785  break;
9786  }
9788  dense_elements_length =
9789  ExternalUnsignedByteArray::cast(object->elements())->length();
9790  break;
9791  }
9792  case EXTERNAL_SHORT_ELEMENTS: {
9793  dense_elements_length =
9794  ExternalShortArray::cast(object->elements())->length();
9795  break;
9796  }
9798  dense_elements_length =
9799  ExternalUnsignedShortArray::cast(object->elements())->length();
9800  break;
9801  }
9802  case EXTERNAL_INT_ELEMENTS: {
9803  dense_elements_length =
9804  ExternalIntArray::cast(object->elements())->length();
9805  break;
9806  }
9808  dense_elements_length =
9809  ExternalUnsignedIntArray::cast(object->elements())->length();
9810  break;
9811  }
9812  case EXTERNAL_FLOAT_ELEMENTS: {
9813  dense_elements_length =
9814  ExternalFloatArray::cast(object->elements())->length();
9815  break;
9816  }
9817  case EXTERNAL_DOUBLE_ELEMENTS: {
9818  dense_elements_length =
9819  ExternalDoubleArray::cast(object->elements())->length();
9820  break;
9821  }
9822  default:
9823  UNREACHABLE();
9824  dense_elements_length = 0;
9825  break;
9826  }
9827  uint32_t length = static_cast<uint32_t>(dense_elements_length);
9828  if (range <= length) {
9829  length = range;
9830  // We will add all indices, so we might as well clear it first
9831  // and avoid duplicates.
9832  indices->Clear();
9833  }
9834  for (uint32_t i = 0; i < length; i++) {
9835  indices->Add(i);
9836  }
9837  if (length == range) return; // All indices accounted for already.
9838  break;
9839  }
9840  }
9841 
9842  Handle<Object> prototype(object->GetPrototype());
9843  if (prototype->IsJSObject()) {
9844  // The prototype will usually have no inherited element indices,
9845  // but we have to check.
9846  CollectElementIndices(Handle<JSObject>::cast(prototype), range, indices);
9847  }
9848 }
9849 
9850 
9861 static bool IterateElements(Isolate* isolate,
9862  Handle<JSArray> receiver,
9863  ArrayConcatVisitor* visitor) {
9864  uint32_t length = static_cast<uint32_t>(receiver->length()->Number());
9865  switch (receiver->GetElementsKind()) {
9866  case FAST_SMI_ELEMENTS:
9867  case FAST_ELEMENTS:
9869  case FAST_HOLEY_ELEMENTS: {
9870  // Run through the elements FixedArray and use HasElement and GetElement
9871  // to check the prototype for missing elements.
9872  Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
9873  int fast_length = static_cast<int>(length);
9874  ASSERT(fast_length <= elements->length());
9875  for (int j = 0; j < fast_length; j++) {
9876  HandleScope loop_scope(isolate);
9877  Handle<Object> element_value(elements->get(j), isolate);
9878  if (!element_value->IsTheHole()) {
9879  visitor->visit(j, element_value);
9880  } else if (receiver->HasElement(j)) {
9881  // Call GetElement on receiver, not its prototype, or getters won't
9882  // have the correct receiver.
9883  element_value = Object::GetElement(receiver, j);
9884  RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
9885  visitor->visit(j, element_value);
9886  }
9887  }
9888  break;
9889  }
9891  case FAST_DOUBLE_ELEMENTS: {
9892  // TODO(1810): Decide if it's worthwhile to implement this.
9893  UNREACHABLE();
9894  break;
9895  }
9896  case DICTIONARY_ELEMENTS: {
9897  Handle<SeededNumberDictionary> dict(receiver->element_dictionary());
9898  List<uint32_t> indices(dict->Capacity() / 2);
9899  // Collect all indices in the object and the prototypes less
9900  // than length. This might introduce duplicates in the indices list.
9901  CollectElementIndices(receiver, length, &indices);
9902  indices.Sort(&compareUInt32);
9903  int j = 0;
9904  int n = indices.length();
9905  while (j < n) {
9906  HandleScope loop_scope;
9907  uint32_t index = indices[j];
9908  Handle<Object> element = Object::GetElement(receiver, index);
9909  RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element, false);
9910  visitor->visit(index, element);
9911  // Skip to next different index (i.e., omit duplicates).
9912  do {
9913  j++;
9914  } while (j < n && indices[j] == index);
9915  }
9916  break;
9917  }
9918  case EXTERNAL_PIXEL_ELEMENTS: {
9919  Handle<ExternalPixelArray> pixels(ExternalPixelArray::cast(
9920  receiver->elements()));
9921  for (uint32_t j = 0; j < length; j++) {
9922  Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)));
9923  visitor->visit(j, e);
9924  }
9925  break;
9926  }
9927  case EXTERNAL_BYTE_ELEMENTS: {
9928  IterateExternalArrayElements<ExternalByteArray, int8_t>(
9929  isolate, receiver, true, true, visitor);
9930  break;
9931  }
9933  IterateExternalArrayElements<ExternalUnsignedByteArray, uint8_t>(
9934  isolate, receiver, true, true, visitor);
9935  break;
9936  }
9937  case EXTERNAL_SHORT_ELEMENTS: {
9938  IterateExternalArrayElements<ExternalShortArray, int16_t>(
9939  isolate, receiver, true, true, visitor);
9940  break;
9941  }
9943  IterateExternalArrayElements<ExternalUnsignedShortArray, uint16_t>(
9944  isolate, receiver, true, true, visitor);
9945  break;
9946  }
9947  case EXTERNAL_INT_ELEMENTS: {
9948  IterateExternalArrayElements<ExternalIntArray, int32_t>(
9949  isolate, receiver, true, false, visitor);
9950  break;
9951  }
9953  IterateExternalArrayElements<ExternalUnsignedIntArray, uint32_t>(
9954  isolate, receiver, true, false, visitor);
9955  break;
9956  }
9957  case EXTERNAL_FLOAT_ELEMENTS: {
9958  IterateExternalArrayElements<ExternalFloatArray, float>(
9959  isolate, receiver, false, false, visitor);
9960  break;
9961  }
9962  case EXTERNAL_DOUBLE_ELEMENTS: {
9963  IterateExternalArrayElements<ExternalDoubleArray, double>(
9964  isolate, receiver, false, false, visitor);
9965  break;
9966  }
9967  default:
9968  UNREACHABLE();
9969  break;
9970  }
9971  visitor->increase_index_offset(length);
9972  return true;
9973 }
9974 
9975 
9982 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) {
9983  ASSERT(args.length() == 1);
9984  HandleScope handle_scope(isolate);
9985 
9986  CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 0);
9987  int argument_count = static_cast<int>(arguments->length()->Number());
9988  RUNTIME_ASSERT(arguments->HasFastObjectElements());
9989  Handle<FixedArray> elements(FixedArray::cast(arguments->elements()));
9990 
9991  // Pass 1: estimate the length and number of elements of the result.
9992  // The actual length can be larger if any of the arguments have getters
9993  // that mutate other arguments (but will otherwise be precise).
9994  // The number of elements is precise if there are no inherited elements.
9995 
9996  uint32_t estimate_result_length = 0;
9997  uint32_t estimate_nof_elements = 0;
9998  {
9999  for (int i = 0; i < argument_count; i++) {
10000  HandleScope loop_scope;
10001  Handle<Object> obj(elements->get(i));
10002  uint32_t length_estimate;
10003  uint32_t element_estimate;
10004  if (obj->IsJSArray()) {
10006  // TODO(1810): Find out if it's worthwhile to properly support
10007  // arbitrary ElementsKinds. For now, pessimistically transition to
10008  // FAST_*_ELEMENTS.
10009  if (array->HasFastDoubleElements()) {
10010  ElementsKind to_kind = FAST_ELEMENTS;
10011  if (array->HasFastHoleyElements()) {
10012  to_kind = FAST_HOLEY_ELEMENTS;
10013  }
10014  array = Handle<JSArray>::cast(
10015  JSObject::TransitionElementsKind(array, to_kind));
10016  }
10017  length_estimate =
10018  static_cast<uint32_t>(array->length()->Number());
10019  element_estimate =
10020  EstimateElementCount(array);
10021  } else {
10022  length_estimate = 1;
10023  element_estimate = 1;
10024  }
10025  // Avoid overflows by capping at kMaxElementCount.
10026  if (JSObject::kMaxElementCount - estimate_result_length <
10027  length_estimate) {
10028  estimate_result_length = JSObject::kMaxElementCount;
10029  } else {
10030  estimate_result_length += length_estimate;
10031  }
10032  if (JSObject::kMaxElementCount - estimate_nof_elements <
10033  element_estimate) {
10034  estimate_nof_elements = JSObject::kMaxElementCount;
10035  } else {
10036  estimate_nof_elements += element_estimate;
10037  }
10038  }
10039  }
10040 
10041  // If estimated number of elements is more than half of length, a
10042  // fixed array (fast case) is more time and space-efficient than a
10043  // dictionary.
10044  bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length;
10045 
10046  Handle<FixedArray> storage;
10047  if (fast_case) {
10048  // The backing storage array must have non-existing elements to
10049  // preserve holes across concat operations.
10050  storage = isolate->factory()->NewFixedArrayWithHoles(
10051  estimate_result_length);
10052  } else {
10053  // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
10054  uint32_t at_least_space_for = estimate_nof_elements +
10055  (estimate_nof_elements >> 2);
10056  storage = Handle<FixedArray>::cast(
10057  isolate->factory()->NewSeededNumberDictionary(at_least_space_for));
10058  }
10059 
10060  ArrayConcatVisitor visitor(isolate, storage, fast_case);
10061 
10062  for (int i = 0; i < argument_count; i++) {
10063  Handle<Object> obj(elements->get(i));
10064  if (obj->IsJSArray()) {
10066  if (!IterateElements(isolate, array, &visitor)) {
10067  return Failure::Exception();
10068  }
10069  } else {
10070  visitor.visit(0, obj);
10071  visitor.increase_index_offset(1);
10072  }
10073  }
10074 
10075  return *visitor.ToArray();
10076 }
10077 
10078 
10079 // This will not allocate (flatten the string), but it may run
10080 // very slowly for very deeply nested ConsStrings. For debugging use only.
10081 RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalPrint) {
10082  NoHandleAllocation ha;
10083  ASSERT(args.length() == 1);
10084 
10085  CONVERT_ARG_CHECKED(String, string, 0);
10086  StringInputBuffer buffer(string);
10087  while (buffer.has_more()) {
10088  uint16_t character = buffer.GetNext();
10089  PrintF("%c", character);
10090  }
10091  return string;
10092 }
10093 
10094 // Moves all own elements of an object, that are below a limit, to positions
10095 // starting at zero. All undefined values are placed after non-undefined values,
10096 // and are followed by non-existing element. Does not change the length
10097 // property.
10098 // Returns the number of non-undefined elements collected.
10099 RUNTIME_FUNCTION(MaybeObject*, Runtime_RemoveArrayHoles) {
10100  ASSERT(args.length() == 2);
10101  CONVERT_ARG_CHECKED(JSObject, object, 0);
10102  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
10103  return object->PrepareElementsForSort(limit);
10104 }
10105 
10106 
10107 // Move contents of argument 0 (an array) to argument 1 (an array)
10108 RUNTIME_FUNCTION(MaybeObject*, Runtime_MoveArrayContents) {
10109  ASSERT(args.length() == 2);
10110  CONVERT_ARG_CHECKED(JSArray, from, 0);
10111  CONVERT_ARG_CHECKED(JSArray, to, 1);
10112  from->ValidateElements();
10113  to->ValidateElements();
10114  FixedArrayBase* new_elements = from->elements();
10115  ElementsKind from_kind = from->GetElementsKind();
10116  MaybeObject* maybe_new_map;
10117  maybe_new_map = to->GetElementsTransitionMap(isolate, from_kind);
10118  Object* new_map;
10119  if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
10120  to->set_map_and_elements(Map::cast(new_map), new_elements);
10121  to->set_length(from->length());
10122  Object* obj;
10123  { MaybeObject* maybe_obj = from->ResetElements();
10124  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
10125  }
10126  from->set_length(Smi::FromInt(0));
10127  to->ValidateElements();
10128  return to;
10129 }
10130 
10131 
10132 // How many elements does this object/array have?
10133 RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) {
10134  ASSERT(args.length() == 1);
10135  CONVERT_ARG_CHECKED(JSObject, object, 0);
10136  HeapObject* elements = object->elements();
10137  if (elements->IsDictionary()) {
10138  int result = SeededNumberDictionary::cast(elements)->NumberOfElements();
10139  return Smi::FromInt(result);
10140  } else if (object->IsJSArray()) {
10141  return JSArray::cast(object)->length();
10142  } else {
10143  return Smi::FromInt(FixedArray::cast(elements)->length());
10144  }
10145 }
10146 
10147 
10148 // Returns an array that tells you where in the [0, length) interval an array
10149 // might have elements. Can either return keys (positive integers) or
10150 // intervals (pair of a negative integer (-start-1) followed by a
10151 // positive (length)) or undefined values.
10152 // Intervals can span over some keys that are not in the object.
10153 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
10154  ASSERT(args.length() == 2);
10155  HandleScope scope(isolate);
10157  CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
10158  if (array->elements()->IsDictionary()) {
10159  // Create an array and get all the keys into it, then remove all the
10160  // keys that are not integers in the range 0 to length-1.
10161  bool threw = false;
10162  Handle<FixedArray> keys =
10163  GetKeysInFixedArrayFor(array, INCLUDE_PROTOS, &threw);
10164  if (threw) return Failure::Exception();
10165 
10166  int keys_length = keys->length();
10167  for (int i = 0; i < keys_length; i++) {
10168  Object* key = keys->get(i);
10169  uint32_t index = 0;
10170  if (!key->ToArrayIndex(&index) || index >= length) {
10171  // Zap invalid keys.
10172  keys->set_undefined(i);
10173  }
10174  }
10175  return *isolate->factory()->NewJSArrayWithElements(keys);
10176  } else {
10177  ASSERT(array->HasFastSmiOrObjectElements() ||
10178  array->HasFastDoubleElements());
10179  Handle<FixedArray> single_interval = isolate->factory()->NewFixedArray(2);
10180  // -1 means start of array.
10181  single_interval->set(0, Smi::FromInt(-1));
10182  FixedArrayBase* elements = FixedArrayBase::cast(array->elements());
10183  uint32_t actual_length =
10184  static_cast<uint32_t>(elements->length());
10185  uint32_t min_length = actual_length < length ? actual_length : length;
10186  Handle<Object> length_object =
10187  isolate->factory()->NewNumber(static_cast<double>(min_length));
10188  single_interval->set(1, *length_object);
10189  return *isolate->factory()->NewJSArrayWithElements(single_interval);
10190  }
10191 }
10192 
10193 
10194 RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) {
10195  ASSERT(args.length() == 3);
10196  CONVERT_ARG_CHECKED(JSObject, obj, 0);
10197  CONVERT_ARG_CHECKED(String, name, 1);
10200  return obj->LookupAccessor(name, component);
10201 }
10202 
10203 
10204 #ifdef ENABLE_DEBUGGER_SUPPORT
10205 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugBreak) {
10206  ASSERT(args.length() == 0);
10207  return Execution::DebugBreakHelper();
10208 }
10209 
10210 
10211 // Helper functions for wrapping and unwrapping stack frame ids.
10212 static Smi* WrapFrameId(StackFrame::Id id) {
10213  ASSERT(IsAligned(OffsetFrom(id), static_cast<intptr_t>(4)));
10214  return Smi::FromInt(id >> 2);
10215 }
10216 
10217 
10218 static StackFrame::Id UnwrapFrameId(int wrapped) {
10219  return static_cast<StackFrame::Id>(wrapped << 2);
10220 }
10221 
10222 
10223 // Adds a JavaScript function as a debug event listener.
10224 // args[0]: debug event listener function to set or null or undefined for
10225 // clearing the event listener function
10226 // args[1]: object supplied during callback
10227 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDebugEventListener) {
10228  ASSERT(args.length() == 2);
10229  RUNTIME_ASSERT(args[0]->IsJSFunction() ||
10230  args[0]->IsUndefined() ||
10231  args[0]->IsNull());
10232  Handle<Object> callback = args.at<Object>(0);
10233  Handle<Object> data = args.at<Object>(1);
10234  isolate->debugger()->SetEventListener(callback, data);
10235 
10236  return isolate->heap()->undefined_value();
10237 }
10238 
10239 
10240 RUNTIME_FUNCTION(MaybeObject*, Runtime_Break) {
10241  ASSERT(args.length() == 0);
10242  isolate->stack_guard()->DebugBreak();
10243  return isolate->heap()->undefined_value();
10244 }
10245 
10246 
10247 static MaybeObject* DebugLookupResultValue(Heap* heap,
10248  Object* receiver,
10249  String* name,
10250  LookupResult* result,
10251  bool* caught_exception) {
10252  Object* value;
10253  switch (result->type()) {
10254  case NORMAL:
10255  value = result->holder()->GetNormalizedProperty(result);
10256  if (value->IsTheHole()) {
10257  return heap->undefined_value();
10258  }
10259  return value;
10260  case FIELD:
10261  value =
10263  result->holder())->FastPropertyAt(result->GetFieldIndex());
10264  if (value->IsTheHole()) {
10265  return heap->undefined_value();
10266  }
10267  return value;
10268  case CONSTANT_FUNCTION:
10269  return result->GetConstantFunction();
10270  case CALLBACKS: {
10271  Object* structure = result->GetCallbackObject();
10272  if (structure->IsForeign() || structure->IsAccessorInfo()) {
10273  MaybeObject* maybe_value = result->holder()->GetPropertyWithCallback(
10274  receiver, structure, name);
10275  if (!maybe_value->ToObject(&value)) {
10276  if (maybe_value->IsRetryAfterGC()) return maybe_value;
10277  ASSERT(maybe_value->IsException());
10278  maybe_value = heap->isolate()->pending_exception();
10279  heap->isolate()->clear_pending_exception();
10280  if (caught_exception != NULL) {
10281  *caught_exception = true;
10282  }
10283  return maybe_value;
10284  }
10285  return value;
10286  } else {
10287  return heap->undefined_value();
10288  }
10289  }
10290  case INTERCEPTOR:
10291  case MAP_TRANSITION:
10292  case CONSTANT_TRANSITION:
10293  case NULL_DESCRIPTOR:
10294  return heap->undefined_value();
10295  case HANDLER:
10296  UNREACHABLE();
10297  return heap->undefined_value();
10298  }
10299  UNREACHABLE(); // keep the compiler happy
10300  return heap->undefined_value();
10301 }
10302 
10303 
10304 // Get debugger related details for an object property.
10305 // args[0]: object holding property
10306 // args[1]: name of the property
10307 //
10308 // The array returned contains the following information:
10309 // 0: Property value
10310 // 1: Property details
10311 // 2: Property value is exception
10312 // 3: Getter function if defined
10313 // 4: Setter function if defined
10314 // Items 2-4 are only filled if the property has either a getter or a setter
10315 // defined through __defineGetter__ and/or __defineSetter__.
10316 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) {
10317  HandleScope scope(isolate);
10318 
10319  ASSERT(args.length() == 2);
10320 
10321  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10322  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
10323 
10324  // Make sure to set the current context to the context before the debugger was
10325  // entered (if the debugger is entered). The reason for switching context here
10326  // is that for some property lookups (accessors and interceptors) callbacks
10327  // into the embedding application can occour, and the embedding application
10328  // could have the assumption that its own global context is the current
10329  // context and not some internal debugger context.
10330  SaveContext save(isolate);
10331  if (isolate->debug()->InDebugger()) {
10332  isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
10333  }
10334 
10335  // Skip the global proxy as it has no properties and always delegates to the
10336  // real global object.
10337  if (obj->IsJSGlobalProxy()) {
10338  obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
10339  }
10340 
10341 
10342  // Check if the name is trivially convertible to an index and get the element
10343  // if so.
10344  uint32_t index;
10345  if (name->AsArrayIndex(&index)) {
10346  Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
10347  Object* element_or_char;
10348  { MaybeObject* maybe_element_or_char =
10349  Runtime::GetElementOrCharAt(isolate, obj, index);
10350  if (!maybe_element_or_char->ToObject(&element_or_char)) {
10351  return maybe_element_or_char;
10352  }
10353  }
10354  details->set(0, element_or_char);
10355  details->set(1, PropertyDetails(NONE, NORMAL).AsSmi());
10356  return *isolate->factory()->NewJSArrayWithElements(details);
10357  }
10358 
10359  // Find the number of objects making up this.
10360  int length = LocalPrototypeChainLength(*obj);
10361 
10362  // Try local lookup on each of the objects.
10363  Handle<JSObject> jsproto = obj;
10364  for (int i = 0; i < length; i++) {
10365  LookupResult result(isolate);
10366  jsproto->LocalLookup(*name, &result);
10367  if (result.IsProperty()) {
10368  // LookupResult is not GC safe as it holds raw object pointers.
10369  // GC can happen later in this code so put the required fields into
10370  // local variables using handles when required for later use.
10371  PropertyType result_type = result.type();
10372  Handle<Object> result_callback_obj;
10373  if (result_type == CALLBACKS) {
10374  result_callback_obj = Handle<Object>(result.GetCallbackObject(),
10375  isolate);
10376  }
10377  Smi* property_details = result.GetPropertyDetails().AsSmi();
10378  // DebugLookupResultValue can cause GC so details from LookupResult needs
10379  // to be copied to handles before this.
10380  bool caught_exception = false;
10381  Object* raw_value;
10382  { MaybeObject* maybe_raw_value =
10383  DebugLookupResultValue(isolate->heap(), *obj, *name,
10384  &result, &caught_exception);
10385  if (!maybe_raw_value->ToObject(&raw_value)) return maybe_raw_value;
10386  }
10387  Handle<Object> value(raw_value, isolate);
10388 
10389  // If the callback object is a fixed array then it contains JavaScript
10390  // getter and/or setter.
10391  bool hasJavaScriptAccessors = result_type == CALLBACKS &&
10392  result_callback_obj->IsAccessorPair();
10393  Handle<FixedArray> details =
10394  isolate->factory()->NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
10395  details->set(0, *value);
10396  details->set(1, property_details);
10397  if (hasJavaScriptAccessors) {
10398  AccessorPair* accessors = AccessorPair::cast(*result_callback_obj);
10399  details->set(2, isolate->heap()->ToBoolean(caught_exception));
10400  details->set(3, accessors->GetComponent(ACCESSOR_GETTER));
10401  details->set(4, accessors->GetComponent(ACCESSOR_SETTER));
10402  }
10403 
10404  return *isolate->factory()->NewJSArrayWithElements(details);
10405  }
10406  if (i < length - 1) {
10407  jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
10408  }
10409  }
10410 
10411  return isolate->heap()->undefined_value();
10412 }
10413 
10414 
10415 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetProperty) {
10416  HandleScope scope(isolate);
10417 
10418  ASSERT(args.length() == 2);
10419 
10420  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10421  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
10422 
10423  LookupResult result(isolate);
10424  obj->Lookup(*name, &result);
10425  if (result.IsProperty()) {
10426  return DebugLookupResultValue(isolate->heap(), *obj, *name, &result, NULL);
10427  }
10428  return isolate->heap()->undefined_value();
10429 }
10430 
10431 
10432 // Return the property type calculated from the property details.
10433 // args[0]: smi with property details.
10434 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyTypeFromDetails) {
10435  ASSERT(args.length() == 1);
10437  return Smi::FromInt(static_cast<int>(details.type()));
10438 }
10439 
10440 
10441 // Return the property attribute calculated from the property details.
10442 // args[0]: smi with property details.
10443 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyAttributesFromDetails) {
10444  ASSERT(args.length() == 1);
10446  return Smi::FromInt(static_cast<int>(details.attributes()));
10447 }
10448 
10449 
10450 // Return the property insertion index calculated from the property details.
10451 // args[0]: smi with property details.
10452 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyIndexFromDetails) {
10453  ASSERT(args.length() == 1);
10455  return Smi::FromInt(details.index());
10456 }
10457 
10458 
10459 // Return property value from named interceptor.
10460 // args[0]: object
10461 // args[1]: property name
10462 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugNamedInterceptorPropertyValue) {
10463  HandleScope scope(isolate);
10464  ASSERT(args.length() == 2);
10465  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10466  RUNTIME_ASSERT(obj->HasNamedInterceptor());
10467  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
10468 
10469  PropertyAttributes attributes;
10470  return obj->GetPropertyWithInterceptor(*obj, *name, &attributes);
10471 }
10472 
10473 
10474 // Return element value from indexed interceptor.
10475 // args[0]: object
10476 // args[1]: index
10477 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugIndexedInterceptorElementValue) {
10478  HandleScope scope(isolate);
10479  ASSERT(args.length() == 2);
10480  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10481  RUNTIME_ASSERT(obj->HasIndexedInterceptor());
10482  CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
10483 
10484  return obj->GetElementWithInterceptor(*obj, index);
10485 }
10486 
10487 
10488 RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckExecutionState) {
10489  ASSERT(args.length() >= 1);
10490  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
10491  // Check that the break id is valid.
10492  if (isolate->debug()->break_id() == 0 ||
10493  break_id != isolate->debug()->break_id()) {
10494  return isolate->Throw(
10495  isolate->heap()->illegal_execution_state_symbol());
10496  }
10497 
10498  return isolate->heap()->true_value();
10499 }
10500 
10501 
10502 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) {
10503  HandleScope scope(isolate);
10504  ASSERT(args.length() == 1);
10505 
10506  // Check arguments.
10507  Object* result;
10508  { MaybeObject* maybe_result = Runtime_CheckExecutionState(
10509  RUNTIME_ARGUMENTS(isolate, args));
10510  if (!maybe_result->ToObject(&result)) return maybe_result;
10511  }
10512 
10513  // Count all frames which are relevant to debugging stack trace.
10514  int n = 0;
10515  StackFrame::Id id = isolate->debug()->break_frame_id();
10516  if (id == StackFrame::NO_ID) {
10517  // If there is no JavaScript stack frame count is 0.
10518  return Smi::FromInt(0);
10519  }
10520 
10521  for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) {
10522  n += it.frame()->GetInlineCount();
10523  }
10524  return Smi::FromInt(n);
10525 }
10526 
10527 
10528 class FrameInspector {
10529  public:
10530  FrameInspector(JavaScriptFrame* frame,
10531  int inlined_jsframe_index,
10532  Isolate* isolate)
10533  : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
10534  // Calculate the deoptimized frame.
10535  if (frame->is_optimized()) {
10536  deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
10537  frame, inlined_jsframe_index, isolate);
10538  }
10539  has_adapted_arguments_ = frame_->has_adapted_arguments();
10540  is_bottommost_ = inlined_jsframe_index == 0;
10541  is_optimized_ = frame_->is_optimized();
10542  }
10543 
10544  ~FrameInspector() {
10545  // Get rid of the calculated deoptimized frame if any.
10546  if (deoptimized_frame_ != NULL) {
10547  Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_,
10548  isolate_);
10549  }
10550  }
10551 
10552  int GetParametersCount() {
10553  return is_optimized_
10554  ? deoptimized_frame_->parameters_count()
10555  : frame_->ComputeParametersCount();
10556  }
10557  int expression_count() { return deoptimized_frame_->expression_count(); }
10558  Object* GetFunction() {
10559  return is_optimized_
10560  ? deoptimized_frame_->GetFunction()
10561  : frame_->function();
10562  }
10563  Object* GetParameter(int index) {
10564  return is_optimized_
10565  ? deoptimized_frame_->GetParameter(index)
10566  : frame_->GetParameter(index);
10567  }
10568  Object* GetExpression(int index) {
10569  return is_optimized_
10570  ? deoptimized_frame_->GetExpression(index)
10571  : frame_->GetExpression(index);
10572  }
10573  int GetSourcePosition() {
10574  return is_optimized_
10575  ? deoptimized_frame_->GetSourcePosition()
10576  : frame_->LookupCode()->SourcePosition(frame_->pc());
10577  }
10578  bool IsConstructor() {
10579  return is_optimized_ && !is_bottommost_
10580  ? deoptimized_frame_->HasConstructStub()
10581  : frame_->IsConstructor();
10582  }
10583 
10584  // To inspect all the provided arguments the frame might need to be
10585  // replaced with the arguments frame.
10586  void SetArgumentsFrame(JavaScriptFrame* frame) {
10587  ASSERT(has_adapted_arguments_);
10588  frame_ = frame;
10589  is_optimized_ = frame_->is_optimized();
10590  ASSERT(!is_optimized_);
10591  }
10592 
10593  private:
10594  JavaScriptFrame* frame_;
10595  DeoptimizedFrameInfo* deoptimized_frame_;
10596  Isolate* isolate_;
10597  bool is_optimized_;
10598  bool is_bottommost_;
10599  bool has_adapted_arguments_;
10600 
10601  DISALLOW_COPY_AND_ASSIGN(FrameInspector);
10602 };
10603 
10604 
10605 static const int kFrameDetailsFrameIdIndex = 0;
10606 static const int kFrameDetailsReceiverIndex = 1;
10607 static const int kFrameDetailsFunctionIndex = 2;
10608 static const int kFrameDetailsArgumentCountIndex = 3;
10609 static const int kFrameDetailsLocalCountIndex = 4;
10610 static const int kFrameDetailsSourcePositionIndex = 5;
10611 static const int kFrameDetailsConstructCallIndex = 6;
10612 static const int kFrameDetailsAtReturnIndex = 7;
10613 static const int kFrameDetailsFlagsIndex = 8;
10614 static const int kFrameDetailsFirstDynamicIndex = 9;
10615 
10616 
10617 static SaveContext* FindSavedContextForFrame(Isolate* isolate,
10618  JavaScriptFrame* frame) {
10619  SaveContext* save = isolate->save_context();
10620  while (save != NULL && !save->IsBelowFrame(frame)) {
10621  save = save->prev();
10622  }
10623  ASSERT(save != NULL);
10624  return save;
10625 }
10626 
10627 
10628 // Return an array with frame details
10629 // args[0]: number: break id
10630 // args[1]: number: frame index
10631 //
10632 // The array returned contains the following information:
10633 // 0: Frame id
10634 // 1: Receiver
10635 // 2: Function
10636 // 3: Argument count
10637 // 4: Local count
10638 // 5: Source position
10639 // 6: Constructor call
10640 // 7: Is at return
10641 // 8: Flags
10642 // Arguments name, value
10643 // Locals name, value
10644 // Return value if any
10645 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
10646  HandleScope scope(isolate);
10647  ASSERT(args.length() == 2);
10648 
10649  // Check arguments.
10650  Object* check;
10651  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
10652  RUNTIME_ARGUMENTS(isolate, args));
10653  if (!maybe_check->ToObject(&check)) return maybe_check;
10654  }
10655  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
10656  Heap* heap = isolate->heap();
10657 
10658  // Find the relevant frame with the requested index.
10659  StackFrame::Id id = isolate->debug()->break_frame_id();
10660  if (id == StackFrame::NO_ID) {
10661  // If there are no JavaScript stack frames return undefined.
10662  return heap->undefined_value();
10663  }
10664 
10665  int count = 0;
10666  JavaScriptFrameIterator it(isolate, id);
10667  for (; !it.done(); it.Advance()) {
10668  if (index < count + it.frame()->GetInlineCount()) break;
10669  count += it.frame()->GetInlineCount();
10670  }
10671  if (it.done()) return heap->undefined_value();
10672 
10673  bool is_optimized = it.frame()->is_optimized();
10674 
10675  int inlined_jsframe_index = 0; // Inlined frame index in optimized frame.
10676  if (is_optimized) {
10677  inlined_jsframe_index =
10678  it.frame()->GetInlineCount() - (index - count) - 1;
10679  }
10680  FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate);
10681 
10682  // Traverse the saved contexts chain to find the active context for the
10683  // selected frame.
10684  SaveContext* save = FindSavedContextForFrame(isolate, it.frame());
10685 
10686  // Get the frame id.
10687  Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate);
10688 
10689  // Find source position in unoptimized code.
10690  int position = frame_inspector.GetSourcePosition();
10691 
10692  // Check for constructor frame.
10693  bool constructor = frame_inspector.IsConstructor();
10694 
10695  // Get scope info and read from it for local variable information.
10696  Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
10697  Handle<SharedFunctionInfo> shared(function->shared());
10698  Handle<ScopeInfo> scope_info(shared->scope_info());
10699  ASSERT(*scope_info != ScopeInfo::Empty());
10700 
10701  // Get the locals names and values into a temporary array.
10702  //
10703  // TODO(1240907): Hide compiler-introduced stack variables
10704  // (e.g. .result)? For users of the debugger, they will probably be
10705  // confusing.
10706  Handle<FixedArray> locals =
10707  isolate->factory()->NewFixedArray(scope_info->LocalCount() * 2);
10708 
10709  // Fill in the values of the locals.
10710  int i = 0;
10711  for (; i < scope_info->StackLocalCount(); ++i) {
10712  // Use the value from the stack.
10713  locals->set(i * 2, scope_info->LocalName(i));
10714  locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
10715  }
10716  if (i < scope_info->LocalCount()) {
10717  // Get the context containing declarations.
10718  Handle<Context> context(
10719  Context::cast(it.frame()->context())->declaration_context());
10720  for (; i < scope_info->LocalCount(); ++i) {
10721  Handle<String> name(scope_info->LocalName(i));
10722  VariableMode mode;
10723  InitializationFlag init_flag;
10724  locals->set(i * 2, *name);
10725  locals->set(i * 2 + 1, context->get(
10726  scope_info->ContextSlotIndex(*name, &mode, &init_flag)));
10727  }
10728  }
10729 
10730  // Check whether this frame is positioned at return. If not top
10731  // frame or if the frame is optimized it cannot be at a return.
10732  bool at_return = false;
10733  if (!is_optimized && index == 0) {
10734  at_return = isolate->debug()->IsBreakAtReturn(it.frame());
10735  }
10736 
10737  // If positioned just before return find the value to be returned and add it
10738  // to the frame information.
10739  Handle<Object> return_value = isolate->factory()->undefined_value();
10740  if (at_return) {
10741  StackFrameIterator it2(isolate);
10742  Address internal_frame_sp = NULL;
10743  while (!it2.done()) {
10744  if (it2.frame()->is_internal()) {
10745  internal_frame_sp = it2.frame()->sp();
10746  } else {
10747  if (it2.frame()->is_java_script()) {
10748  if (it2.frame()->id() == it.frame()->id()) {
10749  // The internal frame just before the JavaScript frame contains the
10750  // value to return on top. A debug break at return will create an
10751  // internal frame to store the return value (eax/rax/r0) before
10752  // entering the debug break exit frame.
10753  if (internal_frame_sp != NULL) {
10754  return_value =
10755  Handle<Object>(Memory::Object_at(internal_frame_sp),
10756  isolate);
10757  break;
10758  }
10759  }
10760  }
10761 
10762  // Indicate that the previous frame was not an internal frame.
10763  internal_frame_sp = NULL;
10764  }
10765  it2.Advance();
10766  }
10767  }
10768 
10769  // Now advance to the arguments adapter frame (if any). It contains all
10770  // the provided parameters whereas the function frame always have the number
10771  // of arguments matching the functions parameters. The rest of the
10772  // information (except for what is collected above) is the same.
10773  if ((inlined_jsframe_index == 0) && it.frame()->has_adapted_arguments()) {
10774  it.AdvanceToArgumentsFrame();
10775  frame_inspector.SetArgumentsFrame(it.frame());
10776  }
10777 
10778  // Find the number of arguments to fill. At least fill the number of
10779  // parameters for the function and fill more if more parameters are provided.
10780  int argument_count = scope_info->ParameterCount();
10781  if (argument_count < frame_inspector.GetParametersCount()) {
10782  argument_count = frame_inspector.GetParametersCount();
10783  }
10784 
10785  // Calculate the size of the result.
10786  int details_size = kFrameDetailsFirstDynamicIndex +
10787  2 * (argument_count + scope_info->LocalCount()) +
10788  (at_return ? 1 : 0);
10789  Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
10790 
10791  // Add the frame id.
10792  details->set(kFrameDetailsFrameIdIndex, *frame_id);
10793 
10794  // Add the function (same as in function frame).
10795  details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
10796 
10797  // Add the arguments count.
10798  details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
10799 
10800  // Add the locals count
10801  details->set(kFrameDetailsLocalCountIndex,
10802  Smi::FromInt(scope_info->LocalCount()));
10803 
10804  // Add the source position.
10805  if (position != RelocInfo::kNoPosition) {
10806  details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
10807  } else {
10808  details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
10809  }
10810 
10811  // Add the constructor information.
10812  details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
10813 
10814  // Add the at return information.
10815  details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
10816 
10817  // Add flags to indicate information on whether this frame is
10818  // bit 0: invoked in the debugger context.
10819  // bit 1: optimized frame.
10820  // bit 2: inlined in optimized frame
10821  int flags = 0;
10822  if (*save->context() == *isolate->debug()->debug_context()) {
10823  flags |= 1 << 0;
10824  }
10825  if (is_optimized) {
10826  flags |= 1 << 1;
10827  flags |= inlined_jsframe_index << 2;
10828  }
10829  details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
10830 
10831  // Fill the dynamic part.
10832  int details_index = kFrameDetailsFirstDynamicIndex;
10833 
10834  // Add arguments name and value.
10835  for (int i = 0; i < argument_count; i++) {
10836  // Name of the argument.
10837  if (i < scope_info->ParameterCount()) {
10838  details->set(details_index++, scope_info->ParameterName(i));
10839  } else {
10840  details->set(details_index++, heap->undefined_value());
10841  }
10842 
10843  // Parameter value.
10844  if (i < frame_inspector.GetParametersCount()) {
10845  // Get the value from the stack.
10846  details->set(details_index++, frame_inspector.GetParameter(i));
10847  } else {
10848  details->set(details_index++, heap->undefined_value());
10849  }
10850  }
10851 
10852  // Add locals name and value from the temporary copy from the function frame.
10853  for (int i = 0; i < scope_info->LocalCount() * 2; i++) {
10854  details->set(details_index++, locals->get(i));
10855  }
10856 
10857  // Add the value being returned.
10858  if (at_return) {
10859  details->set(details_index++, *return_value);
10860  }
10861 
10862  // Add the receiver (same as in function frame).
10863  // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
10864  // THE FRAME ITERATOR TO WRAP THE RECEIVER.
10865  Handle<Object> receiver(it.frame()->receiver(), isolate);
10866  if (!receiver->IsJSObject() &&
10867  shared->is_classic_mode() &&
10868  !shared->native()) {
10869  // If the receiver is not a JSObject and the function is not a
10870  // builtin or strict-mode we have hit an optimization where a
10871  // value object is not converted into a wrapped JS objects. To
10872  // hide this optimization from the debugger, we wrap the receiver
10873  // by creating correct wrapper object based on the calling frame's
10874  // global context.
10875  it.Advance();
10876  Handle<Context> calling_frames_global_context(
10877  Context::cast(Context::cast(it.frame()->context())->global_context()));
10878  receiver =
10879  isolate->factory()->ToObject(receiver, calling_frames_global_context);
10880  }
10881  details->set(kFrameDetailsReceiverIndex, *receiver);
10882 
10883  ASSERT_EQ(details_size, details_index);
10884  return *isolate->factory()->NewJSArrayWithElements(details);
10885 }
10886 
10887 
10888 // Copy all the context locals into an object used to materialize a scope.
10889 static bool CopyContextLocalsToScopeObject(
10890  Isolate* isolate,
10891  Handle<ScopeInfo> scope_info,
10892  Handle<Context> context,
10893  Handle<JSObject> scope_object) {
10894  // Fill all context locals to the context extension.
10895  for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
10896  VariableMode mode;
10897  InitializationFlag init_flag;
10898  int context_index = scope_info->ContextSlotIndex(
10899  scope_info->ContextLocalName(i), &mode, &init_flag);
10900 
10902  isolate,
10903  SetProperty(scope_object,
10904  Handle<String>(scope_info->ContextLocalName(i)),
10905  Handle<Object>(context->get(context_index), isolate),
10906  NONE,
10907  kNonStrictMode),
10908  false);
10909  }
10910 
10911  return true;
10912 }
10913 
10914 
10915 // Create a plain JSObject which materializes the local scope for the specified
10916 // frame.
10917 static Handle<JSObject> MaterializeLocalScopeWithFrameInspector(
10918  Isolate* isolate,
10919  JavaScriptFrame* frame,
10920  FrameInspector* frame_inspector) {
10921  Handle<JSFunction> function(JSFunction::cast(frame_inspector->GetFunction()));
10922  Handle<SharedFunctionInfo> shared(function->shared());
10923  Handle<ScopeInfo> scope_info(shared->scope_info());
10924 
10925  // Allocate and initialize a JSObject with all the arguments, stack locals
10926  // heap locals and extension properties of the debugged function.
10927  Handle<JSObject> local_scope =
10928  isolate->factory()->NewJSObject(isolate->object_function());
10929 
10930  // First fill all parameters.
10931  for (int i = 0; i < scope_info->ParameterCount(); ++i) {
10932  Handle<Object> value(
10933  i < frame_inspector->GetParametersCount() ?
10934  frame_inspector->GetParameter(i) : isolate->heap()->undefined_value());
10935 
10937  isolate,
10938  SetProperty(local_scope,
10939  Handle<String>(scope_info->ParameterName(i)),
10940  value,
10941  NONE,
10942  kNonStrictMode),
10943  Handle<JSObject>());
10944  }
10945 
10946  // Second fill all stack locals.
10947  for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
10949  isolate,
10950  SetProperty(local_scope,
10951  Handle<String>(scope_info->StackLocalName(i)),
10952  Handle<Object>(frame_inspector->GetExpression(i)),
10953  NONE,
10954  kNonStrictMode),
10955  Handle<JSObject>());
10956  }
10957 
10958  if (scope_info->HasContext()) {
10959  // Third fill all context locals.
10960  Handle<Context> frame_context(Context::cast(frame->context()));
10961  Handle<Context> function_context(frame_context->declaration_context());
10962  if (!CopyContextLocalsToScopeObject(
10963  isolate, scope_info, function_context, local_scope)) {
10964  return Handle<JSObject>();
10965  }
10966 
10967  // Finally copy any properties from the function context extension.
10968  // These will be variables introduced by eval.
10969  if (function_context->closure() == *function) {
10970  if (function_context->has_extension() &&
10971  !function_context->IsGlobalContext()) {
10972  Handle<JSObject> ext(JSObject::cast(function_context->extension()));
10973  bool threw = false;
10974  Handle<FixedArray> keys =
10975  GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
10976  if (threw) return Handle<JSObject>();
10977 
10978  for (int i = 0; i < keys->length(); i++) {
10979  // Names of variables introduced by eval are strings.
10980  ASSERT(keys->get(i)->IsString());
10981  Handle<String> key(String::cast(keys->get(i)));
10983  isolate,
10984  SetProperty(local_scope,
10985  key,
10986  GetProperty(ext, key),
10987  NONE,
10988  kNonStrictMode),
10989  Handle<JSObject>());
10990  }
10991  }
10992  }
10993  }
10994 
10995  return local_scope;
10996 }
10997 
10998 
10999 static Handle<JSObject> MaterializeLocalScope(
11000  Isolate* isolate,
11001  JavaScriptFrame* frame,
11002  int inlined_jsframe_index) {
11003  FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
11004  return MaterializeLocalScopeWithFrameInspector(isolate,
11005  frame,
11006  &frame_inspector);
11007 }
11008 
11009 
11010 // Create a plain JSObject which materializes the closure content for the
11011 // context.
11012 static Handle<JSObject> MaterializeClosure(Isolate* isolate,
11013  Handle<Context> context) {
11014  ASSERT(context->IsFunctionContext());
11015 
11016  Handle<SharedFunctionInfo> shared(context->closure()->shared());
11017  Handle<ScopeInfo> scope_info(shared->scope_info());
11018 
11019  // Allocate and initialize a JSObject with all the content of this function
11020  // closure.
11021  Handle<JSObject> closure_scope =
11022  isolate->factory()->NewJSObject(isolate->object_function());
11023 
11024  // Fill all context locals to the context extension.
11025  if (!CopyContextLocalsToScopeObject(
11026  isolate, scope_info, context, closure_scope)) {
11027  return Handle<JSObject>();
11028  }
11029 
11030  // Finally copy any properties from the function context extension. This will
11031  // be variables introduced by eval.
11032  if (context->has_extension()) {
11033  Handle<JSObject> ext(JSObject::cast(context->extension()));
11034  bool threw = false;
11035  Handle<FixedArray> keys =
11036  GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
11037  if (threw) return Handle<JSObject>();
11038 
11039  for (int i = 0; i < keys->length(); i++) {
11040  // Names of variables introduced by eval are strings.
11041  ASSERT(keys->get(i)->IsString());
11042  Handle<String> key(String::cast(keys->get(i)));
11044  isolate,
11045  SetProperty(closure_scope,
11046  key,
11047  GetProperty(ext, key),
11048  NONE,
11049  kNonStrictMode),
11050  Handle<JSObject>());
11051  }
11052  }
11053 
11054  return closure_scope;
11055 }
11056 
11057 
11058 // Create a plain JSObject which materializes the scope for the specified
11059 // catch context.
11060 static Handle<JSObject> MaterializeCatchScope(Isolate* isolate,
11061  Handle<Context> context) {
11062  ASSERT(context->IsCatchContext());
11063  Handle<String> name(String::cast(context->extension()));
11064  Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX));
11065  Handle<JSObject> catch_scope =
11066  isolate->factory()->NewJSObject(isolate->object_function());
11068  isolate,
11069  SetProperty(catch_scope, name, thrown_object, NONE, kNonStrictMode),
11070  Handle<JSObject>());
11071  return catch_scope;
11072 }
11073 
11074 
11075 // Create a plain JSObject which materializes the block scope for the specified
11076 // block context.
11077 static Handle<JSObject> MaterializeBlockScope(
11078  Isolate* isolate,
11079  Handle<Context> context) {
11080  ASSERT(context->IsBlockContext());
11081  Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
11082 
11083  // Allocate and initialize a JSObject with all the arguments, stack locals
11084  // heap locals and extension properties of the debugged function.
11085  Handle<JSObject> block_scope =
11086  isolate->factory()->NewJSObject(isolate->object_function());
11087 
11088  // Fill all context locals.
11089  if (!CopyContextLocalsToScopeObject(
11090  isolate, scope_info, context, block_scope)) {
11091  return Handle<JSObject>();
11092  }
11093 
11094  return block_scope;
11095 }
11096 
11097 
11098 // Create a plain JSObject which materializes the module scope for the specified
11099 // module context.
11100 static Handle<JSObject> MaterializeModuleScope(
11101  Isolate* isolate,
11102  Handle<Context> context) {
11103  ASSERT(context->IsModuleContext());
11104  Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
11105 
11106  // Allocate and initialize a JSObject with all the members of the debugged
11107  // module.
11108  Handle<JSObject> module_scope =
11109  isolate->factory()->NewJSObject(isolate->object_function());
11110 
11111  // Fill all context locals.
11112  if (!CopyContextLocalsToScopeObject(
11113  isolate, scope_info, context, module_scope)) {
11114  return Handle<JSObject>();
11115  }
11116 
11117  return module_scope;
11118 }
11119 
11120 
11121 // Iterate over the actual scopes visible from a stack frame or from a closure.
11122 // The iteration proceeds from the innermost visible nested scope outwards.
11123 // All scopes are backed by an actual context except the local scope,
11124 // which is inserted "artificially" in the context chain.
11125 class ScopeIterator {
11126  public:
11127  enum ScopeType {
11128  ScopeTypeGlobal = 0,
11129  ScopeTypeLocal,
11130  ScopeTypeWith,
11131  ScopeTypeClosure,
11132  ScopeTypeCatch,
11133  ScopeTypeBlock,
11134  ScopeTypeModule
11135  };
11136 
11137  ScopeIterator(Isolate* isolate,
11138  JavaScriptFrame* frame,
11139  int inlined_jsframe_index)
11140  : isolate_(isolate),
11141  frame_(frame),
11142  inlined_jsframe_index_(inlined_jsframe_index),
11143  function_(JSFunction::cast(frame->function())),
11144  context_(Context::cast(frame->context())),
11145  nested_scope_chain_(4) {
11146 
11147  // Catch the case when the debugger stops in an internal function.
11148  Handle<SharedFunctionInfo> shared_info(function_->shared());
11149  Handle<ScopeInfo> scope_info(shared_info->scope_info());
11150  if (shared_info->script() == isolate->heap()->undefined_value()) {
11151  while (context_->closure() == *function_) {
11152  context_ = Handle<Context>(context_->previous(), isolate_);
11153  }
11154  return;
11155  }
11156 
11157  // Get the debug info (create it if it does not exist).
11158  if (!isolate->debug()->EnsureDebugInfo(shared_info)) {
11159  // Return if ensuring debug info failed.
11160  return;
11161  }
11162  Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared_info);
11163 
11164  // Find the break point where execution has stopped.
11165  BreakLocationIterator break_location_iterator(debug_info,
11166  ALL_BREAK_LOCATIONS);
11167  break_location_iterator.FindBreakLocationFromAddress(frame->pc());
11168  if (break_location_iterator.IsExit()) {
11169  // We are within the return sequence. At the momemt it is not possible to
11170  // get a source position which is consistent with the current scope chain.
11171  // Thus all nested with, catch and block contexts are skipped and we only
11172  // provide the function scope.
11173  if (scope_info->HasContext()) {
11174  context_ = Handle<Context>(context_->declaration_context(), isolate_);
11175  } else {
11176  while (context_->closure() == *function_) {
11177  context_ = Handle<Context>(context_->previous(), isolate_);
11178  }
11179  }
11180  if (scope_info->Type() != EVAL_SCOPE) nested_scope_chain_.Add(scope_info);
11181  } else {
11182  // Reparse the code and analyze the scopes.
11183  ZoneScope zone_scope(isolate, DELETE_ON_EXIT);
11184  Handle<Script> script(Script::cast(shared_info->script()));
11185  Scope* scope = NULL;
11186 
11187  // Check whether we are in global, eval or function code.
11188  Handle<ScopeInfo> scope_info(shared_info->scope_info());
11189  if (scope_info->Type() != FUNCTION_SCOPE) {
11190  // Global or eval code.
11191  CompilationInfo info(script);
11192  if (scope_info->Type() == GLOBAL_SCOPE) {
11193  info.MarkAsGlobal();
11194  } else {
11195  ASSERT(scope_info->Type() == EVAL_SCOPE);
11196  info.MarkAsEval();
11197  info.SetCallingContext(Handle<Context>(function_->context()));
11198  }
11199  if (ParserApi::Parse(&info, kNoParsingFlags) && Scope::Analyze(&info)) {
11200  scope = info.function()->scope();
11201  }
11202  } else {
11203  // Function code
11204  CompilationInfo info(shared_info);
11205  if (ParserApi::Parse(&info, kNoParsingFlags) && Scope::Analyze(&info)) {
11206  scope = info.function()->scope();
11207  }
11208  }
11209 
11210  // Retrieve the scope chain for the current position.
11211  if (scope != NULL) {
11212  int source_position = shared_info->code()->SourcePosition(frame_->pc());
11213  scope->GetNestedScopeChain(&nested_scope_chain_, source_position);
11214  } else {
11215  // A failed reparse indicates that the preparser has diverged from the
11216  // parser or that the preparse data given to the initial parse has been
11217  // faulty. We fail in debug mode but in release mode we only provide the
11218  // information we get from the context chain but nothing about
11219  // completely stack allocated scopes or stack allocated locals.
11220  UNREACHABLE();
11221  }
11222  }
11223  }
11224 
11225  ScopeIterator(Isolate* isolate,
11226  Handle<JSFunction> function)
11227  : isolate_(isolate),
11228  frame_(NULL),
11229  inlined_jsframe_index_(0),
11230  function_(function),
11231  context_(function->context()) {
11232  if (function->IsBuiltin()) {
11233  context_ = Handle<Context>();
11234  }
11235  }
11236 
11237  // More scopes?
11238  bool Done() { return context_.is_null(); }
11239 
11240  // Move to the next scope.
11241  void Next() {
11242  ScopeType scope_type = Type();
11243  if (scope_type == ScopeTypeGlobal) {
11244  // The global scope is always the last in the chain.
11245  ASSERT(context_->IsGlobalContext());
11246  context_ = Handle<Context>();
11247  return;
11248  }
11249  if (nested_scope_chain_.is_empty()) {
11250  context_ = Handle<Context>(context_->previous(), isolate_);
11251  } else {
11252  if (nested_scope_chain_.last()->HasContext()) {
11253  ASSERT(context_->previous() != NULL);
11254  context_ = Handle<Context>(context_->previous(), isolate_);
11255  }
11256  nested_scope_chain_.RemoveLast();
11257  }
11258  }
11259 
11260  // Return the type of the current scope.
11261  ScopeType Type() {
11262  if (!nested_scope_chain_.is_empty()) {
11263  Handle<ScopeInfo> scope_info = nested_scope_chain_.last();
11264  switch (scope_info->Type()) {
11265  case FUNCTION_SCOPE:
11266  ASSERT(context_->IsFunctionContext() ||
11267  !scope_info->HasContext());
11268  return ScopeTypeLocal;
11269  case MODULE_SCOPE:
11270  ASSERT(context_->IsModuleContext());
11271  return ScopeTypeModule;
11272  case GLOBAL_SCOPE:
11273  ASSERT(context_->IsGlobalContext());
11274  return ScopeTypeGlobal;
11275  case WITH_SCOPE:
11276  ASSERT(context_->IsWithContext());
11277  return ScopeTypeWith;
11278  case CATCH_SCOPE:
11279  ASSERT(context_->IsCatchContext());
11280  return ScopeTypeCatch;
11281  case BLOCK_SCOPE:
11282  ASSERT(!scope_info->HasContext() ||
11283  context_->IsBlockContext());
11284  return ScopeTypeBlock;
11285  case EVAL_SCOPE:
11286  UNREACHABLE();
11287  }
11288  }
11289  if (context_->IsGlobalContext()) {
11290  ASSERT(context_->global()->IsGlobalObject());
11291  return ScopeTypeGlobal;
11292  }
11293  if (context_->IsFunctionContext()) {
11294  return ScopeTypeClosure;
11295  }
11296  if (context_->IsCatchContext()) {
11297  return ScopeTypeCatch;
11298  }
11299  if (context_->IsBlockContext()) {
11300  return ScopeTypeBlock;
11301  }
11302  if (context_->IsModuleContext()) {
11303  return ScopeTypeModule;
11304  }
11305  ASSERT(context_->IsWithContext());
11306  return ScopeTypeWith;
11307  }
11308 
11309  // Return the JavaScript object with the content of the current scope.
11310  Handle<JSObject> ScopeObject() {
11311  switch (Type()) {
11312  case ScopeIterator::ScopeTypeGlobal:
11313  return Handle<JSObject>(CurrentContext()->global());
11314  case ScopeIterator::ScopeTypeLocal:
11315  // Materialize the content of the local scope into a JSObject.
11316  ASSERT(nested_scope_chain_.length() == 1);
11317  return MaterializeLocalScope(isolate_, frame_, inlined_jsframe_index_);
11318  case ScopeIterator::ScopeTypeWith:
11319  // Return the with object.
11320  return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
11321  case ScopeIterator::ScopeTypeCatch:
11322  return MaterializeCatchScope(isolate_, CurrentContext());
11323  case ScopeIterator::ScopeTypeClosure:
11324  // Materialize the content of the closure scope into a JSObject.
11325  return MaterializeClosure(isolate_, CurrentContext());
11326  case ScopeIterator::ScopeTypeBlock:
11327  return MaterializeBlockScope(isolate_, CurrentContext());
11328  case ScopeIterator::ScopeTypeModule:
11329  return MaterializeModuleScope(isolate_, CurrentContext());
11330  }
11331  UNREACHABLE();
11332  return Handle<JSObject>();
11333  }
11334 
11335  Handle<ScopeInfo> CurrentScopeInfo() {
11336  if (!nested_scope_chain_.is_empty()) {
11337  return nested_scope_chain_.last();
11338  } else if (context_->IsBlockContext()) {
11339  return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension()));
11340  } else if (context_->IsFunctionContext()) {
11341  return Handle<ScopeInfo>(context_->closure()->shared()->scope_info());
11342  }
11343  return Handle<ScopeInfo>::null();
11344  }
11345 
11346  // Return the context for this scope. For the local context there might not
11347  // be an actual context.
11348  Handle<Context> CurrentContext() {
11349  if (Type() == ScopeTypeGlobal ||
11350  nested_scope_chain_.is_empty()) {
11351  return context_;
11352  } else if (nested_scope_chain_.last()->HasContext()) {
11353  return context_;
11354  } else {
11355  return Handle<Context>();
11356  }
11357  }
11358 
11359 #ifdef DEBUG
11360  // Debug print of the content of the current scope.
11361  void DebugPrint() {
11362  switch (Type()) {
11363  case ScopeIterator::ScopeTypeGlobal:
11364  PrintF("Global:\n");
11365  CurrentContext()->Print();
11366  break;
11367 
11368  case ScopeIterator::ScopeTypeLocal: {
11369  PrintF("Local:\n");
11370  function_->shared()->scope_info()->Print();
11371  if (!CurrentContext().is_null()) {
11372  CurrentContext()->Print();
11373  if (CurrentContext()->has_extension()) {
11374  Handle<Object> extension(CurrentContext()->extension());
11375  if (extension->IsJSContextExtensionObject()) {
11376  extension->Print();
11377  }
11378  }
11379  }
11380  break;
11381  }
11382 
11383  case ScopeIterator::ScopeTypeWith:
11384  PrintF("With:\n");
11385  CurrentContext()->extension()->Print();
11386  break;
11387 
11388  case ScopeIterator::ScopeTypeCatch:
11389  PrintF("Catch:\n");
11390  CurrentContext()->extension()->Print();
11391  CurrentContext()->get(Context::THROWN_OBJECT_INDEX)->Print();
11392  break;
11393 
11394  case ScopeIterator::ScopeTypeClosure:
11395  PrintF("Closure:\n");
11396  CurrentContext()->Print();
11397  if (CurrentContext()->has_extension()) {
11398  Handle<Object> extension(CurrentContext()->extension());
11399  if (extension->IsJSContextExtensionObject()) {
11400  extension->Print();
11401  }
11402  }
11403  break;
11404 
11405  default:
11406  UNREACHABLE();
11407  }
11408  PrintF("\n");
11409  }
11410 #endif
11411 
11412  private:
11413  Isolate* isolate_;
11414  JavaScriptFrame* frame_;
11415  int inlined_jsframe_index_;
11416  Handle<JSFunction> function_;
11417  Handle<Context> context_;
11418  List<Handle<ScopeInfo> > nested_scope_chain_;
11419 
11420  DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
11421 };
11422 
11423 
11424 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
11425  HandleScope scope(isolate);
11426  ASSERT(args.length() == 2);
11427 
11428  // Check arguments.
11429  Object* check;
11430  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11431  RUNTIME_ARGUMENTS(isolate, args));
11432  if (!maybe_check->ToObject(&check)) return maybe_check;
11433  }
11434  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
11435 
11436  // Get the frame where the debugging is performed.
11437  StackFrame::Id id = UnwrapFrameId(wrapped_id);
11438  JavaScriptFrameIterator it(isolate, id);
11439  JavaScriptFrame* frame = it.frame();
11440 
11441  // Count the visible scopes.
11442  int n = 0;
11443  for (ScopeIterator it(isolate, frame, 0);
11444  !it.Done();
11445  it.Next()) {
11446  n++;
11447  }
11448 
11449  return Smi::FromInt(n);
11450 }
11451 
11452 
11453 static const int kScopeDetailsTypeIndex = 0;
11454 static const int kScopeDetailsObjectIndex = 1;
11455 static const int kScopeDetailsSize = 2;
11456 
11457 
11458 static MaybeObject* MaterializeScopeDetails(Isolate* isolate,
11459  ScopeIterator* it) {
11460  // Calculate the size of the result.
11461  int details_size = kScopeDetailsSize;
11462  Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
11463 
11464  // Fill in scope details.
11465  details->set(kScopeDetailsTypeIndex, Smi::FromInt(it->Type()));
11466  Handle<JSObject> scope_object = it->ScopeObject();
11467  RETURN_IF_EMPTY_HANDLE(isolate, scope_object);
11468  details->set(kScopeDetailsObjectIndex, *scope_object);
11469 
11470  return *isolate->factory()->NewJSArrayWithElements(details);
11471 }
11472 
11473 // Return an array with scope details
11474 // args[0]: number: break id
11475 // args[1]: number: frame index
11476 // args[2]: number: inlined frame index
11477 // args[3]: number: scope index
11478 //
11479 // The array returned contains the following information:
11480 // 0: Scope type
11481 // 1: Scope object
11482 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
11483  HandleScope scope(isolate);
11484  ASSERT(args.length() == 4);
11485 
11486  // Check arguments.
11487  Object* check;
11488  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11489  RUNTIME_ARGUMENTS(isolate, args));
11490  if (!maybe_check->ToObject(&check)) return maybe_check;
11491  }
11492  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
11493  CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
11494  CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
11495 
11496  // Get the frame where the debugging is performed.
11497  StackFrame::Id id = UnwrapFrameId(wrapped_id);
11498  JavaScriptFrameIterator frame_it(isolate, id);
11499  JavaScriptFrame* frame = frame_it.frame();
11500 
11501  // Find the requested scope.
11502  int n = 0;
11503  ScopeIterator it(isolate, frame, inlined_jsframe_index);
11504  for (; !it.Done() && n < index; it.Next()) {
11505  n++;
11506  }
11507  if (it.Done()) {
11508  return isolate->heap()->undefined_value();
11509  }
11510  return MaterializeScopeDetails(isolate, &it);
11511 }
11512 
11513 
11514 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeCount) {
11515  HandleScope scope(isolate);
11516  ASSERT(args.length() == 1);
11517 
11518  // Check arguments.
11519  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
11520 
11521  // Count the visible scopes.
11522  int n = 0;
11523  for (ScopeIterator it(isolate, fun); !it.Done(); it.Next()) {
11524  n++;
11525  }
11526 
11527  return Smi::FromInt(n);
11528 }
11529 
11530 
11531 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeDetails) {
11532  HandleScope scope(isolate);
11533  ASSERT(args.length() == 2);
11534 
11535  // Check arguments.
11536  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
11537  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
11538 
11539  // Find the requested scope.
11540  int n = 0;
11541  ScopeIterator it(isolate, fun);
11542  for (; !it.Done() && n < index; it.Next()) {
11543  n++;
11544  }
11545  if (it.Done()) {
11546  return isolate->heap()->undefined_value();
11547  }
11548 
11549  return MaterializeScopeDetails(isolate, &it);
11550 }
11551 
11552 
11553 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) {
11554  HandleScope scope(isolate);
11555  ASSERT(args.length() == 0);
11556 
11557 #ifdef DEBUG
11558  // Print the scopes for the top frame.
11559  StackFrameLocator locator;
11560  JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
11561  for (ScopeIterator it(isolate, frame, 0);
11562  !it.Done();
11563  it.Next()) {
11564  it.DebugPrint();
11565  }
11566 #endif
11567  return isolate->heap()->undefined_value();
11568 }
11569 
11570 
11571 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadCount) {
11572  HandleScope scope(isolate);
11573  ASSERT(args.length() == 1);
11574 
11575  // Check arguments.
11576  Object* result;
11577  { MaybeObject* maybe_result = Runtime_CheckExecutionState(
11578  RUNTIME_ARGUMENTS(isolate, args));
11579  if (!maybe_result->ToObject(&result)) return maybe_result;
11580  }
11581 
11582  // Count all archived V8 threads.
11583  int n = 0;
11584  for (ThreadState* thread =
11585  isolate->thread_manager()->FirstThreadStateInUse();
11586  thread != NULL;
11587  thread = thread->Next()) {
11588  n++;
11589  }
11590 
11591  // Total number of threads is current thread and archived threads.
11592  return Smi::FromInt(n + 1);
11593 }
11594 
11595 
11596 static const int kThreadDetailsCurrentThreadIndex = 0;
11597 static const int kThreadDetailsThreadIdIndex = 1;
11598 static const int kThreadDetailsSize = 2;
11599 
11600 // Return an array with thread details
11601 // args[0]: number: break id
11602 // args[1]: number: thread index
11603 //
11604 // The array returned contains the following information:
11605 // 0: Is current thread?
11606 // 1: Thread id
11607 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadDetails) {
11608  HandleScope scope(isolate);
11609  ASSERT(args.length() == 2);
11610 
11611  // Check arguments.
11612  Object* check;
11613  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11614  RUNTIME_ARGUMENTS(isolate, args));
11615  if (!maybe_check->ToObject(&check)) return maybe_check;
11616  }
11617  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
11618 
11619  // Allocate array for result.
11620  Handle<FixedArray> details =
11621  isolate->factory()->NewFixedArray(kThreadDetailsSize);
11622 
11623  // Thread index 0 is current thread.
11624  if (index == 0) {
11625  // Fill the details.
11626  details->set(kThreadDetailsCurrentThreadIndex,
11627  isolate->heap()->true_value());
11628  details->set(kThreadDetailsThreadIdIndex,
11629  Smi::FromInt(ThreadId::Current().ToInteger()));
11630  } else {
11631  // Find the thread with the requested index.
11632  int n = 1;
11633  ThreadState* thread =
11634  isolate->thread_manager()->FirstThreadStateInUse();
11635  while (index != n && thread != NULL) {
11636  thread = thread->Next();
11637  n++;
11638  }
11639  if (thread == NULL) {
11640  return isolate->heap()->undefined_value();
11641  }
11642 
11643  // Fill the details.
11644  details->set(kThreadDetailsCurrentThreadIndex,
11645  isolate->heap()->false_value());
11646  details->set(kThreadDetailsThreadIdIndex,
11647  Smi::FromInt(thread->id().ToInteger()));
11648  }
11649 
11650  // Convert to JS array and return.
11651  return *isolate->factory()->NewJSArrayWithElements(details);
11652 }
11653 
11654 
11655 // Sets the disable break state
11656 // args[0]: disable break state
11657 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDisableBreak) {
11658  HandleScope scope(isolate);
11659  ASSERT(args.length() == 1);
11660  CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 0);
11661  isolate->debug()->set_disable_break(disable_break);
11662  return isolate->heap()->undefined_value();
11663 }
11664 
11665 
11666 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetBreakLocations) {
11667  HandleScope scope(isolate);
11668  ASSERT(args.length() == 1);
11669 
11670  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
11671  Handle<SharedFunctionInfo> shared(fun->shared());
11672  // Find the number of break points
11673  Handle<Object> break_locations = Debug::GetSourceBreakLocations(shared);
11674  if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
11675  // Return array as JS array
11676  return *isolate->factory()->NewJSArrayWithElements(
11677  Handle<FixedArray>::cast(break_locations));
11678 }
11679 
11680 
11681 // Set a break point in a function
11682 // args[0]: function
11683 // args[1]: number: break source position (within the function source)
11684 // args[2]: number: break point object
11685 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFunctionBreakPoint) {
11686  HandleScope scope(isolate);
11687  ASSERT(args.length() == 3);
11688  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
11689  Handle<SharedFunctionInfo> shared(fun->shared());
11690  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
11691  RUNTIME_ASSERT(source_position >= 0);
11692  Handle<Object> break_point_object_arg = args.at<Object>(2);
11693 
11694  // Set break point.
11695  isolate->debug()->SetBreakPoint(shared, break_point_object_arg,
11696  &source_position);
11697 
11698  return Smi::FromInt(source_position);
11699 }
11700 
11701 
11703  Handle<Script> script,
11704  int position) {
11705  // Iterate the heap looking for SharedFunctionInfo generated from the
11706  // script. The inner most SharedFunctionInfo containing the source position
11707  // for the requested break point is found.
11708  // NOTE: This might require several heap iterations. If the SharedFunctionInfo
11709  // which is found is not compiled it is compiled and the heap is iterated
11710  // again as the compilation might create inner functions from the newly
11711  // compiled function and the actual requested break point might be in one of
11712  // these functions.
11713  bool done = false;
11714  // The current candidate for the source position:
11715  int target_start_position = RelocInfo::kNoPosition;
11716  Handle<SharedFunctionInfo> target;
11717  while (!done) {
11718  { // Extra scope for iterator and no-allocation.
11719  isolate->heap()->EnsureHeapIsIterable();
11720  AssertNoAllocation no_alloc_during_heap_iteration;
11721  HeapIterator iterator;
11722  for (HeapObject* obj = iterator.next();
11723  obj != NULL; obj = iterator.next()) {
11724  if (obj->IsSharedFunctionInfo()) {
11725  Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(obj));
11726  if (shared->script() == *script) {
11727  // If the SharedFunctionInfo found has the requested script data and
11728  // contains the source position it is a candidate.
11729  int start_position = shared->function_token_position();
11730  if (start_position == RelocInfo::kNoPosition) {
11731  start_position = shared->start_position();
11732  }
11733  if (start_position <= position &&
11734  position <= shared->end_position()) {
11735  // If there is no candidate or this function is within the current
11736  // candidate this is the new candidate.
11737  if (target.is_null()) {
11738  target_start_position = start_position;
11739  target = shared;
11740  } else {
11741  if (target_start_position == start_position &&
11742  shared->end_position() == target->end_position()) {
11743  // If a top-level function contain only one function
11744  // declartion the source for the top-level and the
11745  // function is the same. In that case prefer the non
11746  // top-level function.
11747  if (!shared->is_toplevel()) {
11748  target_start_position = start_position;
11749  target = shared;
11750  }
11751  } else if (target_start_position <= start_position &&
11752  shared->end_position() <= target->end_position()) {
11753  // This containment check includes equality as a function
11754  // inside a top-level function can share either start or end
11755  // position with the top-level function.
11756  target_start_position = start_position;
11757  target = shared;
11758  }
11759  }
11760  }
11761  }
11762  }
11763  } // End for loop.
11764  } // End No allocation scope.
11765 
11766  if (target.is_null()) {
11767  return isolate->heap()->undefined_value();
11768  }
11769 
11770  // If the candidate found is compiled we are done. NOTE: when lazy
11771  // compilation of inner functions is introduced some additional checking
11772  // needs to be done here to compile inner functions.
11773  done = target->is_compiled();
11774  if (!done) {
11775  // If the candidate is not compiled compile it to reveal any inner
11776  // functions which might contain the requested source position.
11778  }
11779  } // End while loop.
11780 
11781  return *target;
11782 }
11783 
11784 
11785 // Changes the state of a break point in a script and returns source position
11786 // where break point was set. NOTE: Regarding performance see the NOTE for
11787 // GetScriptFromScriptData.
11788 // args[0]: script to set break point in
11789 // args[1]: number: break source position (within the script source)
11790 // args[2]: number: break point object
11791 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScriptBreakPoint) {
11792  HandleScope scope(isolate);
11793  ASSERT(args.length() == 3);
11794  CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
11795  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
11796  RUNTIME_ASSERT(source_position >= 0);
11797  Handle<Object> break_point_object_arg = args.at<Object>(2);
11798 
11799  // Get the script from the script wrapper.
11800  RUNTIME_ASSERT(wrapper->value()->IsScript());
11801  Handle<Script> script(Script::cast(wrapper->value()));
11802 
11804  isolate, script, source_position);
11805  if (!result->IsUndefined()) {
11806  Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
11807  // Find position within function. The script position might be before the
11808  // source position of the first function.
11809  int position;
11810  if (shared->start_position() > source_position) {
11811  position = 0;
11812  } else {
11813  position = source_position - shared->start_position();
11814  }
11815  isolate->debug()->SetBreakPoint(shared, break_point_object_arg, &position);
11816  position += shared->start_position();
11817  return Smi::FromInt(position);
11818  }
11819  return isolate->heap()->undefined_value();
11820 }
11821 
11822 
11823 // Clear a break point
11824 // args[0]: number: break point object
11825 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearBreakPoint) {
11826  HandleScope scope(isolate);
11827  ASSERT(args.length() == 1);
11828  Handle<Object> break_point_object_arg = args.at<Object>(0);
11829 
11830  // Clear break point.
11831  isolate->debug()->ClearBreakPoint(break_point_object_arg);
11832 
11833  return isolate->heap()->undefined_value();
11834 }
11835 
11836 
11837 // Change the state of break on exceptions.
11838 // args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
11839 // args[1]: Boolean indicating on/off.
11840 RUNTIME_FUNCTION(MaybeObject*, Runtime_ChangeBreakOnException) {
11841  HandleScope scope(isolate);
11842  ASSERT(args.length() == 2);
11843  RUNTIME_ASSERT(args[0]->IsNumber());
11844  CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
11845 
11846  // If the number doesn't match an enum value, the ChangeBreakOnException
11847  // function will default to affecting caught exceptions.
11848  ExceptionBreakType type =
11849  static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
11850  // Update break point state.
11851  isolate->debug()->ChangeBreakOnException(type, enable);
11852  return isolate->heap()->undefined_value();
11853 }
11854 
11855 
11856 // Returns the state of break on exceptions
11857 // args[0]: boolean indicating uncaught exceptions
11858 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsBreakOnException) {
11859  HandleScope scope(isolate);
11860  ASSERT(args.length() == 1);
11861  RUNTIME_ASSERT(args[0]->IsNumber());
11862 
11863  ExceptionBreakType type =
11864  static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
11865  bool result = isolate->debug()->IsBreakOnException(type);
11866  return Smi::FromInt(result);
11867 }
11868 
11869 
11870 // Prepare for stepping
11871 // args[0]: break id for checking execution state
11872 // args[1]: step action from the enumeration StepAction
11873 // args[2]: number of times to perform the step, for step out it is the number
11874 // of frames to step down.
11875 RUNTIME_FUNCTION(MaybeObject*, Runtime_PrepareStep) {
11876  HandleScope scope(isolate);
11877  ASSERT(args.length() == 3);
11878  // Check arguments.
11879  Object* check;
11880  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11881  RUNTIME_ARGUMENTS(isolate, args));
11882  if (!maybe_check->ToObject(&check)) return maybe_check;
11883  }
11884  if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
11885  return isolate->Throw(isolate->heap()->illegal_argument_symbol());
11886  }
11887 
11888  // Get the step action and check validity.
11889  StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
11890  if (step_action != StepIn &&
11891  step_action != StepNext &&
11892  step_action != StepOut &&
11893  step_action != StepInMin &&
11894  step_action != StepMin) {
11895  return isolate->Throw(isolate->heap()->illegal_argument_symbol());
11896  }
11897 
11898  // Get the number of steps.
11899  int step_count = NumberToInt32(args[2]);
11900  if (step_count < 1) {
11901  return isolate->Throw(isolate->heap()->illegal_argument_symbol());
11902  }
11903 
11904  // Clear all current stepping setup.
11905  isolate->debug()->ClearStepping();
11906 
11907  // Prepare step.
11908  isolate->debug()->PrepareStep(static_cast<StepAction>(step_action),
11909  step_count);
11910  return isolate->heap()->undefined_value();
11911 }
11912 
11913 
11914 // Clear all stepping set by PrepareStep.
11915 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) {
11916  HandleScope scope(isolate);
11917  ASSERT(args.length() == 0);
11918  isolate->debug()->ClearStepping();
11919  return isolate->heap()->undefined_value();
11920 }
11921 
11922 
11923 // Creates a copy of the with context chain. The copy of the context chain is
11924 // is linked to the function context supplied.
11925 static Handle<Context> CopyNestedScopeContextChain(Isolate* isolate,
11926  Handle<JSFunction> function,
11927  Handle<Context> base,
11928  JavaScriptFrame* frame,
11929  int inlined_jsframe_index) {
11930  HandleScope scope(isolate);
11931  List<Handle<ScopeInfo> > scope_chain;
11932  List<Handle<Context> > context_chain;
11933 
11934  ScopeIterator it(isolate, frame, inlined_jsframe_index);
11935  for (; it.Type() != ScopeIterator::ScopeTypeGlobal &&
11936  it.Type() != ScopeIterator::ScopeTypeLocal ; it.Next()) {
11937  ASSERT(!it.Done());
11938  scope_chain.Add(it.CurrentScopeInfo());
11939  context_chain.Add(it.CurrentContext());
11940  }
11941 
11942  // At the end of the chain. Return the base context to link to.
11943  Handle<Context> context = base;
11944 
11945  // Iteratively copy and or materialize the nested contexts.
11946  while (!scope_chain.is_empty()) {
11947  Handle<ScopeInfo> scope_info = scope_chain.RemoveLast();
11948  Handle<Context> current = context_chain.RemoveLast();
11949  ASSERT(!(scope_info->HasContext() & current.is_null()));
11950 
11951  if (scope_info->Type() == CATCH_SCOPE) {
11952  Handle<String> name(String::cast(current->extension()));
11953  Handle<Object> thrown_object(current->get(Context::THROWN_OBJECT_INDEX));
11954  context =
11955  isolate->factory()->NewCatchContext(function,
11956  context,
11957  name,
11958  thrown_object);
11959  } else if (scope_info->Type() == BLOCK_SCOPE) {
11960  // Materialize the contents of the block scope into a JSObject.
11961  Handle<JSObject> block_scope_object =
11962  MaterializeBlockScope(isolate, current);
11963  if (block_scope_object.is_null()) {
11964  return Handle<Context>::null();
11965  }
11966  // Allocate a new function context for the debug evaluation and set the
11967  // extension object.
11968  Handle<Context> new_context =
11969  isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS,
11970  function);
11971  new_context->set_extension(*block_scope_object);
11972  new_context->set_previous(*context);
11973  context = new_context;
11974  } else {
11975  ASSERT(scope_info->Type() == WITH_SCOPE);
11976  ASSERT(current->IsWithContext());
11977  Handle<JSObject> extension(JSObject::cast(current->extension()));
11978  context =
11979  isolate->factory()->NewWithContext(function, context, extension);
11980  }
11981  }
11982 
11983  return scope.CloseAndEscape(context);
11984 }
11985 
11986 
11987 // Helper function to find or create the arguments object for
11988 // Runtime_DebugEvaluate.
11989 static Handle<Object> GetArgumentsObject(Isolate* isolate,
11990  JavaScriptFrame* frame,
11991  FrameInspector* frame_inspector,
11992  Handle<ScopeInfo> scope_info,
11993  Handle<Context> function_context) {
11994  // Try to find the value of 'arguments' to pass as parameter. If it is not
11995  // found (that is the debugged function does not reference 'arguments' and
11996  // does not support eval) then create an 'arguments' object.
11997  int index;
11998  if (scope_info->StackLocalCount() > 0) {
11999  index = scope_info->StackSlotIndex(isolate->heap()->arguments_symbol());
12000  if (index != -1) {
12001  return Handle<Object>(frame->GetExpression(index), isolate);
12002  }
12003  }
12004 
12005  if (scope_info->HasHeapAllocatedLocals()) {
12006  VariableMode mode;
12007  InitializationFlag init_flag;
12008  index = scope_info->ContextSlotIndex(
12009  isolate->heap()->arguments_symbol(), &mode, &init_flag);
12010  if (index != -1) {
12011  return Handle<Object>(function_context->get(index), isolate);
12012  }
12013  }
12014 
12015  Handle<JSFunction> function(JSFunction::cast(frame_inspector->GetFunction()));
12016  int length = frame_inspector->GetParametersCount();
12017  Handle<JSObject> arguments =
12018  isolate->factory()->NewArgumentsObject(function, length);
12019  Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
12020 
12021  AssertNoAllocation no_gc;
12022  WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
12023  for (int i = 0; i < length; i++) {
12024  array->set(i, frame_inspector->GetParameter(i), mode);
12025  }
12026  arguments->set_elements(*array);
12027  return arguments;
12028 }
12029 
12030 
12031 static const char kSourceStr[] =
12032  "(function(arguments,__source__){return eval(__source__);})";
12033 
12034 
12035 // Evaluate a piece of JavaScript in the context of a stack frame for
12036 // debugging. This is accomplished by creating a new context which in its
12037 // extension part has all the parameters and locals of the function on the
12038 // stack frame. A function which calls eval with the code to evaluate is then
12039 // compiled in this context and called in this context. As this context
12040 // replaces the context of the function on the stack frame a new (empty)
12041 // function is created as well to be used as the closure for the context.
12042 // This function and the context acts as replacements for the function on the
12043 // stack frame presenting the same view of the values of parameters and
12044 // local variables as if the piece of JavaScript was evaluated at the point
12045 // where the function on the stack frame is currently stopped.
12046 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
12047  HandleScope scope(isolate);
12048 
12049  // Check the execution state and decode arguments frame and source to be
12050  // evaluated.
12051  ASSERT(args.length() == 6);
12052  Object* check_result;
12053  { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(
12054  RUNTIME_ARGUMENTS(isolate, args));
12055  if (!maybe_check_result->ToObject(&check_result)) {
12056  return maybe_check_result;
12057  }
12058  }
12059  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12060  CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12061  CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
12062  CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
12063  Handle<Object> additional_context(args[5]);
12064 
12065  // Handle the processing of break.
12066  DisableBreak disable_break_save(disable_break);
12067 
12068  // Get the frame where the debugging is performed.
12069  StackFrame::Id id = UnwrapFrameId(wrapped_id);
12070  JavaScriptFrameIterator it(isolate, id);
12071  JavaScriptFrame* frame = it.frame();
12072  FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
12073  Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
12074  Handle<ScopeInfo> scope_info(function->shared()->scope_info());
12075 
12076  // Traverse the saved contexts chain to find the active context for the
12077  // selected frame.
12078  SaveContext* save = FindSavedContextForFrame(isolate, frame);
12079 
12080  SaveContext savex(isolate);
12081  isolate->set_context(*(save->context()));
12082 
12083  // Create the (empty) function replacing the function on the stack frame for
12084  // the purpose of evaluating in the context created below. It is important
12085  // that this function does not describe any parameters and local variables
12086  // in the context. If it does then this will cause problems with the lookup
12087  // in Context::Lookup, where context slots for parameters and local variables
12088  // are looked at before the extension object.
12089  Handle<JSFunction> go_between =
12090  isolate->factory()->NewFunction(isolate->factory()->empty_string(),
12091  isolate->factory()->undefined_value());
12092  go_between->set_context(function->context());
12093 #ifdef DEBUG
12094  Handle<ScopeInfo> go_between_scope_info(go_between->shared()->scope_info());
12095  ASSERT(go_between_scope_info->ParameterCount() == 0);
12096  ASSERT(go_between_scope_info->ContextLocalCount() == 0);
12097 #endif
12098 
12099  // Materialize the content of the local scope into a JSObject.
12100  Handle<JSObject> local_scope = MaterializeLocalScopeWithFrameInspector(
12101  isolate, frame, &frame_inspector);
12102  RETURN_IF_EMPTY_HANDLE(isolate, local_scope);
12103 
12104  // Allocate a new context for the debug evaluation and set the extension
12105  // object build.
12106  Handle<Context> context =
12107  isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS,
12108  go_between);
12109  context->set_extension(*local_scope);
12110  // Copy any with contexts present and chain them in front of this context.
12111  Handle<Context> frame_context(Context::cast(frame->context()));
12112  Handle<Context> function_context;
12113  // Get the function's context if it has one.
12114  if (scope_info->HasContext()) {
12115  function_context = Handle<Context>(frame_context->declaration_context());
12116  }
12117  context = CopyNestedScopeContextChain(isolate,
12118  go_between,
12119  context,
12120  frame,
12121  inlined_jsframe_index);
12122 
12123  if (additional_context->IsJSObject()) {
12124  Handle<JSObject> extension = Handle<JSObject>::cast(additional_context);
12125  context =
12126  isolate->factory()->NewWithContext(go_between, context, extension);
12127  }
12128 
12129  // Wrap the evaluation statement in a new function compiled in the newly
12130  // created context. The function has one parameter which has to be called
12131  // 'arguments'. This it to have access to what would have been 'arguments' in
12132  // the function being debugged.
12133  // function(arguments,__source__) {return eval(__source__);}
12134 
12135  Handle<String> function_source =
12136  isolate->factory()->NewStringFromAscii(
12137  Vector<const char>(kSourceStr, sizeof(kSourceStr) - 1));
12138 
12139  // Currently, the eval code will be executed in non-strict mode,
12140  // even in the strict code context.
12141  Handle<SharedFunctionInfo> shared =
12142  Compiler::CompileEval(function_source,
12143  context,
12144  context->IsGlobalContext(),
12145  CLASSIC_MODE,
12146  RelocInfo::kNoPosition);
12147  if (shared.is_null()) return Failure::Exception();
12148  Handle<JSFunction> compiled_function =
12149  isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context);
12150 
12151  // Invoke the result of the compilation to get the evaluation function.
12152  bool has_pending_exception;
12153  Handle<Object> receiver(frame->receiver(), isolate);
12154  Handle<Object> evaluation_function =
12155  Execution::Call(compiled_function, receiver, 0, NULL,
12156  &has_pending_exception);
12157  if (has_pending_exception) return Failure::Exception();
12158 
12159  Handle<Object> arguments = GetArgumentsObject(isolate,
12160  frame,
12161  &frame_inspector,
12162  scope_info,
12163  function_context);
12164 
12165  // Invoke the evaluation function and return the result.
12166  Handle<Object> argv[] = { arguments, source };
12167  Handle<Object> result =
12168  Execution::Call(Handle<JSFunction>::cast(evaluation_function),
12169  receiver,
12170  ARRAY_SIZE(argv),
12171  argv,
12172  &has_pending_exception);
12173  if (has_pending_exception) return Failure::Exception();
12174 
12175  // Skip the global proxy as it has no properties and always delegates to the
12176  // real global object.
12177  if (result->IsJSGlobalProxy()) {
12178  result = Handle<JSObject>(JSObject::cast(result->GetPrototype()));
12179  }
12180 
12181  return *result;
12182 }
12183 
12184 
12185 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) {
12186  HandleScope scope(isolate);
12187 
12188  // Check the execution state and decode arguments frame and source to be
12189  // evaluated.
12190  ASSERT(args.length() == 4);
12191  Object* check_result;
12192  { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(
12193  RUNTIME_ARGUMENTS(isolate, args));
12194  if (!maybe_check_result->ToObject(&check_result)) {
12195  return maybe_check_result;
12196  }
12197  }
12198  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
12199  CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
12200  Handle<Object> additional_context(args[3]);
12201 
12202  // Handle the processing of break.
12203  DisableBreak disable_break_save(disable_break);
12204 
12205  // Enter the top context from before the debugger was invoked.
12206  SaveContext save(isolate);
12207  SaveContext* top = &save;
12208  while (top != NULL && *top->context() == *isolate->debug()->debug_context()) {
12209  top = top->prev();
12210  }
12211  if (top != NULL) {
12212  isolate->set_context(*top->context());
12213  }
12214 
12215  // Get the global context now set to the top context from before the
12216  // debugger was invoked.
12217  Handle<Context> context = isolate->global_context();
12218 
12219  bool is_global = true;
12220 
12221  if (additional_context->IsJSObject()) {
12222  // Create a new with context with the additional context information between
12223  // the context of the debugged function and the eval code to be executed.
12224  context = isolate->factory()->NewWithContext(
12225  Handle<JSFunction>(context->closure()),
12226  context,
12227  Handle<JSObject>::cast(additional_context));
12228  is_global = false;
12229  }
12230 
12231  // Compile the source to be evaluated.
12232  // Currently, the eval code will be executed in non-strict mode,
12233  // even in the strict code context.
12234  Handle<SharedFunctionInfo> shared =
12235  Compiler::CompileEval(source,
12236  context,
12237  is_global,
12238  CLASSIC_MODE,
12239  RelocInfo::kNoPosition);
12240  if (shared.is_null()) return Failure::Exception();
12241  Handle<JSFunction> compiled_function =
12242  Handle<JSFunction>(
12243  isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
12244  context));
12245 
12246  // Invoke the result of the compilation to get the evaluation function.
12247  bool has_pending_exception;
12248  Handle<Object> receiver = isolate->global();
12249  Handle<Object> result =
12250  Execution::Call(compiled_function, receiver, 0, NULL,
12251  &has_pending_exception);
12252  // Clear the oneshot breakpoints so that the debugger does not step further.
12253  isolate->debug()->ClearStepping();
12254  if (has_pending_exception) return Failure::Exception();
12255  return *result;
12256 }
12257 
12258 
12259 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetLoadedScripts) {
12260  HandleScope scope(isolate);
12261  ASSERT(args.length() == 0);
12262 
12263  // Fill the script objects.
12264  Handle<FixedArray> instances = isolate->debug()->GetLoadedScripts();
12265 
12266  // Convert the script objects to proper JS objects.
12267  for (int i = 0; i < instances->length(); i++) {
12268  Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
12269  // Get the script wrapper in a local handle before calling GetScriptWrapper,
12270  // because using
12271  // instances->set(i, *GetScriptWrapper(script))
12272  // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
12273  // already have dereferenced the instances handle.
12274  Handle<JSValue> wrapper = GetScriptWrapper(script);
12275  instances->set(i, *wrapper);
12276  }
12277 
12278  // Return result as a JS array.
12279  Handle<JSObject> result =
12280  isolate->factory()->NewJSObject(isolate->array_function());
12281  isolate->factory()->SetContent(Handle<JSArray>::cast(result), instances);
12282  return *result;
12283 }
12284 
12285 
12286 // Helper function used by Runtime_DebugReferencedBy below.
12287 static int DebugReferencedBy(HeapIterator* iterator,
12288  JSObject* target,
12289  Object* instance_filter, int max_references,
12290  FixedArray* instances, int instances_size,
12291  JSFunction* arguments_function) {
12292  NoHandleAllocation ha;
12293  AssertNoAllocation no_alloc;
12294 
12295  // Iterate the heap.
12296  int count = 0;
12297  JSObject* last = NULL;
12298  HeapObject* heap_obj = NULL;
12299  while (((heap_obj = iterator->next()) != NULL) &&
12300  (max_references == 0 || count < max_references)) {
12301  // Only look at all JSObjects.
12302  if (heap_obj->IsJSObject()) {
12303  // Skip context extension objects and argument arrays as these are
12304  // checked in the context of functions using them.
12305  JSObject* obj = JSObject::cast(heap_obj);
12306  if (obj->IsJSContextExtensionObject() ||
12307  obj->map()->constructor() == arguments_function) {
12308  continue;
12309  }
12310 
12311  // Check if the JS object has a reference to the object looked for.
12312  if (obj->ReferencesObject(target)) {
12313  // Check instance filter if supplied. This is normally used to avoid
12314  // references from mirror objects (see Runtime_IsInPrototypeChain).
12315  if (!instance_filter->IsUndefined()) {
12316  Object* V = obj;
12317  while (true) {
12318  Object* prototype = V->GetPrototype();
12319  if (prototype->IsNull()) {
12320  break;
12321  }
12322  if (instance_filter == prototype) {
12323  obj = NULL; // Don't add this object.
12324  break;
12325  }
12326  V = prototype;
12327  }
12328  }
12329 
12330  if (obj != NULL) {
12331  // Valid reference found add to instance array if supplied an update
12332  // count.
12333  if (instances != NULL && count < instances_size) {
12334  instances->set(count, obj);
12335  }
12336  last = obj;
12337  count++;
12338  }
12339  }
12340  }
12341  }
12342 
12343  // Check for circular reference only. This can happen when the object is only
12344  // referenced from mirrors and has a circular reference in which case the
12345  // object is not really alive and would have been garbage collected if not
12346  // referenced from the mirror.
12347  if (count == 1 && last == target) {
12348  count = 0;
12349  }
12350 
12351  // Return the number of referencing objects found.
12352  return count;
12353 }
12354 
12355 
12356 // Scan the heap for objects with direct references to an object
12357 // args[0]: the object to find references to
12358 // args[1]: constructor function for instances to exclude (Mirror)
12359 // args[2]: the the maximum number of objects to return
12360 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugReferencedBy) {
12361  ASSERT(args.length() == 3);
12362 
12363  // First perform a full GC in order to avoid references from dead objects.
12364  isolate->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
12365  "%DebugReferencedBy");
12366  // The heap iterator reserves the right to do a GC to make the heap iterable.
12367  // Due to the GC above we know it won't need to do that, but it seems cleaner
12368  // to get the heap iterator constructed before we start having unprotected
12369  // Object* locals that are not protected by handles.
12370 
12371  // Check parameters.
12372  CONVERT_ARG_CHECKED(JSObject, target, 0);
12373  Object* instance_filter = args[1];
12374  RUNTIME_ASSERT(instance_filter->IsUndefined() ||
12375  instance_filter->IsJSObject());
12376  CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
12377  RUNTIME_ASSERT(max_references >= 0);
12378 
12379 
12380  // Get the constructor function for context extension and arguments array.
12381  JSObject* arguments_boilerplate =
12382  isolate->context()->global_context()->arguments_boilerplate();
12383  JSFunction* arguments_function =
12384  JSFunction::cast(arguments_boilerplate->map()->constructor());
12385 
12386  // Get the number of referencing objects.
12387  int count;
12388  HeapIterator heap_iterator;
12389  count = DebugReferencedBy(&heap_iterator,
12390  target, instance_filter, max_references,
12391  NULL, 0, arguments_function);
12392 
12393  // Allocate an array to hold the result.
12394  Object* object;
12395  { MaybeObject* maybe_object = isolate->heap()->AllocateFixedArray(count);
12396  if (!maybe_object->ToObject(&object)) return maybe_object;
12397  }
12398  FixedArray* instances = FixedArray::cast(object);
12399 
12400  // Fill the referencing objects.
12401  // AllocateFixedArray above does not make the heap non-iterable.
12402  ASSERT(HEAP->IsHeapIterable());
12403  HeapIterator heap_iterator2;
12404  count = DebugReferencedBy(&heap_iterator2,
12405  target, instance_filter, max_references,
12406  instances, count, arguments_function);
12407 
12408  // Return result as JS array.
12409  Object* result;
12410  MaybeObject* maybe_result = isolate->heap()->AllocateJSObject(
12411  isolate->context()->global_context()->array_function());
12412  if (!maybe_result->ToObject(&result)) return maybe_result;
12413  return JSArray::cast(result)->SetContent(instances);
12414 }
12415 
12416 
12417 // Helper function used by Runtime_DebugConstructedBy below.
12418 static int DebugConstructedBy(HeapIterator* iterator,
12419  JSFunction* constructor,
12420  int max_references,
12421  FixedArray* instances,
12422  int instances_size) {
12423  AssertNoAllocation no_alloc;
12424 
12425  // Iterate the heap.
12426  int count = 0;
12427  HeapObject* heap_obj = NULL;
12428  while (((heap_obj = iterator->next()) != NULL) &&
12429  (max_references == 0 || count < max_references)) {
12430  // Only look at all JSObjects.
12431  if (heap_obj->IsJSObject()) {
12432  JSObject* obj = JSObject::cast(heap_obj);
12433  if (obj->map()->constructor() == constructor) {
12434  // Valid reference found add to instance array if supplied an update
12435  // count.
12436  if (instances != NULL && count < instances_size) {
12437  instances->set(count, obj);
12438  }
12439  count++;
12440  }
12441  }
12442  }
12443 
12444  // Return the number of referencing objects found.
12445  return count;
12446 }
12447 
12448 
12449 // Scan the heap for objects constructed by a specific function.
12450 // args[0]: the constructor to find instances of
12451 // args[1]: the the maximum number of objects to return
12452 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugConstructedBy) {
12453  ASSERT(args.length() == 2);
12454 
12455  // First perform a full GC in order to avoid dead objects.
12456  isolate->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
12457  "%DebugConstructedBy");
12458 
12459  // Check parameters.
12460  CONVERT_ARG_CHECKED(JSFunction, constructor, 0);
12461  CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
12462  RUNTIME_ASSERT(max_references >= 0);
12463 
12464  // Get the number of referencing objects.
12465  int count;
12466  HeapIterator heap_iterator;
12467  count = DebugConstructedBy(&heap_iterator,
12468  constructor,
12469  max_references,
12470  NULL,
12471  0);
12472 
12473  // Allocate an array to hold the result.
12474  Object* object;
12475  { MaybeObject* maybe_object = isolate->heap()->AllocateFixedArray(count);
12476  if (!maybe_object->ToObject(&object)) return maybe_object;
12477  }
12478  FixedArray* instances = FixedArray::cast(object);
12479 
12480  ASSERT(HEAP->IsHeapIterable());
12481  // Fill the referencing objects.
12482  HeapIterator heap_iterator2;
12483  count = DebugConstructedBy(&heap_iterator2,
12484  constructor,
12485  max_references,
12486  instances,
12487  count);
12488 
12489  // Return result as JS array.
12490  Object* result;
12491  { MaybeObject* maybe_result = isolate->heap()->AllocateJSObject(
12492  isolate->context()->global_context()->array_function());
12493  if (!maybe_result->ToObject(&result)) return maybe_result;
12494  }
12495  return JSArray::cast(result)->SetContent(instances);
12496 }
12497 
12498 
12499 // Find the effective prototype object as returned by __proto__.
12500 // args[0]: the object to find the prototype for.
12501 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPrototype) {
12502  ASSERT(args.length() == 1);
12503 
12504  CONVERT_ARG_CHECKED(JSObject, obj, 0);
12505 
12506  // Use the __proto__ accessor.
12507  return Accessors::ObjectPrototype.getter(obj, NULL);
12508 }
12509 
12510 
12511 // Patches script source (should be called upon BeforeCompile event).
12512 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugSetScriptSource) {
12513  HandleScope scope(isolate);
12514  ASSERT(args.length() == 2);
12515 
12516  CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
12517  Handle<String> source(String::cast(args[1]));
12518 
12519  RUNTIME_ASSERT(script_wrapper->value()->IsScript());
12520  Handle<Script> script(Script::cast(script_wrapper->value()));
12521 
12522  int compilation_state = Smi::cast(script->compilation_state())->value();
12523  RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL);
12524  script->set_source(*source);
12525 
12526  return isolate->heap()->undefined_value();
12527 }
12528 
12529 
12530 RUNTIME_FUNCTION(MaybeObject*, Runtime_SystemBreak) {
12531  ASSERT(args.length() == 0);
12532  CPU::DebugBreak();
12533  return isolate->heap()->undefined_value();
12534 }
12535 
12536 
12537 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleFunction) {
12538 #ifdef DEBUG
12539  HandleScope scope(isolate);
12540  ASSERT(args.length() == 1);
12541  // Get the function and make sure it is compiled.
12542  CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
12544  return Failure::Exception();
12545  }
12546  func->code()->PrintLn();
12547 #endif // DEBUG
12548  return isolate->heap()->undefined_value();
12549 }
12550 
12551 
12552 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleConstructor) {
12553 #ifdef DEBUG
12554  HandleScope scope(isolate);
12555  ASSERT(args.length() == 1);
12556  // Get the function and make sure it is compiled.
12557  CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
12559  return Failure::Exception();
12560  }
12561  func->shared()->construct_stub()->PrintLn();
12562 #endif // DEBUG
12563  return isolate->heap()->undefined_value();
12564 }
12565 
12566 
12567 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetInferredName) {
12568  NoHandleAllocation ha;
12569  ASSERT(args.length() == 1);
12570 
12571  CONVERT_ARG_CHECKED(JSFunction, f, 0);
12572  return f->shared()->inferred_name();
12573 }
12574 
12575 
12576 static int FindSharedFunctionInfosForScript(HeapIterator* iterator,
12577  Script* script,
12578  FixedArray* buffer) {
12579  AssertNoAllocation no_allocations;
12580  int counter = 0;
12581  int buffer_size = buffer->length();
12582  for (HeapObject* obj = iterator->next();
12583  obj != NULL;
12584  obj = iterator->next()) {
12585  ASSERT(obj != NULL);
12586  if (!obj->IsSharedFunctionInfo()) {
12587  continue;
12588  }
12589  SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
12590  if (shared->script() != script) {
12591  continue;
12592  }
12593  if (counter < buffer_size) {
12594  buffer->set(counter, shared);
12595  }
12596  counter++;
12597  }
12598  return counter;
12599 }
12600 
12601 // For a script finds all SharedFunctionInfo's in the heap that points
12602 // to this script. Returns JSArray of SharedFunctionInfo wrapped
12603 // in OpaqueReferences.
12604 RUNTIME_FUNCTION(MaybeObject*,
12605  Runtime_LiveEditFindSharedFunctionInfosForScript) {
12606  ASSERT(args.length() == 1);
12607  HandleScope scope(isolate);
12608  CONVERT_ARG_CHECKED(JSValue, script_value, 0);
12609 
12610 
12611  Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
12612 
12613  const int kBufferSize = 32;
12614 
12615  Handle<FixedArray> array;
12616  array = isolate->factory()->NewFixedArray(kBufferSize);
12617  int number;
12618  {
12619  isolate->heap()->EnsureHeapIsIterable();
12620  AssertNoAllocation no_allocations;
12621  HeapIterator heap_iterator;
12622  Script* scr = *script;
12623  FixedArray* arr = *array;
12624  number = FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
12625  }
12626  if (number > kBufferSize) {
12627  array = isolate->factory()->NewFixedArray(number);
12628  isolate->heap()->EnsureHeapIsIterable();
12629  AssertNoAllocation no_allocations;
12630  HeapIterator heap_iterator;
12631  Script* scr = *script;
12632  FixedArray* arr = *array;
12633  FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
12634  }
12635 
12636  Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array);
12637  result->set_length(Smi::FromInt(number));
12638 
12639  LiveEdit::WrapSharedFunctionInfos(result);
12640 
12641  return *result;
12642 }
12643 
12644 // For a script calculates compilation information about all its functions.
12645 // The script source is explicitly specified by the second argument.
12646 // The source of the actual script is not used, however it is important that
12647 // all generated code keeps references to this particular instance of script.
12648 // Returns a JSArray of compilation infos. The array is ordered so that
12649 // each function with all its descendant is always stored in a continues range
12650 // with the function itself going first. The root function is a script function.
12651 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditGatherCompileInfo) {
12652  ASSERT(args.length() == 2);
12653  HandleScope scope(isolate);
12654  CONVERT_ARG_CHECKED(JSValue, script, 0);
12655  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
12656  Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
12657 
12658  JSArray* result = LiveEdit::GatherCompileInfo(script_handle, source);
12659 
12660  if (isolate->has_pending_exception()) {
12661  return Failure::Exception();
12662  }
12663 
12664  return result;
12665 }
12666 
12667 // Changes the source of the script to a new_source.
12668 // If old_script_name is provided (i.e. is a String), also creates a copy of
12669 // the script with its original source and sends notification to debugger.
12670 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceScript) {
12671  ASSERT(args.length() == 3);
12672  HandleScope scope(isolate);
12673  CONVERT_ARG_CHECKED(JSValue, original_script_value, 0);
12674  CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
12675  Handle<Object> old_script_name(args[2], isolate);
12676 
12677  RUNTIME_ASSERT(original_script_value->value()->IsScript());
12678  Handle<Script> original_script(Script::cast(original_script_value->value()));
12679 
12680  Object* old_script = LiveEdit::ChangeScriptSource(original_script,
12681  new_source,
12682  old_script_name);
12683 
12684  if (old_script->IsScript()) {
12685  Handle<Script> script_handle(Script::cast(old_script));
12686  return *(GetScriptWrapper(script_handle));
12687  } else {
12688  return isolate->heap()->null_value();
12689  }
12690 }
12691 
12692 
12693 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSourceUpdated) {
12694  ASSERT(args.length() == 1);
12695  HandleScope scope(isolate);
12696  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 0);
12697  return LiveEdit::FunctionSourceUpdated(shared_info);
12698 }
12699 
12700 
12701 // Replaces code of SharedFunctionInfo with a new one.
12702 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceFunctionCode) {
12703  ASSERT(args.length() == 2);
12704  HandleScope scope(isolate);
12705  CONVERT_ARG_HANDLE_CHECKED(JSArray, new_compile_info, 0);
12706  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 1);
12707 
12708  return LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
12709 }
12710 
12711 // Connects SharedFunctionInfo to another script.
12712 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSetScript) {
12713  ASSERT(args.length() == 2);
12714  HandleScope scope(isolate);
12715  Handle<Object> function_object(args[0], isolate);
12716  Handle<Object> script_object(args[1], isolate);
12717 
12718  if (function_object->IsJSValue()) {
12719  Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
12720  if (script_object->IsJSValue()) {
12721  RUNTIME_ASSERT(JSValue::cast(*script_object)->value()->IsScript());
12722  Script* script = Script::cast(JSValue::cast(*script_object)->value());
12723  script_object = Handle<Object>(script, isolate);
12724  }
12725 
12726  LiveEdit::SetFunctionScript(function_wrapper, script_object);
12727  } else {
12728  // Just ignore this. We may not have a SharedFunctionInfo for some functions
12729  // and we check it in this function.
12730  }
12731 
12732  return isolate->heap()->undefined_value();
12733 }
12734 
12735 
12736 // In a code of a parent function replaces original function as embedded object
12737 // with a substitution one.
12738 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceRefToNestedFunction) {
12739  ASSERT(args.length() == 3);
12740  HandleScope scope(isolate);
12741 
12742  CONVERT_ARG_HANDLE_CHECKED(JSValue, parent_wrapper, 0);
12743  CONVERT_ARG_HANDLE_CHECKED(JSValue, orig_wrapper, 1);
12744  CONVERT_ARG_HANDLE_CHECKED(JSValue, subst_wrapper, 2);
12745 
12746  LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper,
12747  subst_wrapper);
12748 
12749  return isolate->heap()->undefined_value();
12750 }
12751 
12752 
12753 // Updates positions of a shared function info (first parameter) according
12754 // to script source change. Text change is described in second parameter as
12755 // array of groups of 3 numbers:
12756 // (change_begin, change_end, change_end_new_position).
12757 // Each group describes a change in text; groups are sorted by change_begin.
12758 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditPatchFunctionPositions) {
12759  ASSERT(args.length() == 2);
12760  HandleScope scope(isolate);
12761  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
12762  CONVERT_ARG_HANDLE_CHECKED(JSArray, position_change_array, 1);
12763 
12764  return LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
12765 }
12766 
12767 
12768 // For array of SharedFunctionInfo's (each wrapped in JSValue)
12769 // checks that none of them have activations on stacks (of any thread).
12770 // Returns array of the same length with corresponding results of
12771 // LiveEdit::FunctionPatchabilityStatus type.
12772 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCheckAndDropActivations) {
12773  ASSERT(args.length() == 2);
12774  HandleScope scope(isolate);
12775  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
12776  CONVERT_BOOLEAN_ARG_CHECKED(do_drop, 1);
12777 
12778  return *LiveEdit::CheckAndDropActivations(shared_array, do_drop,
12779  isolate->zone());
12780 }
12781 
12782 // Compares 2 strings line-by-line, then token-wise and returns diff in form
12783 // of JSArray of triplets (pos1, pos1_end, pos2_end) describing list
12784 // of diff chunks.
12785 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCompareStrings) {
12786  ASSERT(args.length() == 2);
12787  HandleScope scope(isolate);
12788  CONVERT_ARG_HANDLE_CHECKED(String, s1, 0);
12789  CONVERT_ARG_HANDLE_CHECKED(String, s2, 1);
12790 
12791  return *LiveEdit::CompareStrings(s1, s2);
12792 }
12793 
12794 
12795 // A testing entry. Returns statement position which is the closest to
12796 // source_position.
12797 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionCodePositionFromSource) {
12798  ASSERT(args.length() == 2);
12799  HandleScope scope(isolate);
12800  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
12801  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
12802 
12803  Handle<Code> code(function->code(), isolate);
12804 
12805  if (code->kind() != Code::FUNCTION &&
12806  code->kind() != Code::OPTIMIZED_FUNCTION) {
12807  return isolate->heap()->undefined_value();
12808  }
12809 
12810  RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION));
12811  int closest_pc = 0;
12812  int distance = kMaxInt;
12813  while (!it.done()) {
12814  int statement_position = static_cast<int>(it.rinfo()->data());
12815  // Check if this break point is closer that what was previously found.
12816  if (source_position <= statement_position &&
12817  statement_position - source_position < distance) {
12818  closest_pc =
12819  static_cast<int>(it.rinfo()->pc() - code->instruction_start());
12820  distance = statement_position - source_position;
12821  // Check whether we can't get any closer.
12822  if (distance == 0) break;
12823  }
12824  it.next();
12825  }
12826 
12827  return Smi::FromInt(closest_pc);
12828 }
12829 
12830 
12831 // Calls specified function with or without entering the debugger.
12832 // This is used in unit tests to run code as if debugger is entered or simply
12833 // to have a stack with C++ frame in the middle.
12834 RUNTIME_FUNCTION(MaybeObject*, Runtime_ExecuteInDebugContext) {
12835  ASSERT(args.length() == 2);
12836  HandleScope scope(isolate);
12837  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
12838  CONVERT_BOOLEAN_ARG_CHECKED(without_debugger, 1);
12839 
12840  Handle<Object> result;
12841  bool pending_exception;
12842  {
12843  if (without_debugger) {
12844  result = Execution::Call(function, isolate->global(), 0, NULL,
12845  &pending_exception);
12846  } else {
12847  EnterDebugger enter_debugger;
12848  result = Execution::Call(function, isolate->global(), 0, NULL,
12849  &pending_exception);
12850  }
12851  }
12852  if (!pending_exception) {
12853  return *result;
12854  } else {
12855  return Failure::Exception();
12856  }
12857 }
12858 
12859 
12860 // Sets a v8 flag.
12861 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFlags) {
12862  CONVERT_ARG_CHECKED(String, arg, 0);
12863  SmartArrayPointer<char> flags =
12864  arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
12865  FlagList::SetFlagsFromString(*flags, StrLength(*flags));
12866  return isolate->heap()->undefined_value();
12867 }
12868 
12869 
12870 // Performs a GC.
12871 // Presently, it only does a full GC.
12872 RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectGarbage) {
12873  isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage");
12874  return isolate->heap()->undefined_value();
12875 }
12876 
12877 
12878 // Gets the current heap usage.
12879 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHeapUsage) {
12880  int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
12881  if (!Smi::IsValid(usage)) {
12882  return *isolate->factory()->NewNumberFromInt(usage);
12883  }
12884  return Smi::FromInt(usage);
12885 }
12886 
12887 
12888 // Captures a live object list from the present heap.
12889 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLOLEnabled) {
12890 #ifdef LIVE_OBJECT_LIST
12891  return isolate->heap()->true_value();
12892 #else
12893  return isolate->heap()->false_value();
12894 #endif
12895 }
12896 
12897 
12898 // Captures a live object list from the present heap.
12899 RUNTIME_FUNCTION(MaybeObject*, Runtime_CaptureLOL) {
12900 #ifdef LIVE_OBJECT_LIST
12901  return LiveObjectList::Capture();
12902 #else
12903  return isolate->heap()->undefined_value();
12904 #endif
12905 }
12906 
12907 
12908 // Deletes the specified live object list.
12909 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteLOL) {
12910 #ifdef LIVE_OBJECT_LIST
12911  CONVERT_SMI_ARG_CHECKED(id, 0);
12912  bool success = LiveObjectList::Delete(id);
12913  return isolate->heap()->ToBoolean(success);
12914 #else
12915  return isolate->heap()->undefined_value();
12916 #endif
12917 }
12918 
12919 
12920 // Generates the response to a debugger request for a dump of the objects
12921 // contained in the difference between the captured live object lists
12922 // specified by id1 and id2.
12923 // If id1 is 0 (i.e. not a valid lol), then the whole of lol id2 will be
12924 // dumped.
12925 RUNTIME_FUNCTION(MaybeObject*, Runtime_DumpLOL) {
12926 #ifdef LIVE_OBJECT_LIST
12927  HandleScope scope;
12928  CONVERT_SMI_ARG_CHECKED(id1, 0);
12929  CONVERT_SMI_ARG_CHECKED(id2, 1);
12930  CONVERT_SMI_ARG_CHECKED(start, 2);
12931  CONVERT_SMI_ARG_CHECKED(count, 3);
12932  CONVERT_ARG_HANDLE_CHECKED(JSObject, filter_obj, 4);
12933  EnterDebugger enter_debugger;
12934  return LiveObjectList::Dump(id1, id2, start, count, filter_obj);
12935 #else
12936  return isolate->heap()->undefined_value();
12937 #endif
12938 }
12939 
12940 
12941 // Gets the specified object as requested by the debugger.
12942 // This is only used for obj ids shown in live object lists.
12943 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObj) {
12944 #ifdef LIVE_OBJECT_LIST
12945  CONVERT_SMI_ARG_CHECKED(obj_id, 0);
12946  Object* result = LiveObjectList::GetObj(obj_id);
12947  return result;
12948 #else
12949  return isolate->heap()->undefined_value();
12950 #endif
12951 }
12952 
12953 
12954 // Gets the obj id for the specified address if valid.
12955 // This is only used for obj ids shown in live object lists.
12956 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObjId) {
12957 #ifdef LIVE_OBJECT_LIST
12958  HandleScope scope;
12959  CONVERT_ARG_HANDLE_CHECKED(String, address, 0);
12960  Object* result = LiveObjectList::GetObjId(address);
12961  return result;
12962 #else
12963  return isolate->heap()->undefined_value();
12964 #endif
12965 }
12966 
12967 
12968 // Gets the retainers that references the specified object alive.
12969 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObjRetainers) {
12970 #ifdef LIVE_OBJECT_LIST
12971  HandleScope scope;
12972  CONVERT_SMI_ARG_CHECKED(obj_id, 0);
12973  RUNTIME_ASSERT(args[1]->IsUndefined() || args[1]->IsJSObject());
12974  RUNTIME_ASSERT(args[2]->IsUndefined() || args[2]->IsBoolean());
12975  RUNTIME_ASSERT(args[3]->IsUndefined() || args[3]->IsSmi());
12976  RUNTIME_ASSERT(args[4]->IsUndefined() || args[4]->IsSmi());
12977  CONVERT_ARG_HANDLE_CHECKED(JSObject, filter_obj, 5);
12978 
12979  Handle<JSObject> instance_filter;
12980  if (args[1]->IsJSObject()) {
12981  instance_filter = args.at<JSObject>(1);
12982  }
12983  bool verbose = false;
12984  if (args[2]->IsBoolean()) {
12985  verbose = args[2]->IsTrue();
12986  }
12987  int start = 0;
12988  if (args[3]->IsSmi()) {
12989  start = args.smi_at(3);
12990  }
12991  int limit = Smi::kMaxValue;
12992  if (args[4]->IsSmi()) {
12993  limit = args.smi_at(4);
12994  }
12995 
12996  return LiveObjectList::GetObjRetainers(obj_id,
12997  instance_filter,
12998  verbose,
12999  start,
13000  limit,
13001  filter_obj);
13002 #else
13003  return isolate->heap()->undefined_value();
13004 #endif
13005 }
13006 
13007 
13008 // Gets the reference path between 2 objects.
13009 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLPath) {
13010 #ifdef LIVE_OBJECT_LIST
13011  HandleScope scope;
13012  CONVERT_SMI_ARG_CHECKED(obj_id1, 0);
13013  CONVERT_SMI_ARG_CHECKED(obj_id2, 1);
13014  RUNTIME_ASSERT(args[2]->IsUndefined() || args[2]->IsJSObject());
13015 
13016  Handle<JSObject> instance_filter;
13017  if (args[2]->IsJSObject()) {
13018  instance_filter = args.at<JSObject>(2);
13019  }
13020 
13021  Object* result =
13022  LiveObjectList::GetPath(obj_id1, obj_id2, instance_filter);
13023  return result;
13024 #else
13025  return isolate->heap()->undefined_value();
13026 #endif
13027 }
13028 
13029 
13030 // Generates the response to a debugger request for a list of all
13031 // previously captured live object lists.
13032 RUNTIME_FUNCTION(MaybeObject*, Runtime_InfoLOL) {
13033 #ifdef LIVE_OBJECT_LIST
13034  CONVERT_SMI_ARG_CHECKED(start, 0);
13035  CONVERT_SMI_ARG_CHECKED(count, 1);
13036  return LiveObjectList::Info(start, count);
13037 #else
13038  return isolate->heap()->undefined_value();
13039 #endif
13040 }
13041 
13042 
13043 // Gets a dump of the specified object as requested by the debugger.
13044 // This is only used for obj ids shown in live object lists.
13045 RUNTIME_FUNCTION(MaybeObject*, Runtime_PrintLOLObj) {
13046 #ifdef LIVE_OBJECT_LIST
13047  HandleScope scope;
13048  CONVERT_SMI_ARG_CHECKED(obj_id, 0);
13049  Object* result = LiveObjectList::PrintObj(obj_id);
13050  return result;
13051 #else
13052  return isolate->heap()->undefined_value();
13053 #endif
13054 }
13055 
13056 
13057 // Resets and releases all previously captured live object lists.
13058 RUNTIME_FUNCTION(MaybeObject*, Runtime_ResetLOL) {
13059 #ifdef LIVE_OBJECT_LIST
13061  return isolate->heap()->undefined_value();
13062 #else
13063  return isolate->heap()->undefined_value();
13064 #endif
13065 }
13066 
13067 
13068 // Generates the response to a debugger request for a summary of the types
13069 // of objects in the difference between the captured live object lists
13070 // specified by id1 and id2.
13071 // If id1 is 0 (i.e. not a valid lol), then the whole of lol id2 will be
13072 // summarized.
13073 RUNTIME_FUNCTION(MaybeObject*, Runtime_SummarizeLOL) {
13074 #ifdef LIVE_OBJECT_LIST
13075  HandleScope scope;
13076  CONVERT_SMI_ARG_CHECKED(id1, 0);
13077  CONVERT_SMI_ARG_CHECKED(id2, 1);
13078  CONVERT_ARG_HANDLE_CHECKED(JSObject, filter_obj, 2);
13079 
13080  EnterDebugger enter_debugger;
13081  return LiveObjectList::Summarize(id1, id2, filter_obj);
13082 #else
13083  return isolate->heap()->undefined_value();
13084 #endif
13085 }
13086 
13087 #endif // ENABLE_DEBUGGER_SUPPORT
13088 
13089 
13090 RUNTIME_FUNCTION(MaybeObject*, Runtime_ProfilerResume) {
13091  NoHandleAllocation ha;
13093  return isolate->heap()->undefined_value();
13094 }
13095 
13096 
13097 RUNTIME_FUNCTION(MaybeObject*, Runtime_ProfilerPause) {
13098  NoHandleAllocation ha;
13100  return isolate->heap()->undefined_value();
13101 }
13102 
13103 
13104 // Finds the script object from the script data. NOTE: This operation uses
13105 // heap traversal to find the function generated for the source position
13106 // for the requested break point. For lazily compiled functions several heap
13107 // traversals might be required rendering this operation as a rather slow
13108 // operation. However for setting break points which is normally done through
13109 // some kind of user interaction the performance is not crucial.
13110 static Handle<Object> Runtime_GetScriptFromScriptName(
13111  Handle<String> script_name) {
13112  // Scan the heap for Script objects to find the script with the requested
13113  // script data.
13114  Handle<Script> script;
13115  script_name->GetHeap()->EnsureHeapIsIterable();
13116  AssertNoAllocation no_allocation_during_heap_iteration;
13117  HeapIterator iterator;
13118  HeapObject* obj = NULL;
13119  while (script.is_null() && ((obj = iterator.next()) != NULL)) {
13120  // If a script is found check if it has the script data requested.
13121  if (obj->IsScript()) {
13122  if (Script::cast(obj)->name()->IsString()) {
13123  if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) {
13124  script = Handle<Script>(Script::cast(obj));
13125  }
13126  }
13127  }
13128  }
13129 
13130  // If no script with the requested script data is found return undefined.
13131  if (script.is_null()) return FACTORY->undefined_value();
13132 
13133  // Return the script found.
13134  return GetScriptWrapper(script);
13135 }
13136 
13137 
13138 // Get the script object from script data. NOTE: Regarding performance
13139 // see the NOTE for GetScriptFromScriptData.
13140 // args[0]: script data for the script to find the source for
13141 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScript) {
13142  HandleScope scope(isolate);
13143 
13144  ASSERT(args.length() == 1);
13145 
13146  CONVERT_ARG_CHECKED(String, script_name, 0);
13147 
13148  // Find the requested script.
13149  Handle<Object> result =
13150  Runtime_GetScriptFromScriptName(Handle<String>(script_name));
13151  return *result;
13152 }
13153 
13154 
13155 // Determines whether the given stack frame should be displayed in
13156 // a stack trace. The caller is the error constructor that asked
13157 // for the stack trace to be collected. The first time a construct
13158 // call to this function is encountered it is skipped. The seen_caller
13159 // in/out parameter is used to remember if the caller has been seen
13160 // yet.
13161 static bool ShowFrameInStackTrace(StackFrame* raw_frame,
13162  Object* caller,
13163  bool* seen_caller) {
13164  // Only display JS frames.
13165  if (!raw_frame->is_java_script()) {
13166  return false;
13167  }
13168  JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
13169  Object* raw_fun = frame->function();
13170  // Not sure when this can happen but skip it just in case.
13171  if (!raw_fun->IsJSFunction()) {
13172  return false;
13173  }
13174  if ((raw_fun == caller) && !(*seen_caller)) {
13175  *seen_caller = true;
13176  return false;
13177  }
13178  // Skip all frames until we've seen the caller.
13179  if (!(*seen_caller)) return false;
13180  // Also, skip non-visible built-in functions and any call with the builtins
13181  // object as receiver, so as to not reveal either the builtins object or
13182  // an internal function.
13183  // The --builtins-in-stack-traces command line flag allows including
13184  // internal call sites in the stack trace for debugging purposes.
13185  if (!FLAG_builtins_in_stack_traces) {
13186  JSFunction* fun = JSFunction::cast(raw_fun);
13187  if (frame->receiver()->IsJSBuiltinsObject() ||
13188  (fun->IsBuiltin() && !fun->shared()->native())) {
13189  return false;
13190  }
13191  }
13192  return true;
13193 }
13194 
13195 
13196 // Collect the raw data for a stack trace. Returns an array of 4
13197 // element segments each containing a receiver, function, code and
13198 // native code offset.
13199 RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectStackTrace) {
13200  ASSERT_EQ(args.length(), 3);
13201  CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
13202  Handle<Object> caller = args.at<Object>(1);
13203  CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[2]);
13204 
13205  HandleScope scope(isolate);
13206  Factory* factory = isolate->factory();
13207 
13208  limit = Max(limit, 0); // Ensure that limit is not negative.
13209  int initial_size = Min(limit, 10);
13210  Handle<FixedArray> elements =
13211  factory->NewFixedArrayWithHoles(initial_size * 4);
13212 
13213  StackFrameIterator iter(isolate);
13214  // If the caller parameter is a function we skip frames until we're
13215  // under it before starting to collect.
13216  bool seen_caller = !caller->IsJSFunction();
13217  int cursor = 0;
13218  int frames_seen = 0;
13219  while (!iter.done() && frames_seen < limit) {
13220  StackFrame* raw_frame = iter.frame();
13221  if (ShowFrameInStackTrace(raw_frame, *caller, &seen_caller)) {
13222  frames_seen++;
13223  JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
13224  // Set initial size to the maximum inlining level + 1 for the outermost
13225  // function.
13227  frame->Summarize(&frames);
13228  for (int i = frames.length() - 1; i >= 0; i--) {
13229  if (cursor + 4 > elements->length()) {
13230  int new_capacity = JSObject::NewElementsCapacity(elements->length());
13231  Handle<FixedArray> new_elements =
13232  factory->NewFixedArrayWithHoles(new_capacity);
13233  for (int i = 0; i < cursor; i++) {
13234  new_elements->set(i, elements->get(i));
13235  }
13236  elements = new_elements;
13237  }
13238  ASSERT(cursor + 4 <= elements->length());
13239 
13240  Handle<Object> recv = frames[i].receiver();
13241  Handle<JSFunction> fun = frames[i].function();
13242  Handle<Code> code = frames[i].code();
13243  Handle<Smi> offset(Smi::FromInt(frames[i].offset()));
13244  elements->set(cursor++, *recv);
13245  elements->set(cursor++, *fun);
13246  elements->set(cursor++, *code);
13247  elements->set(cursor++, *offset);
13248  }
13249  }
13250  iter.Advance();
13251  }
13252  Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
13253  // Capture and attach a more detailed stack trace if necessary.
13254  isolate->CaptureAndSetCurrentStackTraceFor(error_object);
13255  result->set_length(Smi::FromInt(cursor));
13256  return *result;
13257 }
13258 
13259 
13260 // Returns V8 version as a string.
13261 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetV8Version) {
13262  ASSERT_EQ(args.length(), 0);
13263 
13264  NoHandleAllocation ha;
13265 
13266  const char* version_string = v8::V8::GetVersion();
13267 
13268  return isolate->heap()->AllocateStringFromAscii(CStrVector(version_string),
13269  NOT_TENURED);
13270 }
13271 
13272 
13273 RUNTIME_FUNCTION(MaybeObject*, Runtime_Abort) {
13274  ASSERT(args.length() == 2);
13275  OS::PrintError("abort: %s\n",
13276  reinterpret_cast<char*>(args[0]) + args.smi_at(1));
13277  isolate->PrintStack();
13278  OS::Abort();
13279  UNREACHABLE();
13280  return NULL;
13281 }
13282 
13283 
13284 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFromCache) {
13285  // This is only called from codegen, so checks might be more lax.
13287  Object* key = args[1];
13288 
13289  int finger_index = cache->finger_index();
13290  Object* o = cache->get(finger_index);
13291  if (o == key) {
13292  // The fastest case: hit the same place again.
13293  return cache->get(finger_index + 1);
13294  }
13295 
13296  for (int i = finger_index - 2;
13298  i -= 2) {
13299  o = cache->get(i);
13300  if (o == key) {
13301  cache->set_finger_index(i);
13302  return cache->get(i + 1);
13303  }
13304  }
13305 
13306  int size = cache->size();
13307  ASSERT(size <= cache->length());
13308 
13309  for (int i = size - 2; i > finger_index; i -= 2) {
13310  o = cache->get(i);
13311  if (o == key) {
13312  cache->set_finger_index(i);
13313  return cache->get(i + 1);
13314  }
13315  }
13316 
13317  // There is no value in the cache. Invoke the function and cache result.
13318  HandleScope scope(isolate);
13319 
13320  Handle<JSFunctionResultCache> cache_handle(cache);
13321  Handle<Object> key_handle(key);
13322  Handle<Object> value;
13323  {
13325  cache_handle->get(JSFunctionResultCache::kFactoryIndex)));
13326  // TODO(antonm): consider passing a receiver when constructing a cache.
13327  Handle<Object> receiver(isolate->global_context()->global());
13328  // This handle is nor shared, nor used later, so it's safe.
13329  Handle<Object> argv[] = { key_handle };
13330  bool pending_exception;
13331  value = Execution::Call(factory,
13332  receiver,
13333  ARRAY_SIZE(argv),
13334  argv,
13335  &pending_exception);
13336  if (pending_exception) return Failure::Exception();
13337  }
13338 
13339 #ifdef DEBUG
13340  if (FLAG_verify_heap) {
13341  cache_handle->JSFunctionResultCacheVerify();
13342  }
13343 #endif
13344 
13345  // Function invocation may have cleared the cache. Reread all the data.
13346  finger_index = cache_handle->finger_index();
13347  size = cache_handle->size();
13348 
13349  // If we have spare room, put new data into it, otherwise evict post finger
13350  // entry which is likely to be the least recently used.
13351  int index = -1;
13352  if (size < cache_handle->length()) {
13353  cache_handle->set_size(size + JSFunctionResultCache::kEntrySize);
13354  index = size;
13355  } else {
13356  index = finger_index + JSFunctionResultCache::kEntrySize;
13357  if (index == cache_handle->length()) {
13359  }
13360  }
13361 
13362  ASSERT(index % 2 == 0);
13364  ASSERT(index < cache_handle->length());
13365 
13366  cache_handle->set(index, *key_handle);
13367  cache_handle->set(index + 1, *value);
13368  cache_handle->set_finger_index(index);
13369 
13370 #ifdef DEBUG
13371  if (FLAG_verify_heap) {
13372  cache_handle->JSFunctionResultCacheVerify();
13373  }
13374 #endif
13375 
13376  return *value;
13377 }
13378 
13379 
13380 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewMessageObject) {
13381  HandleScope scope(isolate);
13383  CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 1);
13384  return *isolate->factory()->NewJSMessageObject(
13385  type,
13386  arguments,
13387  0,
13388  0,
13389  isolate->factory()->undefined_value(),
13390  isolate->factory()->undefined_value(),
13391  isolate->factory()->undefined_value());
13392 }
13393 
13394 
13395 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetType) {
13396  CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
13397  return message->type();
13398 }
13399 
13400 
13401 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetArguments) {
13402  CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
13403  return message->arguments();
13404 }
13405 
13406 
13407 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetStartPosition) {
13408  CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
13409  return Smi::FromInt(message->start_position());
13410 }
13411 
13412 
13413 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetScript) {
13414  CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
13415  return message->script();
13416 }
13417 
13418 
13419 #ifdef DEBUG
13420 // ListNatives is ONLY used by the fuzz-natives.js in debug mode
13421 // Exclude the code in release mode.
13422 RUNTIME_FUNCTION(MaybeObject*, Runtime_ListNatives) {
13423  ASSERT(args.length() == 0);
13424  HandleScope scope;
13425 #define COUNT_ENTRY(Name, argc, ressize) + 1
13426  int entry_count = 0
13427  RUNTIME_FUNCTION_LIST(COUNT_ENTRY)
13428  INLINE_FUNCTION_LIST(COUNT_ENTRY)
13429  INLINE_RUNTIME_FUNCTION_LIST(COUNT_ENTRY);
13430 #undef COUNT_ENTRY
13431  Factory* factory = isolate->factory();
13432  Handle<FixedArray> elements = factory->NewFixedArray(entry_count);
13433  int index = 0;
13434  bool inline_runtime_functions = false;
13435 #define ADD_ENTRY(Name, argc, ressize) \
13436  { \
13437  HandleScope inner; \
13438  Handle<String> name; \
13439  /* Inline runtime functions have an underscore in front of the name. */ \
13440  if (inline_runtime_functions) { \
13441  name = factory->NewStringFromAscii( \
13442  Vector<const char>("_" #Name, StrLength("_" #Name))); \
13443  } else { \
13444  name = factory->NewStringFromAscii( \
13445  Vector<const char>(#Name, StrLength(#Name))); \
13446  } \
13447  Handle<FixedArray> pair_elements = factory->NewFixedArray(2); \
13448  pair_elements->set(0, *name); \
13449  pair_elements->set(1, Smi::FromInt(argc)); \
13450  Handle<JSArray> pair = factory->NewJSArrayWithElements(pair_elements); \
13451  elements->set(index++, *pair); \
13452  }
13453  inline_runtime_functions = false;
13454  RUNTIME_FUNCTION_LIST(ADD_ENTRY)
13455  inline_runtime_functions = true;
13456  INLINE_FUNCTION_LIST(ADD_ENTRY)
13457  INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY)
13458 #undef ADD_ENTRY
13459  ASSERT_EQ(index, entry_count);
13460  Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
13461  return *result;
13462 }
13463 #endif
13464 
13465 
13466 RUNTIME_FUNCTION(MaybeObject*, Runtime_Log) {
13467  ASSERT(args.length() == 2);
13468  CONVERT_ARG_CHECKED(String, format, 0);
13469  CONVERT_ARG_CHECKED(JSArray, elms, 1);
13470  String::FlatContent format_content = format->GetFlatContent();
13471  RUNTIME_ASSERT(format_content.IsAscii());
13472  Vector<const char> chars = format_content.ToAsciiVector();
13473  LOGGER->LogRuntime(chars, elms);
13474  return isolate->heap()->undefined_value();
13475 }
13476 
13477 
13478 RUNTIME_FUNCTION(MaybeObject*, Runtime_IS_VAR) {
13479  UNREACHABLE(); // implemented as macro in the parser
13480  return NULL;
13481 }
13482 
13483 
13484 #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \
13485  RUNTIME_FUNCTION(MaybeObject*, Runtime_Has##Name) { \
13486  CONVERT_ARG_CHECKED(JSObject, obj, 0); \
13487  return isolate->heap()->ToBoolean(obj->Has##Name()); \
13488  }
13489 
13490 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiElements)
13491 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements)
13492 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements)
13493 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
13494 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
13495 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
13496 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalPixelElements)
13497 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
13498 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalByteElements)
13499 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedByteElements)
13500 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalShortElements)
13501 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedShortElements)
13502 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalIntElements)
13503 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedIntElements)
13504 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalFloatElements)
13505 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalDoubleElements)
13506 // Properties test sitting with elements tests - not fooling anyone.
13508 
13509 #undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
13510 
13511 
13512 RUNTIME_FUNCTION(MaybeObject*, Runtime_HaveSameMap) {
13513  ASSERT(args.length() == 2);
13514  CONVERT_ARG_CHECKED(JSObject, obj1, 0);
13515  CONVERT_ARG_CHECKED(JSObject, obj2, 1);
13516  return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
13517 }
13518 
13519 // ----------------------------------------------------------------------------
13520 // Implementation of Runtime
13521 
13522 #define F(name, number_of_args, result_size) \
13523  { Runtime::k##name, Runtime::RUNTIME, #name, \
13524  FUNCTION_ADDR(Runtime_##name), number_of_args, result_size },
13525 
13526 
13527 #define I(name, number_of_args, result_size) \
13528  { Runtime::kInline##name, Runtime::INLINE, \
13529  "_" #name, NULL, number_of_args, result_size },
13530 
13531 static const Runtime::Function kIntrinsicFunctions[] = {
13535 };
13536 
13537 
13539  Object* dictionary) {
13540  ASSERT(Isolate::Current()->heap() == heap);
13541  ASSERT(dictionary != NULL);
13542  ASSERT(StringDictionary::cast(dictionary)->NumberOfElements() == 0);
13543  for (int i = 0; i < kNumFunctions; ++i) {
13544  Object* name_symbol;
13545  { MaybeObject* maybe_name_symbol =
13546  heap->LookupAsciiSymbol(kIntrinsicFunctions[i].name);
13547  if (!maybe_name_symbol->ToObject(&name_symbol)) return maybe_name_symbol;
13548  }
13549  StringDictionary* string_dictionary = StringDictionary::cast(dictionary);
13550  { MaybeObject* maybe_dictionary = string_dictionary->Add(
13551  String::cast(name_symbol),
13552  Smi::FromInt(i),
13553  PropertyDetails(NONE, NORMAL));
13554  if (!maybe_dictionary->ToObject(&dictionary)) {
13555  // Non-recoverable failure. Calling code must restart heap
13556  // initialization.
13557  return maybe_dictionary;
13558  }
13559  }
13560  }
13561  return dictionary;
13562 }
13563 
13564 
13566  Heap* heap = name->GetHeap();
13567  int entry = heap->intrinsic_function_names()->FindEntry(*name);
13568  if (entry != kNotFound) {
13569  Object* smi_index = heap->intrinsic_function_names()->ValueAt(entry);
13570  int function_index = Smi::cast(smi_index)->value();
13571  return &(kIntrinsicFunctions[function_index]);
13572  }
13573  return NULL;
13574 }
13575 
13576 
13578  return &(kIntrinsicFunctions[static_cast<int>(id)]);
13579 }
13580 
13581 
13583  Isolate* isolate = Isolate::Current();
13584  Failure* failure = Failure::cast(result);
13585  if (failure->IsRetryAfterGC()) {
13586  if (isolate->heap()->new_space()->AddFreshPage()) {
13587  return;
13588  }
13589 
13590  // Try to do a garbage collection; ignore it if it fails. The C
13591  // entry stub will throw an out-of-memory exception in that case.
13592  isolate->heap()->CollectGarbage(failure->allocation_space(),
13593  "Runtime::PerformGC");
13594  } else {
13595  // Handle last resort GC and make sure to allow future allocations
13596  // to grow the heap without causing GCs (if possible).
13597  isolate->counters()->gc_last_resort_from_js()->Increment();
13599  "Runtime::PerformGC");
13600  }
13601 }
13602 
13603 
13604 } } // namespace v8::internal
static bool IsBlack(MarkBit mark_bit)
Definition: mark-compact.h:70
Object * GetPrototype()
Definition: objects.cc:709
byte * Address
Definition: globals.h:172
MaybeObject * AllocateRawString< SeqAsciiString >(Isolate *isolate, int length)
Definition: runtime.cc:5805
static Object * FindSharedFunctionInfoInScript(Isolate *isolate, Handle< Script > script, int position)
#define INLINE_FUNCTION_LIST(F)
Definition: runtime.h:493
void ClearTypeFeedbackCells(Heap *heap)
Definition: objects.cc:8258
const SwVfpRegister s2
static Handle< Object > New(Handle< JSFunction > func, int argc, Handle< Object > argv[], bool *pending_exception)
Definition: execution.cc:177
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:1944
static const int kMaxLength
Definition: objects.h:2301
void Destroy(Object **location)
void FlattenString(Handle< String > string)
Definition: handles.cc:211
static bool CompileLazy(Handle< JSFunction > function, ClearExceptionFlag flag)
Definition: objects.cc:7465
Handle< JSObject > NewJSObject(Handle< JSFunction > constructor, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:973
Object * function() const
Definition: frames-inl.h:231
FixedArray * function_bindings()
Definition: objects-inl.h:4234
static Object *& Object_at(Address addr)
Definition: v8memory.h:75
static const int kMaxAsciiCharCode
Definition: objects.h:7107
static const int kNotFound
Definition: runtime.h:625
#define CONVERT_SMI_ARG_CHECKED(name, index)
Definition: runtime.cc:91
static const int kGlobalFieldIndex
Definition: objects.h:6483
void set(int index, Object *value)
Definition: objects-inl.h:1695
bool is_hidden_prototype()
Definition: objects.h:4629
#define CONVERT_DOUBLE_ARG_CHECKED(name, index)
Definition: runtime.cc:98
static const Function * FunctionForSymbol(Handle< String > name)
Definition: runtime.cc:13565
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:12305
int64_t ToUTC(int64_t time_ms)
Definition: date.h:131
GlobalObject * global()
Definition: contexts.h:319
static bool UseCrankshaft()
Definition: v8.h:86
uint32_t NumberToUint32(Object *number)
Definition: v8conversions.h:43
static DescriptorArray * cast(Object *obj)
Object * ToBoolean(bool condition)
Definition: heap-inl.h:641
Isolate * isolate()
Definition: heap-inl.h:494
double DoubleToInteger(double x)
static void PerformGC(Object *result)
Definition: runtime.cc:13582
void set_length(Smi *length)
Definition: objects-inl.h:4991
void Compile(Handle< String > replacement, int capture_count, int subject_length)
Definition: runtime.cc:2728
Handle< FixedArray > NewFixedArrayWithHoles(int size, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:53
static uint32_t encode(T value)
Definition: utils.h:261
static Smi * FromInt(int value)
Definition: objects-inl.h:973
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:569
MUST_USE_RESULT MaybeObject * AllocateJSFunctionProxy(Object *handler, Object *call_trap, Object *construct_trap, Object *prototype)
Definition: heap.cc:4045
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:747
static void RevertStackCheckCode(Code *unoptimized_code, Code *check_code, Code *replacement_code)
bool HasRealNamedProperty(String *key)
Definition: objects.cc:10294
int isless(double x, double y)
MUST_USE_RESULT MaybeObject * CopyInsert(Descriptor *descriptor, TransitionFlag transition_flag)
Definition: objects.cc:5838
void CollectAllGarbage(int flags, const char *gc_reason=NULL)
Definition: heap.cc:452
Handle< JSArray > NewJSArray(int capacity, ElementsKind elements_kind=TERMINAL_FAST_ELEMENTS_KIND, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:1005
value format" "after each garbage collection") DEFINE_bool(print_cumulative_gc_stat, false, "print cumulative GC statistics in name=value format on exit") DEFINE_bool(trace_gc_verbose, false, "print more details following each garbage collection") DEFINE_bool(trace_fragmentation, false, "report fragmentation for old pointer and data pages") DEFINE_bool(collect_maps, true, "garbage collect maps from which no objects can be reached") DEFINE_bool(flush_code, true, "flush code that we expect not to use again before full gc") DEFINE_bool(incremental_marking, true, "use incremental marking") DEFINE_bool(incremental_marking_steps, true, "do incremental marking steps") DEFINE_bool(trace_incremental_marking, false, "trace progress of the incremental marking") DEFINE_bool(use_idle_notification, true, "Use idle notification to reduce memory footprint.") DEFINE_bool(send_idle_notification, false, "Send idle notifcation between stress runs.") DEFINE_bool(use_ic, true, "use inline caching") DEFINE_bool(native_code_counters, false, "generate extra code for manipulating stats counters") DEFINE_bool(always_compact, false, "Perform compaction on every full GC") DEFINE_bool(lazy_sweeping, true, "Use lazy sweeping for old pointer and data spaces") DEFINE_bool(never_compact, false, "Never perform compaction on full GC-testing only") DEFINE_bool(compact_code_space, true, "Compact code space on full non-incremental collections") DEFINE_bool(cleanup_code_caches_at_gc, true, "Flush inline caches prior to mark compact collection and" "flush code caches in maps during mark compact cycle.") DEFINE_int(random_seed, 0, "Default seed for initializing random generator" "(0, the default, means to use system random).") DEFINE_bool(use_verbose_printer, true, "allows verbose printing") DEFINE_bool(allow_natives_syntax, false, "allow natives syntax") DEFINE_bool(trace_sim, false, "Trace simulator execution") DEFINE_bool(check_icache, false, "Check icache flushes in ARM and MIPS simulator") DEFINE_int(stop_sim_at, 0, "Simulator stop after x number of instructions") DEFINE_int(sim_stack_alignment, 8, "Stack alingment in bytes in simulator(4 or 8, 8 is default)") DEFINE_bool(trace_exception, false, "print stack trace when throwing exceptions") DEFINE_bool(preallocate_message_memory, false, "preallocate some memory to build stack traces.") DEFINE_bool(randomize_hashes, true, "randomize hashes to avoid predictable hash collisions" "(with snapshots this option cannot override the baked-in seed)") DEFINE_int(hash_seed, 0, "Fixed seed to use to hash property keys(0 means random)" "(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(preemption, false, "activate a 100ms timer that switches between V8 threads") DEFINE_bool(regexp_optimization, true, "generate optimized regexp code") DEFINE_bool(testing_bool_flag, true, "testing_bool_flag") DEFINE_int(testing_int_flag, 13, "testing_int_flag") DEFINE_float(testing_float_flag, 2.5, "float-flag") DEFINE_string(testing_string_flag, "Hello, world!", "string-flag") DEFINE_int(testing_prng_seed, 42, "Seed used for threading test randomness") DEFINE_string(testing_serialization_file, "/tmp/serdes", "file in which to serialize heap") DEFINE_bool(help, false, "Print usage message, including flags, on console") DEFINE_bool(dump_counters, false, "Dump counters on exit") DEFINE_string(map_counters, "", "Map counters to a file") DEFINE_args(js_arguments, JSARGUMENTS_INIT, "Pass all remaining arguments to the script.Alias for\"--\".") DEFINE_bool(debug_compile_events, true,"Enable debugger compile events") DEFINE_bool(debug_script_collected_events, true,"Enable debugger script collected events") DEFINE_bool(gdbjit, false,"enable GDBJIT interface (disables compacting GC)") DEFINE_bool(gdbjit_full, false,"enable GDBJIT interface for all code objects") DEFINE_bool(gdbjit_dump, false,"dump elf objects with debug info to disk") DEFINE_string(gdbjit_dump_filter,"","dump only objects containing this substring") DEFINE_bool(force_marking_deque_overflows, false,"force overflows of marking deque by reducing it's size ""to 64 words") DEFINE_bool(stress_compaction, false,"stress the GC compactor to flush out bugs (implies ""--force_marking_deque_overflows)")#define FLAG DEFINE_bool(enable_slow_asserts, false,"enable asserts that are slow to execute") DEFINE_bool(trace_codegen, false,"print name of functions for which code is generated") DEFINE_bool(print_source, false,"pretty print source code") DEFINE_bool(print_builtin_source, false,"pretty print source code for builtins") DEFINE_bool(print_ast, false,"print source AST") DEFINE_bool(print_builtin_ast, false,"print source AST for builtins") DEFINE_string(stop_at,"","function name where to insert a breakpoint") DEFINE_bool(print_builtin_scopes, false,"print scopes for builtins") DEFINE_bool(print_scopes, false,"print scopes") DEFINE_bool(trace_contexts, false,"trace contexts operations") DEFINE_bool(gc_greedy, false,"perform GC prior to some allocations") DEFINE_bool(gc_verbose, false,"print stuff during garbage collection") DEFINE_bool(heap_stats, false,"report heap statistics before and after GC") DEFINE_bool(code_stats, false,"report code statistics after GC") DEFINE_bool(verify_heap, false,"verify heap pointers before and after GC") DEFINE_bool(print_handles, false,"report handles after GC") DEFINE_bool(print_global_handles, false,"report global handles after GC") DEFINE_bool(trace_ic, false,"trace inline cache state transitions") DEFINE_bool(print_interfaces, false,"print interfaces") DEFINE_bool(print_interface_details, false,"print interface inference details") DEFINE_int(print_interface_depth, 5,"depth for printing interfaces") DEFINE_bool(trace_normalization, false,"prints when objects are turned into dictionaries.") DEFINE_bool(trace_lazy, false,"trace lazy compilation") DEFINE_bool(collect_heap_spill_statistics, false,"report heap spill statistics along with heap_stats ""(requires heap_stats)") DEFINE_bool(trace_isolates, false,"trace isolate state changes") DEFINE_bool(log_state_changes, false,"Log state changes.") DEFINE_bool(regexp_possessive_quantifier, false,"enable possessive quantifier syntax for testing") DEFINE_bool(trace_regexp_bytecodes, false,"trace regexp bytecode execution") DEFINE_bool(trace_regexp_assembler, false,"trace regexp macro assembler calls.")#define FLAG DEFINE_bool(log, false,"Minimal logging (no API, code, GC, suspect, or handles samples).") DEFINE_bool(log_all, false,"Log all events to the log file.") DEFINE_bool(log_runtime, false,"Activate runtime system %Log call.") DEFINE_bool(log_api, false,"Log API events to the log file.") DEFINE_bool(log_code, false,"Log code events to the log file without profiling.") DEFINE_bool(log_gc, false,"Log heap samples on garbage collection for the hp2ps tool.") DEFINE_bool(log_handles, false,"Log global handle events.") DEFINE_bool(log_snapshot_positions, false,"log positions of (de)serialized objects in the snapshot.") DEFINE_bool(log_suspect, false,"Log suspect operations.") DEFINE_bool(prof, false,"Log statistical profiling information (implies --log-code).") DEFINE_bool(prof_auto, true,"Used with --prof, starts profiling automatically") DEFINE_bool(prof_lazy, false,"Used with --prof, only does sampling and logging"" when profiler is active (implies --noprof_auto).") DEFINE_bool(prof_browser_mode, true,"Used with --prof, turns on browser-compatible mode for profiling.") DEFINE_bool(log_regexp, false,"Log regular expression execution.") DEFINE_bool(sliding_state_window, false,"Update sliding state window counters.") DEFINE_string(logfile,"v8.log","Specify the name of the log file.") DEFINE_bool(ll_prof, false,"Enable low-level linux profiler.")#define FLAG DEFINE_bool(trace_elements_transitions, false,"trace elements transitions") DEFINE_bool(print_code_stubs, false,"print code stubs") DEFINE_bool(test_secondary_stub_cache, false,"test secondary stub cache by disabling the primary one") DEFINE_bool(test_primary_stub_cache, false,"test primary stub cache by disabling the secondary one") DEFINE_bool(print_code, false,"print generated code") DEFINE_bool(print_opt_code, false,"print optimized code") DEFINE_bool(print_unopt_code, false,"print unoptimized code before ""printing optimized code based on it") DEFINE_bool(print_code_verbose, false,"print more information for code") DEFINE_bool(print_builtin_code, false,"print generated code for builtins")#43"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flags.cc"2#define FLAG_MODE_DEFINE_DEFAULTS#1"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flag-definitions.h"1#define FLAG_FULL(ftype, ctype, nam, def, cmt)#define FLAG_READONLY(ftype, ctype, nam, def, cmt)#define DEFINE_implication(whenflag, thenflag)#define DEFINE_bool(nam, def, cmt)#define DEFINE_int(nam, def, cmt)#define DEFINE_float(nam, def, cmt)#define DEFINE_string(nam, def, cmt)#define DEFINE_args(nam, def, cmt)#define FLAG DEFINE_bool(use_strict, false,"enforce strict mode") DEFINE_bool(es5_readonly, false,"activate correct semantics for inheriting readonliness") DEFINE_bool(es52_globals, false,"activate new semantics for global var declarations") DEFINE_bool(harmony_typeof, false,"enable harmony semantics for typeof") DEFINE_bool(harmony_scoping, false,"enable harmony block scoping") DEFINE_bool(harmony_modules, false,"enable harmony modules (implies block scoping)") DEFINE_bool(harmony_proxies, false,"enable harmony proxies") DEFINE_bool(harmony_collections, false,"enable harmony collections (sets, maps, and weak maps)") DEFINE_bool(harmony, false,"enable all harmony features (except typeof)") DEFINE_implication(harmony, harmony_scoping) DEFINE_implication(harmony, harmony_modules) DEFINE_implication(harmony, harmony_proxies) DEFINE_implication(harmony, harmony_collections) DEFINE_implication(harmony_modules, harmony_scoping) DEFINE_bool(packed_arrays, false,"optimizes arrays that have no holes") DEFINE_bool(smi_only_arrays, true,"tracks arrays with only smi values") DEFINE_bool(clever_optimizations, true,"Optimize object size, Array shift, DOM strings and string +") DEFINE_bool(unbox_double_arrays, true,"automatically unbox arrays of doubles") DEFINE_bool(string_slices, true,"use string slices") DEFINE_bool(crankshaft, true,"use crankshaft") DEFINE_string(hydrogen_filter,"","optimization filter") DEFINE_bool(use_range, true,"use hydrogen range analysis") DEFINE_bool(eliminate_dead_phis, true,"eliminate dead phis") DEFINE_bool(use_gvn, true,"use hydrogen global value numbering") DEFINE_bool(use_canonicalizing, true,"use hydrogen instruction canonicalizing") DEFINE_bool(use_inlining, true,"use function inlining") DEFINE_int(max_inlined_source_size, 600,"maximum source size in bytes considered for a single inlining") DEFINE_int(max_inlined_nodes, 196,"maximum number of AST nodes considered for a single inlining") DEFINE_int(max_inlined_nodes_cumulative, 196,"maximum cumulative number of AST nodes considered for inlining") DEFINE_bool(loop_invariant_code_motion, true,"loop invariant code motion") DEFINE_bool(collect_megamorphic_maps_from_stub_cache, true,"crankshaft harvests type feedback from stub cache") DEFINE_bool(hydrogen_stats, false,"print statistics for hydrogen") DEFINE_bool(trace_hydrogen, false,"trace generated hydrogen to file") DEFINE_string(trace_phase,"Z","trace generated IR for specified phases") DEFINE_bool(trace_inlining, false,"trace inlining decisions") DEFINE_bool(trace_alloc, false,"trace register allocator") DEFINE_bool(trace_all_uses, false,"trace all use positions") DEFINE_bool(trace_range, false,"trace range analysis") DEFINE_bool(trace_gvn, false,"trace global value numbering") DEFINE_bool(trace_representation, false,"trace representation types") DEFINE_bool(stress_pointer_maps, false,"pointer map for every instruction") DEFINE_bool(stress_environments, false,"environment for every instruction") DEFINE_int(deopt_every_n_times, 0,"deoptimize every n times a deopt point is passed") DEFINE_bool(trap_on_deopt, false,"put a break point before deoptimizing") DEFINE_bool(deoptimize_uncommon_cases, true,"deoptimize uncommon cases") DEFINE_bool(polymorphic_inlining, true,"polymorphic inlining") DEFINE_bool(use_osr, true,"use on-stack replacement") DEFINE_bool(array_bounds_checks_elimination, false,"perform array bounds checks elimination") DEFINE_bool(array_index_dehoisting, false,"perform array index dehoisting") DEFINE_bool(trace_osr, false,"trace on-stack replacement") DEFINE_int(stress_runs, 0,"number of stress runs") DEFINE_bool(optimize_closures, true,"optimize closures") DEFINE_bool(inline_construct, true,"inline constructor calls") DEFINE_bool(inline_arguments, true,"inline functions with arguments object") DEFINE_int(loop_weight, 1,"loop weight for representation inference") DEFINE_bool(optimize_for_in, true,"optimize functions containing for-in loops") DEFINE_bool(experimental_profiler, true,"enable all profiler experiments") DEFINE_bool(watch_ic_patching, false,"profiler considers IC stability") DEFINE_int(frame_count, 1,"number of stack frames inspected by the profiler") DEFINE_bool(self_optimization, false,"primitive functions trigger their own optimization") DEFINE_bool(direct_self_opt, false,"call recompile stub directly when self-optimizing") DEFINE_bool(retry_self_opt, false,"re-try self-optimization if it failed") DEFINE_bool(count_based_interrupts, false,"trigger profiler ticks based on counting instead of timing") DEFINE_bool(interrupt_at_exit, false,"insert an interrupt check at function exit") DEFINE_bool(weighted_back_edges, false,"weight back edges by jump distance for interrupt triggering") DEFINE_int(interrupt_budget, 5900,"execution budget before interrupt is triggered") DEFINE_int(type_info_threshold, 15,"percentage of ICs that must have type info to allow optimization") DEFINE_int(self_opt_count, 130,"call count before self-optimization") DEFINE_implication(experimental_profiler, watch_ic_patching) DEFINE_implication(experimental_profiler, self_optimization) DEFINE_implication(experimental_profiler, retry_self_opt) DEFINE_implication(experimental_profiler, count_based_interrupts) DEFINE_implication(experimental_profiler, interrupt_at_exit) DEFINE_implication(experimental_profiler, weighted_back_edges) DEFINE_bool(trace_opt_verbose, false,"extra verbose compilation tracing") DEFINE_implication(trace_opt_verbose, trace_opt) DEFINE_bool(debug_code, false,"generate extra code (assertions) for debugging") DEFINE_bool(code_comments, false,"emit comments in code disassembly") DEFINE_bool(enable_sse2, true,"enable use of SSE2 instructions if available") DEFINE_bool(enable_sse3, true,"enable use of SSE3 instructions if available") DEFINE_bool(enable_sse4_1, true,"enable use of SSE4.1 instructions if available") DEFINE_bool(enable_cmov, true,"enable use of CMOV instruction if available") DEFINE_bool(enable_rdtsc, true,"enable use of RDTSC instruction if available") DEFINE_bool(enable_sahf, true,"enable use of SAHF instruction if available (X64 only)") DEFINE_bool(enable_vfp3, true,"enable use of VFP3 instructions if available - this implies ""enabling ARMv7 instructions (ARM only)") DEFINE_bool(enable_armv7, true,"enable use of ARMv7 instructions if available (ARM only)") DEFINE_bool(enable_fpu, true,"enable use of MIPS FPU instructions if available (MIPS only)") DEFINE_string(expose_natives_as, NULL,"expose natives in global object") DEFINE_string(expose_debug_as, NULL,"expose debug in global object") DEFINE_bool(expose_gc, false,"expose gc extension") DEFINE_bool(expose_externalize_string, false,"expose externalize string extension") DEFINE_int(stack_trace_limit, 10,"number of stack frames to capture") DEFINE_bool(builtins_in_stack_traces, false,"show built-in functions in stack traces") DEFINE_bool(disable_native_files, false,"disable builtin natives files") DEFINE_bool(inline_new, true,"use fast inline allocation") DEFINE_bool(stack_trace_on_abort, true,"print a stack trace if an assertion failure occurs") DEFINE_bool(trace, false,"trace function calls") DEFINE_bool(mask_constants_with_cookie, true,"use random jit cookie to mask large constants") DEFINE_bool(lazy, true,"use lazy compilation") DEFINE_bool(trace_opt, false,"trace lazy optimization") DEFINE_bool(trace_opt_stats, false,"trace lazy optimization statistics") DEFINE_bool(opt, true,"use adaptive optimizations") DEFINE_bool(always_opt, false,"always try to optimize functions") DEFINE_bool(prepare_always_opt, false,"prepare for turning on always opt") DEFINE_bool(trace_deopt, false,"trace deoptimization") DEFINE_int(min_preparse_length, 1024,"minimum length for automatic enable preparsing") DEFINE_bool(always_full_compiler, false,"try to use the dedicated run-once backend for all code") DEFINE_bool(trace_bailout, false,"print reasons for falling back to using the classic V8 backend") DEFINE_bool(compilation_cache, true,"enable compilation cache") DEFINE_bool(cache_prototype_transitions, true,"cache prototype transitions") DEFINE_bool(trace_debug_json, false,"trace debugging JSON request/response") DEFINE_bool(debugger_auto_break, true,"automatically set the debug break flag when debugger commands are ""in the queue") DEFINE_bool(enable_liveedit, true,"enable liveedit experimental feature") DEFINE_bool(break_on_abort, true,"always cause a debug break before aborting") DEFINE_int(stack_size, kPointerSize *123,"default size of stack region v8 is allowed to use (in kBytes)") DEFINE_int(max_stack_trace_source_length, 300,"maximum length of function source code printed in a stack trace.") DEFINE_bool(always_inline_smi_code, false,"always inline smi code in non-opt code") DEFINE_int(max_new_space_size, 0,"max size of the new generation (in kBytes)") DEFINE_int(max_old_space_size, 0,"max size of the old generation (in Mbytes)") DEFINE_int(max_executable_size, 0,"max size of executable memory (in Mbytes)") DEFINE_bool(gc_global, false,"always perform global GCs") DEFINE_int(gc_interval,-1,"garbage collect after <n> allocations") DEFINE_bool(trace_gc, false,"print one trace line following each garbage collection") DEFINE_bool(trace_gc_nvp, false,"print one detailed trace line in name=value format ""after each garbage collection") DEFINE_bool(print_cumulative_gc_stat, false,"print cumulative GC statistics in name=value format on exit") DEFINE_bool(trace_gc_verbose, false,"print more details following each garbage collection") DEFINE_bool(trace_fragmentation, false,"report fragmentation for old pointer and data pages") DEFINE_bool(collect_maps, true,"garbage collect maps from which no objects can be reached") DEFINE_bool(flush_code, true,"flush code that we expect not to use again before full gc") DEFINE_bool(incremental_marking, true,"use incremental marking") DEFINE_bool(incremental_marking_steps, true,"do incremental marking steps") DEFINE_bool(trace_incremental_marking, false,"trace progress of the incremental marking") DEFINE_bool(use_idle_notification, true,"Use idle notification to reduce memory footprint.") DEFINE_bool(send_idle_notification, false,"Send idle notifcation between stress runs.") DEFINE_bool(use_ic, true,"use inline caching") DEFINE_bool(native_code_counters, false,"generate extra code for manipulating stats counters") DEFINE_bool(always_compact, false,"Perform compaction on every full GC") DEFINE_bool(lazy_sweeping, true,"Use lazy sweeping for old pointer and data spaces") DEFINE_bool(never_compact, false,"Never perform compaction on full GC - testing only") DEFINE_bool(compact_code_space, true,"Compact code space on full non-incremental collections") DEFINE_bool(cleanup_code_caches_at_gc, true,"Flush inline caches prior to mark compact collection and ""flush code caches in maps during mark compact cycle.") DEFINE_int(random_seed, 0,"Default seed for initializing random generator ""(0, the default, means to use system random).") DEFINE_bool(use_verbose_printer, true,"allows verbose printing") DEFINE_bool(allow_natives_syntax, false,"allow natives syntax") DEFINE_bool(trace_sim, false,"Trace simulator execution") DEFINE_bool(check_icache, false,"Check icache flushes in ARM and MIPS simulator") DEFINE_int(stop_sim_at, 0,"Simulator stop after x number of instructions") DEFINE_int(sim_stack_alignment, 8,"Stack alingment in bytes in simulator (4 or 8, 8 is default)") DEFINE_bool(trace_exception, false,"print stack trace when throwing exceptions") DEFINE_bool(preallocate_message_memory, false,"preallocate some memory to build stack traces.") DEFINE_bool(randomize_hashes, true,"randomize hashes to avoid predictable hash collisions ""(with snapshots this option cannot override the baked-in seed)") DEFINE_int(hash_seed, 0,"Fixed seed to use to hash property keys (0 means random)""(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(preemption, false,"activate a 100ms timer that switches between V8 threads") DEFINE_bool(regexp_optimization, true,"generate optimized regexp code") DEFINE_bool(testing_bool_flag, true,"testing_bool_flag") DEFINE_int(testing_int_flag, 13,"testing_int_flag") DEFINE_float(testing_float_flag, 2.5,"float-flag") DEFINE_string(testing_string_flag,"Hello, world!","string-flag") DEFINE_int(testing_prng_seed, 42,"Seed used for threading test randomness") DEFINE_string(testing_serialization_file,"/tmp/serdes","file in which to serialize heap") DEFINE_bool(help, false,"Print usage message, including flags, on console") DEFINE_bool(dump_counters, false,"Dump counters on exit") DEFINE_string(map_counters,"","Map counters to a file") DEFINE_args(js_arguments, JSARGUMENTS_INIT,"Pass all remaining arguments to the script. Alias for \"--\".") DEFINE_bool(debug_compile_events, true,"Enable debugger compile events") DEFINE_bool(debug_script_collected_events, true,"Enable debugger script collected events") DEFINE_bool(gdbjit, false,"enable GDBJIT interface (disables compacting GC)") DEFINE_bool(gdbjit_full, false,"enable GDBJIT interface for all code objects") DEFINE_bool(gdbjit_dump, false,"dump elf objects with debug info to disk") DEFINE_string(gdbjit_dump_filter,"","dump only objects containing this substring") DEFINE_bool(force_marking_deque_overflows, false,"force overflows of marking deque by reducing it's size ""to 64 words") DEFINE_bool(stress_compaction, false,"stress the GC compactor to flush out bugs (implies ""--force_marking_deque_overflows)")#define FLAG DEFINE_bool(enable_slow_asserts, false,"enable asserts that are slow to execute") DEFINE_bool(trace_codegen, false,"print name of functions for which code is generated") DEFINE_bool(print_source, false,"pretty print source code") DEFINE_bool(print_builtin_source, false,"pretty print source code for builtins") DEFINE_bool(print_ast, false,"print source AST") DEFINE_bool(print_builtin_ast, false,"print source AST for builtins") DEFINE_string(stop_at,"","function name where to insert a breakpoint") DEFINE_bool(print_builtin_scopes, false,"print scopes for builtins") DEFINE_bool(print_scopes, false,"print scopes") DEFINE_bool(trace_contexts, false,"trace contexts operations") DEFINE_bool(gc_greedy, false,"perform GC prior to some allocations") DEFINE_bool(gc_verbose, false,"print stuff during garbage collection") DEFINE_bool(heap_stats, false,"report heap statistics before and after GC") DEFINE_bool(code_stats, false,"report code statistics after GC") DEFINE_bool(verify_heap, false,"verify heap pointers before and after GC") DEFINE_bool(print_handles, false,"report handles after GC") DEFINE_bool(print_global_handles, false,"report global handles after GC") DEFINE_bool(trace_ic, false,"trace inline cache state transitions") DEFINE_bool(print_interfaces, false,"print interfaces") DEFINE_bool(print_interface_details, false,"print interface inference details") DEFINE_int(print_interface_depth, 5,"depth for printing interfaces") DEFINE_bool(trace_normalization, false,"prints when objects are turned into dictionaries.") DEFINE_bool(trace_lazy, false,"trace lazy compilation") DEFINE_bool(collect_heap_spill_statistics, false,"report heap spill statistics along with heap_stats ""(requires heap_stats)") DEFINE_bool(trace_isolates, false,"trace isolate state changes") DEFINE_bool(log_state_changes, false,"Log state changes.") DEFINE_bool(regexp_possessive_quantifier, false,"enable possessive quantifier syntax for testing") DEFINE_bool(trace_regexp_bytecodes, false,"trace regexp bytecode execution") DEFINE_bool(trace_regexp_assembler, false,"trace regexp macro assembler calls.")#define FLAG DEFINE_bool(log, false,"Minimal logging (no API, code, GC, suspect, or handles samples).") DEFINE_bool(log_all, false,"Log all events to the log file.") DEFINE_bool(log_runtime, false,"Activate runtime system %Log call.") DEFINE_bool(log_api, false,"Log API events to the log file.") DEFINE_bool(log_code, false,"Log code events to the log file without profiling.") DEFINE_bool(log_gc, false,"Log heap samples on garbage collection for the hp2ps tool.") DEFINE_bool(log_handles, false,"Log global handle events.") DEFINE_bool(log_snapshot_positions, false,"log positions of (de)serialized objects in the snapshot.") DEFINE_bool(log_suspect, false,"Log suspect operations.") DEFINE_bool(prof, false,"Log statistical profiling information (implies --log-code).") DEFINE_bool(prof_auto, true,"Used with --prof, starts profiling automatically") DEFINE_bool(prof_lazy, false,"Used with --prof, only does sampling and logging"" when profiler is active (implies --noprof_auto).") DEFINE_bool(prof_browser_mode, true,"Used with --prof, turns on browser-compatible mode for profiling.") DEFINE_bool(log_regexp, false,"Log regular expression execution.") DEFINE_bool(sliding_state_window, false,"Update sliding state window counters.") DEFINE_string(logfile,"v8.log","Specify the name of the log file.") DEFINE_bool(ll_prof, false,"Enable low-level linux profiler.")#define FLAG DEFINE_bool(trace_elements_transitions, false,"trace elements transitions") DEFINE_bool(print_code_stubs, false,"print code stubs") DEFINE_bool(test_secondary_stub_cache, false,"test secondary stub cache by disabling the primary one") DEFINE_bool(test_primary_stub_cache, false,"test primary stub cache by disabling the secondary one") DEFINE_bool(print_code, false,"print generated code") DEFINE_bool(print_opt_code, false,"print optimized code") DEFINE_bool(print_unopt_code, false,"print unoptimized code before ""printing optimized code based on it") DEFINE_bool(print_code_verbose, false,"print more information for code") DEFINE_bool(print_builtin_code, false,"print generated code for builtins")#47"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flags.cc"2 namespace{struct Flag{enum FlagType{TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_ARGS} name
Definition: flags.cc:1349
static MUST_USE_RESULT MaybeObject * ForceDeleteObjectProperty(Isolate *isolate, Handle< JSReceiver > object, Handle< Object > key)
Definition: runtime.cc:4675
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:801
double ceiling(double x)
bool is_access_check_needed()
Definition: objects-inl.h:2941
static const int kSourceFieldIndex
Definition: objects.h:6482
void Add(Object *value)
Definition: runtime.cc:2343
static bool Analyze(CompilationInfo *info)
Definition: scopes.cc:263
T Max(T a, T b)
Definition: utils.h:222
const int kSmiValueSize
Definition: v8.h:3900
static AccessorPair * cast(Object *obj)
MaybeObject * AllocateRawString< SeqTwoByteString >(Isolate *isolate, int length)
Definition: runtime.cc:5799
static const int64_t kMaxTimeBeforeUTCInMs
Definition: date.h:56
MUST_USE_RESULT MaybeObject * LookupAsciiSymbol(Vector< const char > str)
Definition: heap.cc:5336
static Failure * OutOfMemoryException()
Definition: objects-inl.h:1021
static Handle< FixedArray > GetElements(Handle< FixedArray > value)
Definition: parser.cc:3949
static const char * LocalTimezone(double time)
double fast_sqrt(double input)
int32_t uc32
Definition: globals.h:274
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:6918
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:2086
static int IrregexpPrepare(Handle< JSRegExp > regexp, Handle< String > subject, Zone *zone)
Definition: jsregexp.cc:504
Object * ToBoolean()
Definition: objects.cc:107
static Handle< Object > GetConstructorDelegate(Handle< Object > object)
Definition: execution.cc:281
T & at(int i) const
Definition: list.h:85
static int IrregexpExecRaw(Handle< JSRegExp > regexp, Handle< String > subject, int index, Vector< int > registers, Zone *zone)
Definition: jsregexp.cc:540
Flag flags[]
Definition: flags.cc:1467
static const int kNoNumber
Definition: ast.h:197
int int32_t
Definition: unicode.cc:47
static Object * Lookup(FixedArray *cache, String *string, String *pattern)
Definition: heap.cc:2732
static Failure * Exception()
Definition: objects-inl.h:1016
int Search(Vector< const SubjectChar > subject, int index)
const int kMaxInt
Definition: globals.h:224
void set_map(Map *value)
Definition: objects-inl.h:1135
#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:4540
virtual void Summarize(List< FrameSummary > *frames)
Definition: frames.cc:741
PropertyDescriptorIndices
Definition: runtime.cc:997
#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:2810
static const Function * FunctionForId(FunctionId id)
Definition: runtime.cc:13577
Context * global_context()
Definition: contexts.cc:58
static Handle< Object > TransitionElementsKind(Handle< JSObject > object, ElementsKind to_kind)
Definition: objects.cc:9848
static int GlobalOffsetsVectorSize(Handle< JSRegExp > regexp, int registers_per_match, int *max_matches)
Definition: jsregexp.cc:524
BitField< int, 0, kStringBuilderConcatHelperLengthBits > StringBuilderSubstringLength
Definition: runtime.cc:2400
#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:9651
static void DeoptimizeFunction(JSFunction *function)
Handle< JSArray > ToArray()
Definition: runtime.cc:9565
void Apply(ReplacementStringBuilder *builder, int match_from, int match_to, Handle< JSArray > last_match_info)
Definition: runtime.cc:2772
Handle< JSArray > ToJSArray()
Definition: runtime.cc:2370
int IntegerLog2(uint32_t value)
static ExternalUnsignedShortArray * cast(Object *obj)
Handle< JSArray > GetKeysFor(Handle< JSReceiver > object, bool *threw)
Definition: handles.cc:693
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:9516
static Context * cast(Object *context)
Definition: contexts.h:207
static const int kMaxLength
Definition: objects.h:7375
static SharedFunctionInfo * cast(Object *obj)
Handle< Object > NewNumber(double value, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:581
#define CHECK(condition)
Definition: checks.h:56
static Type GetType(Handle< FixedArray > value)
Definition: parser.cc:3943
bool IsInternalError() const
Definition: objects-inl.h:994
FixedArrayBuilder(Handle< FixedArray > backing_store)
Definition: runtime.cc:2313
static const int kSize
Definition: objects.h:8134
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:4144
#define RETURN_IF_EMPTY_HANDLE(isolate, call)
Definition: isolate.h:134
void ReplaceCode(Code *code)
Definition: objects-inl.h:4090
Factory * factory()
Definition: isolate.h:977
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:547
PropertyAttributes
void visit(uint32_t i, Handle< Object > elm)
Definition: runtime.cc:9529
int fpclassify(double x)
int ComputeParametersCount() const
Definition: frames.h:499
#define CONVERT_LANGUAGE_MODE_ARG(name, index)
Definition: runtime.cc:130
static void SetLastSubject(FixedArray *array, String *to)
Definition: jsregexp.h:168
bool AsArrayIndex(uint32_t *index)
Definition: objects-inl.h:4748
static bool Is(uchar c)
Definition: unicode.cc:779
#define RUNTIME_FUNCTION_LIST(F)
Definition: runtime.h:483
Object * GetValue(int descriptor_number)
Definition: objects-inl.h:1984
static Object ** RawField(HeapObject *obj, int offset)
Definition: objects-inl.h:963
const int kIntSize
Definition: globals.h:231
#define RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, value)
Definition: isolate.h:119
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:6026
const int kMaxBuilderEntriesPerRegExpMatch
Definition: runtime.cc:2916
void FindStringIndices(Isolate *isolate, Vector< const SubjectChar > subject, Vector< const PatternChar > pattern, ZoneList< int > *indices, unsigned int limit, Zone *zone)
Definition: runtime.cc:2833
bool Equals(String *other)
Definition: objects-inl.h:2275
Handle< String > SubString(Handle< String > str, int start, int end, PretenureFlag pretenure)
Definition: handles.cc:326
static const int kHeaderSize
Definition: objects.h:1220
#define V8_INFINITY
Definition: globals.h:32
static MUST_USE_RESULT MaybeObject * InitializeIntrinsicFunctionNames(Heap *heap, Object *dictionary)
Definition: runtime.cc:13538
static const int kMultilineFieldIndex
Definition: objects.h:6485
bool CollectGarbage(AllocationSpace space, GarbageCollector collector, const char *gc_reason, const char *collector_reason)
Definition: heap.cc:491
static ExternalShortArray * cast(Object *obj)
static ScopeInfo * cast(Object *object)
int get(uchar c, uchar n, uchar *result)
Definition: unicode-inl.h:48
static MarkBit MarkBitFrom(Address addr)
uint8_t byte
Definition: globals.h:171
#define CONVERT_ARG_CHECKED(Type, name, index)
Definition: runtime.cc:73
static const char * GetVersion()
Definition: api.cc:4291
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:3039
const int kStringBuilderConcatHelperPositionBits
Definition: runtime.cc:2391
Object * InObjectPropertyAtPut(int index, Object *value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
Definition: objects-inl.h:1566
uint64_t ObjectPair
Definition: runtime.cc:8871
static void SetLastInput(FixedArray *array, String *to)
Definition: jsregexp.h:172
static MaybeObject * Info(int start_idx, int dump_limit)
Handle< SeededNumberDictionary > DictionaryAtNumberPut(Handle< SeededNumberDictionary >, uint32_t key, Handle< Object > value)
Definition: factory.cc:1156
Handle< Map > GetElementsTransitionMap(Handle< JSObject > object, ElementsKind elements_kind)
Definition: factory.cc:506
bool IsNull() const
Definition: v8.h:4295
static Handle< Object > CharAt(Handle< String > str, uint32_t index)
Definition: execution.cc:666
Handle< Object > Lookup(Handle< String > name, ContextLookupFlags flags, int *index, PropertyAttributes *attributes, BindingFlags *binding_flags)
Definition: contexts.cc:87
HANDLE HANDLE LPSTACKFRAME64 StackFrame
static Handle< String > StringReplaceOneCharWithString(Isolate *isolate, Handle< String > subject, Handle< String > search, Handle< String > replace, bool *found, int recursion_limit)
Definition: runtime.cc:3417
static void Abort()
#define UNREACHABLE()
Definition: checks.h:50
void EnsureHeapIsIterable()
Definition: heap.cc:4985
Handle< JSArray > ToJSArray(Handle< JSArray > target_array)
Definition: runtime.cc:2376
double StringToInt(UnicodeCache *unicode_cache, String *str, int radix)
T * start() const
Definition: utils.h:389
static void PrintTop(FILE *file, bool print_args, bool print_line_number)
Definition: frames.cc:754
STATIC_ASSERT((FixedDoubleArray::kHeaderSize &kDoubleAlignmentMask)==0)
Handle< SeqTwoByteString > NewRawTwoByteString(int length, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:234
static SeededNumberDictionary * cast(Object *obj)
Definition: objects.h:3207
Handle< Object > LookupSingleCharacterStringFromCode(uint32_t index)
Definition: handles.cc:318
MUST_USE_RESULT MaybeObject * SetContent(FixedArrayBase *storage)
Definition: objects-inl.h:5004
static void SetLastCaptureCount(FixedArray *array, int to)
Definition: jsregexp.h:164
static Context * GlobalContextFromLiterals(FixedArray *literals)
Definition: objects.cc:7642
static const int kInputIndex
Definition: objects.h:8137
void SetExpectedNofProperties(Handle< JSFunction > func, int nof)
Definition: handles.cc:157
#define MUST_USE_RESULT
Definition: globals.h:360
#define CONVERT_BOOLEAN_ARG_CHECKED(name, index)
Definition: runtime.cc:84
static ExternalIntArray * cast(Object *obj)
static const int kLiteralGlobalContextIndex
Definition: objects.h:5994
static ThreadId Current()
Definition: isolate.h:153
V8EXPORT Local< Value > GetPrototype()
Definition: api.cc:2892
static MUST_USE_RESULT MaybeObject * HandleStackGuardInterrupt(Isolate *isolate)
Definition: execution.cc:891
Handle< Object > Create(Object *value)
bool CodeGenerationFromStringsAllowed(Isolate *isolate, Handle< Context > context)
Definition: runtime.cc:9334
static bool IsValidElementsTransition(ElementsKind from_kind, ElementsKind to_kind)
Definition: objects.cc:9924
static bool IsValid(intptr_t value)
Definition: objects-inl.h:1051
static Failure * cast(MaybeObject *object)
Definition: objects-inl.h:485
bool ToArrayIndex(uint32_t *index)
Definition: objects-inl.h:1637
bool(* AllowCodeGenerationFromStringsCallback)(Local< Context > context)
Definition: v8.h:2707
static const int kNoGCFlags
Definition: heap.h:1049
Handle< ObjectHashSet > ObjectHashSetAdd(Handle< ObjectHashSet > table, Handle< Object > key)
Definition: handles.cc:778
const int kPointerSize
Definition: globals.h:234
static void AddSubjectSlice(FixedArrayBuilder *builder, int from, int to)
Definition: runtime.cc:2422
T * NewArray(size_t size)
Definition: allocation.h:83
static const int kMaxWidth
Definition: unicode.h:293
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:5328
const char * DoubleToCString(double v, Vector< char > buffer)
Definition: conversions.cc:68
intptr_t OffsetFrom(T x)
Definition: utils.h:126
static int GetCapture(FixedArray *array, int index)
Definition: jsregexp.h:160
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:332
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:1179
GlobalHandles * global_handles()
Definition: isolate.h:865
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:1004
void increase_index_offset(uint32_t delta)
Definition: runtime.cc:9557
static void TransformToFastProperties(Handle< JSObject > object, int unused_property_fields)
Definition: objects.cc:3352
const uintptr_t kUintptrAllBitsSet
Definition: globals.h:248
static const int kFirstCapture
Definition: jsregexp.h:146
static bool decode(uint32_t value)
Definition: utils.h:272
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: globals.h:321
void Update(Map *map, String *name, int field_offset)
Definition: heap.cc:6982
static Handle< Object > SetLocalPropertyIgnoreAttributes(Handle< JSObject > object, Handle< String > key, Handle< Object > value, PropertyAttributes attributes)
Definition: objects.cc:2924
const Register pc
Vector< const uc16 > ToUC16Vector()
Definition: objects.h:6924
double modulo(double x, double y)
int length() const
Definition: utils.h:383
static Handle< Object > Exec(Handle< JSRegExp > regexp, Handle< String > subject, int index, Handle< JSArray > lastMatchInfo, Zone *zone)
Definition: jsregexp.cc:231
void EnsureCapacity(int elements)
Definition: runtime.cc:2328
Handle< FixedArray > GetKeysInFixedArrayFor(Handle< JSReceiver > object, KeyCollectionType type, bool *threw)
Definition: handles.cc:600
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:9663
bool IsTwoByteRepresentation()
Definition: objects-inl.h:295
Object * FastPropertyAt(int index)
Definition: objects-inl.h:1521
static ExternalPixelArray * cast(Object *obj)
bool IsFastSmiElementsKind(ElementsKind kind)
static int GetLastCaptureCount(FixedArray *array)
Definition: jsregexp.h:180
static const int kMakeHeapIterableMask
Definition: heap.h:1056
static const int kIgnoreCaseFieldIndex
Definition: objects.h:6484
double power_double_int(double x, int y)
Definition: assembler.cc:1164
AccessType
Definition: v8.h:2101
static const int kHeaderSize
Definition: objects.h:7282
Definition: v8.h:104
WriteBarrierMode GetWriteBarrierMode(const AssertNoAllocation &)
Definition: objects-inl.h:1769
int CompareChars(const lchar *lhs, const rchar *rhs, int chars)
Definition: utils.h:767
PropertyDetails GetDetails(int descriptor_number)
Definition: objects-inl.h:1996
static JavaScriptFrame * cast(StackFrame *frame)
Definition: frames.h:532
Failure * Throw(Object *exception, MessageLocation *location=NULL)
Definition: isolate.cc:918
static MaybeObject * GetObjRetainers(int obj_id, Handle< JSObject > instance_filter, bool verbose, int start, int count, Handle< JSObject > filter_obj)
static MaybeObject * FunctionGetArguments(Object *object, void *)
Definition: accessors.cc:589
static ScopeInfo * Empty()
Definition: scopeinfo.cc:152
unibrow::Mapping< unibrow::ToUppercase, 128 > * to_upper_mapping()
Definition: runtime.h:552
static uint32_t MakeArrayIndexHash(uint32_t value, int length)
Definition: objects.cc:7218
void Lookup(String *name, LookupResult *result)
Definition: objects.cc:4212
void set_map_no_write_barrier(Map *value)
Definition: objects-inl.h:1146
Handle< FixedArray > CopyFixedArray(Handle< FixedArray > array)
Definition: factory.cc:516
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:144
Vector< const char > CStrVector(const char *data)
Definition: utils.h:525
Handle< ObjectHashTable > PutIntoObjectHashTable(Handle< ObjectHashTable > table, Handle< Object > key, Handle< Object > value)
Definition: handles.cc:794
void VisitThread(Isolate *isolate, ThreadLocalTop *top)
Definition: runtime.cc:8259
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:2409
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:1019
ContextLookupFlags
Definition: contexts.h:38
Context * context()
Definition: isolate.h:518
static const int kMaxLoopNestingMarker
Definition: objects.h:4491
bool IsFastSmiOrObjectElementsKind(ElementsKind kind)
void FindStringIndicesDispatch(Isolate *isolate, String *subject, String *pattern, ZoneList< int > *indices, unsigned int limit, Zone *zone)
Definition: runtime.cc:2855
static int StringMatch(Isolate *isolate, Handle< String > sub, Handle< String > pat, int index)
Definition: runtime.cc:3493
const SwVfpRegister s1
static SeqTwoByteString * cast(Object *obj)
static const int kLastMatchOverhead
Definition: jsregexp.h:147
MUST_USE_RESULT MaybeObject * AllocateJSProxy(Object *handler, Object *prototype)
Definition: heap.cc:4025
LocalElementType HasLocalElement(uint32_t index)
Definition: objects.cc:8949
static ExternalDoubleArray * cast(Object *obj)
static ExternalFloatArray * cast(Object *obj)
FlatContent GetFlatContent()
Definition: objects.cc:6119
int ArithmeticShiftRight(int x, int s)
Definition: utils.h:117
void set(int index, double value)
Definition: objects-inl.h:1746
MaybeObject * AllocateRawString(Isolate *isolate, int length)
bool has_named_interceptor()
Definition: objects.h:4638
static MUST_USE_RESULT MaybeObject * FunctionSetPrototype(JSObject *object, Object *value, void *)
Definition: accessors.cc:476
int Lookup(Map *map, String *name)
Definition: heap.cc:6970
char * DoubleToPrecisionCString(double value, int p)
Definition: conversions.cc:292
int32_t DoubleToInt32(double x)
int InitialSemiSpaceSize()
Definition: heap.h:470
void LocalLookup(String *name, LookupResult *result)
Definition: objects.cc:4170
static HeapNumber * cast(Object *obj)
static void WriteToFlat(String *source, sinkchar *sink, int from, int to)
Definition: objects.cc:6819
const int kStringBuilderConcatHelperLengthBits
Definition: runtime.cc:2390
MUST_USE_RESULT MaybeObject * NormalizeElements()
Definition: objects.cc:3376
static StringDictionary * cast(Object *obj)
Definition: objects.h:3153
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:3311
bool is_null() const
Definition: handles.h:87
JavaScriptFrameIteratorTemp< StackFrameIterator > JavaScriptFrameIterator
Definition: frames.h:773
#define RUNTIME_ASSERT(value)
Definition: runtime.cc:67
static const int kAtomPatternIndex
Definition: objects.h:6443
void AddSubjectSlice(int from, int to)
Definition: runtime.cc:2446
static void Enter(Heap *heap, FixedArray *cache, String *string, String *pattern, FixedArray *array)
Definition: heap.cc:2751
static JSGlobalPropertyCell * cast(Object *obj)
static Deoptimizer * Grab(Isolate *isolate)
Definition: deoptimizer.cc:98
static bool CompileOptimized(Handle< JSFunction > function, int osr_ast_id, ClearExceptionFlag flag)
Definition: objects.cc:7480
#define UNIMPLEMENTED()
Definition: checks.h:48
uint16_t uc16
Definition: globals.h:273
static bool IsUpperCaseChar(RuntimeState *runtime_state, uint16_t ch)
Definition: runtime.cc:6616
void set_extension(Object *object)
Definition: contexts.h:313
PropertyDetails DetailsAt(int entry)
Definition: objects.h:3049
Handle< Object > NewTypeError(const char *type, Vector< Handle< Object > > args)
Definition: factory.cc:614
static Handle< Object > CreateArrayLiteralBoilerplate(Isolate *isolate, Handle< FixedArray > literals, Handle< FixedArray > elements)
Definition: runtime.cc:461
static Handle< Object > GetFunctionDelegate(Handle< Object > object)
Definition: execution.cc:223
static JSReceiver * cast(Object *obj)
static JSValue * cast(Object *obj)
Definition: objects-inl.h:4327
bool IsFunctionContext()
Definition: contexts.h:339
void AddString(Handle< String > string)
Definition: runtime.cc:2452
static void PrintError(const char *format,...)
static Handle< T > null()
Definition: handles.h:86
bool is_undetectable()
Definition: objects.h:4661
void MemsetPointer(T **dest, U *value, int counter)
Definition: v8utils.h:146
kPropertyAccessorsOffset kNamedPropertyHandlerOffset kInstanceTemplateOffset kAccessCheckInfoOffset kEvalFrominstructionsOffsetOffset kThisPropertyAssignmentsOffset flag
Definition: objects-inl.h:3682
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:2326
static void IncrementLiveBytesFromMutator(Address address, int by)
Definition: spaces.cc:764
#define HEAP
Definition: isolate.h:1408
void set_is_access_check_needed(bool access_check_needed)
Definition: objects-inl.h:2932
MUST_USE_RESULT MaybeObject * GetProperty(String *key)
Definition: objects-inl.h:851
static MUST_USE_RESULT MaybeObject * GetObjectProperty(Isolate *isolate, Handle< Object > object, Handle< Object > key)
Definition: runtime.cc:4288
#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 trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt 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 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
Definition: flags.cc:274
static const int kIndexIndex
Definition: objects.h:8136
Object * extension()
Definition: contexts.h:312
static bool CompileLazy(Handle< SharedFunctionInfo > shared, ClearExceptionFlag flag)
Definition: objects.cc:7458
InstanceType instance_type()
Definition: objects-inl.h:2864
static MUST_USE_RESULT MaybeObject * ForceSetObjectProperty(Isolate *isolate, Handle< JSObject > object, Handle< Object > key, Handle< Object > value, PropertyAttributes attr)
Definition: runtime.cc:4622
static JSProxy * cast(Object *obj)
#define CONVERT_ARG_HANDLE_CHECKED(Type, name, index)
Definition: runtime.cc:77
void USE(T)
Definition: globals.h:303
int32_t NumberToInt32(Object *number)
Definition: v8conversions.h:37
Counters * counters()
Definition: isolate.h:804
static Object * GetPath(int obj_id1, int obj_id2, Handle< JSObject > instance_filter)
MUST_USE_RESULT MaybeObject * CopyDropTransitions(DescriptorArray::SharedMode shared_mode)
Definition: objects.cc:4920
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 true
Definition: flags.cc:157
static AccessorInfo * cast(Object *obj)
static FixedArray * cast(Object *obj)
static const int kHeaderSize
Definition: objects.h:2115
Handle< FixedDoubleArray > CopyFixedDoubleArray(Handle< FixedDoubleArray > array)
Definition: factory.cc:521
static const int kBoundFunctionIndex
Definition: objects.h:5997
Failure * ThrowIllegalOperation()
Definition: isolate.cc:939
static Handle< Object > GetElement(Handle< Object > object, uint32_t index)
Definition: objects.cc:244
static Handle< Object > PreventExtensions(Handle< JSObject > object)
Definition: objects.cc:4039
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:38
bool IsEmpty() const
Definition: v8.h:208
bool HasCapacity(int elements)
Definition: runtime.cc:2322
#define FACTORY
Definition: isolate.h:1409
double FastI2D(int x)
Definition: conversions.h:73
static void NormalizeProperties(Handle< JSObject > object, PropertyNormalizationMode mode, int expected_additional_properties)
Definition: objects.cc:3228
void Reset(Input input)
Definition: unicode-inl.h:231
Definition: v8.h:1381
Object * get(int index)
Definition: objects-inl.h:1675
int FindEntry(String *key)
Definition: objects.cc:11109
static Handle< Object > ToString(Handle< Object > obj, bool *exc)
Definition: execution.cc:614
bool IsFastHoleyElementsKind(ElementsKind kind)
static const int kMaxInliningLevels
Definition: compiler.h:278
Handle< FixedArray > array()
Definition: runtime.cc:2358
V8EXPORT Local< Object > ToObject() const
Definition: api.cc:2345
static uint32_t & uint32_at(Address addr)
Definition: v8memory.h:47
void CreateFillerObjectAt(Address addr, int size)
Definition: heap.cc:3447
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:786
static bool is_valid(T value)
Definition: utils.h:256
BitField< int, kStringBuilderConcatHelperLengthBits, kStringBuilderConcatHelperPositionBits > StringBuilderSubstringPosition
Definition: runtime.cc:2404
static Object * GetObj(int obj_id)
static const int kMaxLength
Definition: objects.h:7166
static Handle< Object > Compile(Handle< JSRegExp > re, Handle< String > pattern, Handle< String > flags)
Definition: jsregexp.cc:168
bool HasLocalProperty(String *name)
Definition: objects-inl.h:4770
static ExternalByteArray * cast(Object *obj)
Vector< Handle< Object > > HandleVector(v8::internal::Handle< T > *elms, int length)
Definition: v8utils.h:114
char * DoubleToRadixCString(double value, int radix)
Definition: conversions.cc:362
static MaybeObject * Capture()
static const int kLastIndexFieldIndex
Definition: objects.h:6486
ActivationsFinder(JSFunction *function)
Definition: runtime.cc:8256
static GlobalObject * cast(Object *obj)
static const int kBoundThisIndex
Definition: objects.h:5998
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:56
#define INLINE_RUNTIME_FUNCTION_LIST(F)
Definition: runtime.h:531
static ConsString * cast(Object *obj)
static Handle< Object > TryGetConstructorDelegate(Handle< Object > object, bool *has_pending_exception)
Definition: execution.cc:307
#define LOGGER
Definition: isolate.h:1411
static int NewElementsCapacity(int old_capacity)
Definition: objects.h:1748
static FixedArrayBase * cast(Object *object)
Definition: objects-inl.h:1669
#define CONVERT_NUMBER_CHECKED(type, name, Type, obj)
Definition: runtime.cc:105
int jsframe_count() const
Definition: deoptimizer.h:123
#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:1006
static void DebugBreak()
static const int kBoundArgumentsStartIndex
Definition: objects.h:5999
static ExternalUnsignedIntArray * cast(Object *obj)
static const int kNotFound
Definition: objects.h:2606
static void DefineAccessor(Handle< JSObject > object, Handle< String > name, Handle< Object > getter, Handle< Object > setter, PropertyAttributes attributes)
Definition: objects.cc:4480
void check(i::Vector< const char > string)
static void FatalProcessOutOfMemory(const char *location, bool take_snapshot=false)
NewSpace * new_space()
Definition: heap.h:499
#define ARRAY_SIZE(a)
Definition: globals.h:295
StringDictionary * property_dictionary()
Definition: objects-inl.h:4626
Handle< ObjectHashSet > NewObjectHashSet(int at_least_space_for)
Definition: factory.cc:99
static void PauseProfiler()
Definition: api.cc:5322
static const int kMaxLength
Definition: objects.h:7321
Object * GetParameter(int index) const
Definition: frames-inl.h:211
static Handle< Object > TryGetFunctionDelegate(Handle< Object > object, bool *has_pending_exception)
Definition: execution.cc:250
#define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name)
Definition: runtime.cc:13484
void set_allow_osr_at_loop_nesting_level(int level)
Definition: objects-inl.h:3151
static ObjectHashSet * cast(Object *obj)
Definition: objects.h:3291
static JSObject * cast(Object *obj)
void ClearInlineCaches()
Definition: objects.cc:8243
static const int kMaxArrayIndexSize
Definition: objects.h:7104
static MUST_USE_RESULT MaybeObject * GetElementOrCharAt(Isolate *isolate, Handle< Object > object, uint32_t index)
Definition: runtime.cc:4263
FlagType type() const
Definition: flags.cc:1358
unsigned int uchar
Definition: unicode.h:40
int FastD2I(double x)
Definition: conversions.h:64
V8EXPORT Local< Uint32 > ToArrayIndex() const
Definition: api.cc:2625
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
static v8::internal::Handle< v8::internal::TemplateInfo > OpenHandle(const Template *that)
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:2304
static void SetCapture(FixedArray *array, int index, int to)
Definition: jsregexp.h:176
static JSGlobalObject * cast(Object *obj)
static JSFunction * cast(Object *obj)