v8  3.25.30(node0.11.13)
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 #include <limits>
30 
31 #include "v8.h"
32 
33 #include "accessors.h"
34 #include "allocation-site-scopes.h"
35 #include "api.h"
36 #include "arguments.h"
37 #include "bootstrapper.h"
38 #include "codegen.h"
39 #include "compilation-cache.h"
40 #include "compiler.h"
41 #include "cpu.h"
42 #include "cpu-profiler.h"
43 #include "dateparser-inl.h"
44 #include "debug.h"
45 #include "deoptimizer.h"
46 #include "date.h"
47 #include "execution.h"
48 #include "full-codegen.h"
49 #include "global-handles.h"
50 #include "isolate-inl.h"
51 #include "jsregexp.h"
52 #include "jsregexp-inl.h"
53 #include "json-parser.h"
54 #include "json-stringifier.h"
55 #include "liveedit.h"
56 #include "misc-intrinsics.h"
57 #include "parser.h"
58 #include "platform.h"
59 #include "runtime-profiler.h"
60 #include "runtime.h"
61 #include "scopeinfo.h"
62 #include "smart-pointers.h"
63 #include "string-search.h"
64 #include "stub-cache.h"
65 #include "uri.h"
66 #include "v8conversions.h"
67 #include "v8threads.h"
68 #include "vm-state-inl.h"
69 
70 #ifdef V8_I18N_SUPPORT
71 #include "i18n.h"
72 #include "unicode/brkiter.h"
73 #include "unicode/calendar.h"
74 #include "unicode/coll.h"
75 #include "unicode/curramt.h"
76 #include "unicode/datefmt.h"
77 #include "unicode/dcfmtsym.h"
78 #include "unicode/decimfmt.h"
79 #include "unicode/dtfmtsym.h"
80 #include "unicode/dtptngen.h"
81 #include "unicode/locid.h"
82 #include "unicode/numfmt.h"
83 #include "unicode/numsys.h"
84 #include "unicode/rbbi.h"
85 #include "unicode/smpdtfmt.h"
86 #include "unicode/timezone.h"
87 #include "unicode/uchar.h"
88 #include "unicode/ucol.h"
89 #include "unicode/ucurr.h"
90 #include "unicode/uloc.h"
91 #include "unicode/unum.h"
92 #include "unicode/uversion.h"
93 #endif
94 
95 #ifndef _STLP_VENDOR_CSTD
96 // STLPort doesn't import fpclassify and isless into the std namespace.
97 using std::fpclassify;
98 using std::isless;
99 #endif
100 
101 namespace v8 {
102 namespace internal {
103 
104 
105 #define RUNTIME_ASSERT(value) \
106  if (!(value)) return isolate->ThrowIllegalOperation();
107 
108 // Cast the given object to a value of the specified type and store
109 // it in a variable with the given name. If the object is not of the
110 // expected type call IllegalOperation and return.
111 #define CONVERT_ARG_CHECKED(Type, name, index) \
112  RUNTIME_ASSERT(args[index]->Is##Type()); \
113  Type* name = Type::cast(args[index]);
114 
115 #define CONVERT_ARG_HANDLE_CHECKED(Type, name, index) \
116  RUNTIME_ASSERT(args[index]->Is##Type()); \
117  Handle<Type> name = args.at<Type>(index);
118 
119 // Cast the given object to a boolean and store it in a variable with
120 // the given name. If the object is not a boolean call IllegalOperation
121 // and return.
122 #define CONVERT_BOOLEAN_ARG_CHECKED(name, index) \
123  RUNTIME_ASSERT(args[index]->IsBoolean()); \
124  bool name = args[index]->IsTrue();
125 
126 // Cast the given argument to a Smi and store its value in an int variable
127 // with the given name. If the argument is not a Smi call IllegalOperation
128 // and return.
129 #define CONVERT_SMI_ARG_CHECKED(name, index) \
130  RUNTIME_ASSERT(args[index]->IsSmi()); \
131  int name = args.smi_at(index);
132 
133 // Cast the given argument to a double and store it in a variable with
134 // the given name. If the argument is not a number (as opposed to
135 // the number not-a-number) call IllegalOperation and return.
136 #define CONVERT_DOUBLE_ARG_CHECKED(name, index) \
137  RUNTIME_ASSERT(args[index]->IsNumber()); \
138  double name = args.number_at(index);
139 
140 // Call the specified converter on the object *comand store the result in
141 // a variable of the specified type with the given name. If the
142 // object is not a Number call IllegalOperation and return.
143 #define CONVERT_NUMBER_CHECKED(type, name, Type, obj) \
144  RUNTIME_ASSERT(obj->IsNumber()); \
145  type name = NumberTo##Type(obj);
146 
147 
148 // Cast the given argument to PropertyDetails and store its value in a
149 // variable with the given name. If the argument is not a Smi call
150 // IllegalOperation and return.
151 #define CONVERT_PROPERTY_DETAILS_CHECKED(name, index) \
152  RUNTIME_ASSERT(args[index]->IsSmi()); \
153  PropertyDetails name = PropertyDetails(Smi::cast(args[index]));
154 
155 
156 // Assert that the given argument has a valid value for a StrictMode
157 // and store it in a StrictMode variable with the given name.
158 #define CONVERT_STRICT_MODE_ARG_CHECKED(name, index) \
159  RUNTIME_ASSERT(args[index]->IsSmi()); \
160  RUNTIME_ASSERT(args.smi_at(index) == STRICT || \
161  args.smi_at(index) == SLOPPY); \
162  StrictMode name = static_cast<StrictMode>(args.smi_at(index));
163 
164 
165 static Handle<Map> ComputeObjectLiteralMap(
166  Handle<Context> context,
167  Handle<FixedArray> constant_properties,
168  bool* is_result_from_cache) {
169  Isolate* isolate = context->GetIsolate();
170  int properties_length = constant_properties->length();
171  int number_of_properties = properties_length / 2;
172  // Check that there are only internal strings and array indices among keys.
173  int number_of_string_keys = 0;
174  for (int p = 0; p != properties_length; p += 2) {
175  Object* key = constant_properties->get(p);
176  uint32_t element_index = 0;
177  if (key->IsInternalizedString()) {
178  number_of_string_keys++;
179  } else if (key->ToArrayIndex(&element_index)) {
180  // An index key does not require space in the property backing store.
181  number_of_properties--;
182  } else {
183  // Bail out as a non-internalized-string non-index key makes caching
184  // impossible.
185  // ASSERT to make sure that the if condition after the loop is false.
186  ASSERT(number_of_string_keys != number_of_properties);
187  break;
188  }
189  }
190  // If we only have internalized strings and array indices among keys then we
191  // can use the map cache in the native context.
192  const int kMaxKeys = 10;
193  if ((number_of_string_keys == number_of_properties) &&
194  (number_of_string_keys < kMaxKeys)) {
195  // Create the fixed array with the key.
196  Handle<FixedArray> keys =
197  isolate->factory()->NewFixedArray(number_of_string_keys);
198  if (number_of_string_keys > 0) {
199  int index = 0;
200  for (int p = 0; p < properties_length; p += 2) {
201  Object* key = constant_properties->get(p);
202  if (key->IsInternalizedString()) {
203  keys->set(index++, key);
204  }
205  }
206  ASSERT(index == number_of_string_keys);
207  }
208  *is_result_from_cache = true;
209  return isolate->factory()->ObjectLiteralMapFromCache(context, keys);
210  }
211  *is_result_from_cache = false;
212  return isolate->factory()->CopyMap(
213  Handle<Map>(context->object_function()->initial_map()),
214  number_of_properties);
215 }
216 
217 
218 static Handle<Object> CreateLiteralBoilerplate(
219  Isolate* isolate,
220  Handle<FixedArray> literals,
221  Handle<FixedArray> constant_properties);
222 
223 
224 static Handle<Object> CreateObjectLiteralBoilerplate(
225  Isolate* isolate,
226  Handle<FixedArray> literals,
227  Handle<FixedArray> constant_properties,
228  bool should_have_fast_elements,
229  bool has_function_literal) {
230  // Get the native context from the literals array. This is the
231  // context in which the function was created and we use the object
232  // function from this context to create the object literal. We do
233  // not use the object function from the current native context
234  // because this might be the object function from another context
235  // which we should not have access to.
236  Handle<Context> context =
237  Handle<Context>(JSFunction::NativeContextFromLiterals(*literals));
238 
239  // In case we have function literals, we want the object to be in
240  // slow properties mode for now. We don't go in the map cache because
241  // maps with constant functions can't be shared if the functions are
242  // not the same (which is the common case).
243  bool is_result_from_cache = false;
244  Handle<Map> map = has_function_literal
245  ? Handle<Map>(context->object_function()->initial_map())
246  : ComputeObjectLiteralMap(context,
247  constant_properties,
248  &is_result_from_cache);
249 
250  PretenureFlag pretenure_flag =
251  isolate->heap()->InNewSpace(*literals) ? NOT_TENURED : TENURED;
252 
253  Handle<JSObject> boilerplate =
254  isolate->factory()->NewJSObjectFromMap(map, pretenure_flag);
255 
256  // Normalize the elements of the boilerplate to save space if needed.
257  if (!should_have_fast_elements) JSObject::NormalizeElements(boilerplate);
258 
259  // Add the constant properties to the boilerplate.
260  int length = constant_properties->length();
261  bool should_transform =
262  !is_result_from_cache && boilerplate->HasFastProperties();
263  if (should_transform || has_function_literal) {
264  // Normalize the properties of object to avoid n^2 behavior
265  // when extending the object multiple properties. Indicate the number of
266  // properties to be added.
268  boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2);
269  }
270 
271  // TODO(verwaest): Support tracking representations in the boilerplate.
272  for (int index = 0; index < length; index +=2) {
273  Handle<Object> key(constant_properties->get(index+0), isolate);
274  Handle<Object> value(constant_properties->get(index+1), isolate);
275  if (value->IsFixedArray()) {
276  // The value contains the constant_properties of a
277  // simple object or array literal.
278  Handle<FixedArray> array = Handle<FixedArray>::cast(value);
279  value = CreateLiteralBoilerplate(isolate, literals, array);
280  if (value.is_null()) return value;
281  }
282  Handle<Object> result;
283  uint32_t element_index = 0;
284  StoreMode mode = value->IsJSObject() ? FORCE_FIELD : ALLOW_AS_CONSTANT;
285  if (key->IsInternalizedString()) {
286  if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
287  // Array index as string (uint32).
288  result = JSObject::SetOwnElement(
289  boilerplate, element_index, value, SLOPPY);
290  } else {
291  Handle<String> name(String::cast(*key));
292  ASSERT(!name->AsArrayIndex(&element_index));
294  boilerplate, name, value, NONE,
296  }
297  } else if (key->ToArrayIndex(&element_index)) {
298  // Array index (uint32).
299  result = JSObject::SetOwnElement(
300  boilerplate, element_index, value, SLOPPY);
301  } else {
302  // Non-uint32 number.
303  ASSERT(key->IsNumber());
304  double num = key->Number();
305  char arr[100];
306  Vector<char> buffer(arr, ARRAY_SIZE(arr));
307  const char* str = DoubleToCString(num, buffer);
308  Handle<String> name =
309  isolate->factory()->NewStringFromAscii(CStrVector(str));
311  boilerplate, name, value, NONE,
313  }
314  // If setting the property on the boilerplate throws an
315  // exception, the exception is converted to an empty handle in
316  // the handle based operations. In that case, we need to
317  // convert back to an exception.
318  if (result.is_null()) return result;
319  }
320 
321  // Transform to fast properties if necessary. For object literals with
322  // containing function literals we defer this operation until after all
323  // computed properties have been assigned so that we can generate
324  // constant function properties.
325  if (should_transform && !has_function_literal) {
327  boilerplate, boilerplate->map()->unused_property_fields());
328  }
329 
330  return boilerplate;
331 }
332 
333 
334 MaybeObject* TransitionElements(Handle<Object> object,
335  ElementsKind to_kind,
336  Isolate* isolate) {
337  HandleScope scope(isolate);
338  if (!object->IsJSObject()) return isolate->ThrowIllegalOperation();
339  ElementsKind from_kind =
340  Handle<JSObject>::cast(object)->map()->elements_kind();
341  if (Map::IsValidElementsTransition(from_kind, to_kind)) {
343  return *object;
344  }
345  return isolate->ThrowIllegalOperation();
346 }
347 
348 
349 static const int kSmiLiteralMinimumLength = 1024;
350 
351 
353  Isolate* isolate,
354  Handle<FixedArray> literals,
355  Handle<FixedArray> elements) {
356  // Create the JSArray.
357  Handle<JSFunction> constructor(
358  JSFunction::NativeContextFromLiterals(*literals)->array_function());
359 
360  PretenureFlag pretenure_flag =
361  isolate->heap()->InNewSpace(*literals) ? NOT_TENURED : TENURED;
362 
364  isolate->factory()->NewJSObject(constructor, pretenure_flag));
365 
366  ElementsKind constant_elements_kind =
367  static_cast<ElementsKind>(Smi::cast(elements->get(0))->value());
368  Handle<FixedArrayBase> constant_elements_values(
369  FixedArrayBase::cast(elements->get(1)));
370 
371  ASSERT(IsFastElementsKind(constant_elements_kind));
372  Context* native_context = isolate->context()->native_context();
373  Object* maybe_maps_array = native_context->js_array_maps();
374  ASSERT(!maybe_maps_array->IsUndefined());
375  Object* maybe_map = FixedArray::cast(maybe_maps_array)->get(
376  constant_elements_kind);
377  ASSERT(maybe_map->IsMap());
378  object->set_map(Map::cast(maybe_map));
379 
380  Handle<FixedArrayBase> copied_elements_values;
381  if (IsFastDoubleElementsKind(constant_elements_kind)) {
382  ASSERT(FLAG_smi_only_arrays);
383  copied_elements_values = isolate->factory()->CopyFixedDoubleArray(
384  Handle<FixedDoubleArray>::cast(constant_elements_values));
385  } else {
386  ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind));
387  const bool is_cow =
388  (constant_elements_values->map() ==
389  isolate->heap()->fixed_cow_array_map());
390  if (is_cow) {
391  copied_elements_values = constant_elements_values;
392 #if DEBUG
393  Handle<FixedArray> fixed_array_values =
394  Handle<FixedArray>::cast(copied_elements_values);
395  for (int i = 0; i < fixed_array_values->length(); i++) {
396  ASSERT(!fixed_array_values->get(i)->IsFixedArray());
397  }
398 #endif
399  } else {
400  Handle<FixedArray> fixed_array_values =
401  Handle<FixedArray>::cast(constant_elements_values);
402  Handle<FixedArray> fixed_array_values_copy =
403  isolate->factory()->CopyFixedArray(fixed_array_values);
404  copied_elements_values = fixed_array_values_copy;
405  for (int i = 0; i < fixed_array_values->length(); i++) {
406  Object* current = fixed_array_values->get(i);
407  if (current->IsFixedArray()) {
408  // The value contains the constant_properties of a
409  // simple object or array literal.
410  Handle<FixedArray> fa(FixedArray::cast(fixed_array_values->get(i)));
411  Handle<Object> result =
412  CreateLiteralBoilerplate(isolate, literals, fa);
413  if (result.is_null()) return result;
414  fixed_array_values_copy->set(i, *result);
415  }
416  }
417  }
418  }
419  object->set_elements(*copied_elements_values);
420  object->set_length(Smi::FromInt(copied_elements_values->length()));
421 
422  // Ensure that the boilerplate object has FAST_*_ELEMENTS, unless the flag is
423  // on or the object is larger than the threshold.
424  if (!FLAG_smi_only_arrays &&
425  constant_elements_values->length() < kSmiLiteralMinimumLength) {
426  ElementsKind elements_kind = object->GetElementsKind();
427  if (!IsFastObjectElementsKind(elements_kind)) {
428  if (IsFastHoleyElementsKind(elements_kind)) {
430  isolate)->IsFailure());
431  } else {
432  CHECK(!TransitionElements(object, FAST_ELEMENTS, isolate)->IsFailure());
433  }
434  }
435  }
436 
437  object->ValidateElements();
438  return object;
439 }
440 
441 
442 static Handle<Object> CreateLiteralBoilerplate(
443  Isolate* isolate,
444  Handle<FixedArray> literals,
445  Handle<FixedArray> array) {
447  const bool kHasNoFunctionLiteral = false;
448  switch (CompileTimeValue::GetLiteralType(array)) {
450  return CreateObjectLiteralBoilerplate(isolate,
451  literals,
452  elements,
453  true,
454  kHasNoFunctionLiteral);
456  return CreateObjectLiteralBoilerplate(isolate,
457  literals,
458  elements,
459  false,
460  kHasNoFunctionLiteral);
463  isolate, literals, elements);
464  default:
465  UNREACHABLE();
466  return Handle<Object>::null();
467  }
468 }
469 
470 
471 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_CreateObjectLiteral) {
472  HandleScope scope(isolate);
473  ASSERT(args.length() == 4);
475  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
476  CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2);
478  bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
479  bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
480 
481  // Check if boilerplate exists. If not, create it first.
482  Handle<Object> literal_site(literals->get(literals_index), isolate);
484  Handle<JSObject> boilerplate;
485  if (*literal_site == isolate->heap()->undefined_value()) {
486  Handle<Object> raw_boilerplate = CreateObjectLiteralBoilerplate(
487  isolate,
488  literals,
489  constant_properties,
490  should_have_fast_elements,
491  has_function_literal);
492  RETURN_IF_EMPTY_HANDLE(isolate, raw_boilerplate);
493  boilerplate = Handle<JSObject>::cast(raw_boilerplate);
494 
495  AllocationSiteCreationContext creation_context(isolate);
496  site = creation_context.EnterNewScope();
497  RETURN_IF_EMPTY_HANDLE(isolate,
498  JSObject::DeepWalk(boilerplate, &creation_context));
499  creation_context.ExitScope(site, boilerplate);
500 
501  // Update the functions literal and return the boilerplate.
502  literals->set(literals_index, *site);
503  } else {
504  site = Handle<AllocationSite>::cast(literal_site);
505  boilerplate = Handle<JSObject>(JSObject::cast(site->transition_info()),
506  isolate);
507  }
508 
509  AllocationSiteUsageContext usage_context(isolate, site, true);
510  usage_context.EnterNewScope();
511  Handle<Object> copy = JSObject::DeepCopy(boilerplate, &usage_context);
512  usage_context.ExitScope(site, boilerplate);
513  RETURN_IF_EMPTY_HANDLE(isolate, copy);
514  return *copy;
515 }
516 
517 
518 static Handle<AllocationSite> GetLiteralAllocationSite(
519  Isolate* isolate,
520  Handle<FixedArray> literals,
521  int literals_index,
522  Handle<FixedArray> elements) {
523  // Check if boilerplate exists. If not, create it first.
524  Handle<Object> literal_site(literals->get(literals_index), isolate);
526  if (*literal_site == isolate->heap()->undefined_value()) {
527  ASSERT(*elements != isolate->heap()->empty_fixed_array());
528  Handle<Object> boilerplate =
529  Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
530  if (boilerplate.is_null()) return Handle<AllocationSite>::null();
531 
532  AllocationSiteCreationContext creation_context(isolate);
533  site = creation_context.EnterNewScope();
535  &creation_context).is_null()) {
537  }
538  creation_context.ExitScope(site, Handle<JSObject>::cast(boilerplate));
539 
540  literals->set(literals_index, *site);
541  } else {
542  site = Handle<AllocationSite>::cast(literal_site);
543  }
544 
545  return site;
546 }
547 
548 
549 static MaybeObject* CreateArrayLiteralImpl(Isolate* isolate,
550  Handle<FixedArray> literals,
551  int literals_index,
552  Handle<FixedArray> elements,
553  int flags) {
554  Handle<AllocationSite> site = GetLiteralAllocationSite(isolate, literals,
555  literals_index, elements);
556  RETURN_IF_EMPTY_HANDLE(isolate, site);
557 
558  bool enable_mementos = (flags & ArrayLiteral::kDisableMementos) == 0;
559  Handle<JSObject> boilerplate(JSObject::cast(site->transition_info()));
560  AllocationSiteUsageContext usage_context(isolate, site, enable_mementos);
561  usage_context.EnterNewScope();
562  JSObject::DeepCopyHints hints = (flags & ArrayLiteral::kShallowElements) == 0
565  Handle<JSObject> copy = JSObject::DeepCopy(boilerplate, &usage_context,
566  hints);
567  usage_context.ExitScope(site, boilerplate);
568  RETURN_IF_EMPTY_HANDLE(isolate, copy);
569  return *copy;
570 }
571 
572 
573 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_CreateArrayLiteral) {
574  HandleScope scope(isolate);
575  ASSERT(args.length() == 4);
577  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
579  CONVERT_SMI_ARG_CHECKED(flags, 3);
580 
581  return CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
582  flags);
583 }
584 
585 
586 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_CreateArrayLiteralStubBailout) {
587  HandleScope scope(isolate);
588  ASSERT(args.length() == 3);
590  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
592 
593  return CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
594  ArrayLiteral::kShallowElements);
595 }
596 
597 
598 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateSymbol) {
599  HandleScope scope(isolate);
600  ASSERT(args.length() == 1);
601  Handle<Object> name(args[0], isolate);
602  RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
603  Symbol* symbol;
604  MaybeObject* maybe = isolate->heap()->AllocateSymbol();
605  if (!maybe->To(&symbol)) return maybe;
606  if (name->IsString()) symbol->set_name(*name);
607  return symbol;
608 }
609 
610 
611 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreatePrivateSymbol) {
612  HandleScope scope(isolate);
613  ASSERT(args.length() == 1);
614  Handle<Object> name(args[0], isolate);
615  RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
616  Symbol* symbol;
617  MaybeObject* maybe = isolate->heap()->AllocatePrivateSymbol();
618  if (!maybe->To(&symbol)) return maybe;
619  if (name->IsString()) symbol->set_name(*name);
620  return symbol;
621 }
622 
623 
624 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateGlobalPrivateSymbol) {
625  HandleScope scope(isolate);
626  ASSERT(args.length() == 1);
628  Handle<JSObject> registry = isolate->GetSymbolRegistry();
629  Handle<String> part = isolate->factory()->private_intern_string();
630  Handle<JSObject> privates =
632  Handle<Object> symbol = JSObject::GetProperty(privates, name);
633  if (!symbol->IsSymbol()) {
634  ASSERT(symbol->IsUndefined());
635  symbol = isolate->factory()->NewPrivateSymbol();
636  Handle<Symbol>::cast(symbol)->set_name(*name);
637  JSObject::SetProperty(privates, name, symbol, NONE, STRICT);
638  }
639  return *symbol;
640 }
641 
642 
643 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewSymbolWrapper) {
644  ASSERT(args.length() == 1);
645  CONVERT_ARG_CHECKED(Symbol, symbol, 0);
646  return symbol->ToObject(isolate);
647 }
648 
649 
650 RUNTIME_FUNCTION(MaybeObject*, Runtime_SymbolDescription) {
651  SealHandleScope shs(isolate);
652  ASSERT(args.length() == 1);
653  CONVERT_ARG_CHECKED(Symbol, symbol, 0);
654  return symbol->name();
655 }
656 
657 
658 RUNTIME_FUNCTION(MaybeObject*, Runtime_SymbolRegistry) {
659  HandleScope scope(isolate);
660  ASSERT(args.length() == 0);
661  return *isolate->GetSymbolRegistry();
662 }
663 
664 
665 RUNTIME_FUNCTION(MaybeObject*, Runtime_SymbolIsPrivate) {
666  SealHandleScope shs(isolate);
667  ASSERT(args.length() == 1);
668  CONVERT_ARG_CHECKED(Symbol, symbol, 0);
669  return isolate->heap()->ToBoolean(symbol->is_private());
670 }
671 
672 
673 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSProxy) {
674  SealHandleScope shs(isolate);
675  ASSERT(args.length() == 2);
676  CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
677  Object* prototype = args[1];
678  Object* used_prototype =
679  prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
680  return isolate->heap()->AllocateJSProxy(handler, used_prototype);
681 }
682 
683 
684 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSFunctionProxy) {
685  SealHandleScope shs(isolate);
686  ASSERT(args.length() == 4);
687  CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
688  Object* call_trap = args[1];
689  RUNTIME_ASSERT(call_trap->IsJSFunction() || call_trap->IsJSFunctionProxy());
690  CONVERT_ARG_CHECKED(JSFunction, construct_trap, 2);
691  Object* prototype = args[3];
692  Object* used_prototype =
693  prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
694  return isolate->heap()->AllocateJSFunctionProxy(
695  handler, call_trap, construct_trap, used_prototype);
696 }
697 
698 
699 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSProxy) {
700  SealHandleScope shs(isolate);
701  ASSERT(args.length() == 1);
702  Object* obj = args[0];
703  return isolate->heap()->ToBoolean(obj->IsJSProxy());
704 }
705 
706 
707 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSFunctionProxy) {
708  SealHandleScope shs(isolate);
709  ASSERT(args.length() == 1);
710  Object* obj = args[0];
711  return isolate->heap()->ToBoolean(obj->IsJSFunctionProxy());
712 }
713 
714 
715 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHandler) {
716  SealHandleScope shs(isolate);
717  ASSERT(args.length() == 1);
718  CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
719  return proxy->handler();
720 }
721 
722 
723 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetCallTrap) {
724  SealHandleScope shs(isolate);
725  ASSERT(args.length() == 1);
727  return proxy->call_trap();
728 }
729 
730 
731 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructTrap) {
732  SealHandleScope shs(isolate);
733  ASSERT(args.length() == 1);
735  return proxy->construct_trap();
736 }
737 
738 
739 RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) {
740  HandleScope scope(isolate);
741  ASSERT(args.length() == 1);
743  JSProxy::Fix(proxy);
744  return isolate->heap()->undefined_value();
745 }
746 
747 
749  JSArrayBuffer* phantom_array_buffer) {
750  if (phantom_array_buffer->should_be_freed()) {
751  ASSERT(phantom_array_buffer->is_external());
752  free(phantom_array_buffer->backing_store());
753  }
754  if (phantom_array_buffer->is_external()) return;
755 
756  size_t allocated_length = NumberToSize(
757  isolate, phantom_array_buffer->byte_length());
758 
760  -static_cast<int64_t>(allocated_length));
763  phantom_array_buffer->backing_store(),
764  allocated_length);
765 }
766 
767 
769  Handle<JSArrayBuffer> array_buffer,
770  bool is_external,
771  void* data,
772  size_t allocated_length) {
773  ASSERT(array_buffer->GetInternalFieldCount() ==
775  for (int i = 0; i < v8::ArrayBuffer::kInternalFieldCount; i++) {
776  array_buffer->SetInternalField(i, Smi::FromInt(0));
777  }
778  array_buffer->set_backing_store(data);
779  array_buffer->set_flag(Smi::FromInt(0));
780  array_buffer->set_is_external(is_external);
781 
782  Handle<Object> byte_length =
783  isolate->factory()->NewNumberFromSize(allocated_length);
784  CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber());
785  array_buffer->set_byte_length(*byte_length);
786 
787  array_buffer->set_weak_next(isolate->heap()->array_buffers_list());
788  isolate->heap()->set_array_buffers_list(*array_buffer);
789  array_buffer->set_weak_first_view(isolate->heap()->undefined_value());
790 }
791 
792 
794  Isolate* isolate,
795  Handle<JSArrayBuffer> array_buffer,
796  size_t allocated_length,
797  bool initialize) {
798  void* data;
800  if (allocated_length != 0) {
801  if (initialize) {
802  data = V8::ArrayBufferAllocator()->Allocate(allocated_length);
803  } else {
804  data =
805  V8::ArrayBufferAllocator()->AllocateUninitialized(allocated_length);
806  }
807  if (data == NULL) return false;
808  } else {
809  data = NULL;
810  }
811 
812  SetupArrayBuffer(isolate, array_buffer, false, data, allocated_length);
813 
814  isolate->heap()->AdjustAmountOfExternalAllocatedMemory(allocated_length);
815 
816  return true;
817 }
818 
819 
821  Isolate* isolate = array_buffer->GetIsolate();
822  for (Handle<Object> view_obj(array_buffer->weak_first_view(), isolate);
823  !view_obj->IsUndefined();) {
825  if (view->IsJSTypedArray()) {
826  JSTypedArray::cast(*view)->Neuter();
827  } else if (view->IsJSDataView()) {
828  JSDataView::cast(*view)->Neuter();
829  } else {
830  UNREACHABLE();
831  }
832  view_obj = handle(view->weak_next(), isolate);
833  }
834  array_buffer->Neuter();
835 }
836 
837 
838 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferInitialize) {
839  HandleScope scope(isolate);
840  ASSERT(args.length() == 2);
842  CONVERT_ARG_HANDLE_CHECKED(Object, byteLength, 1);
843  size_t allocated_length;
844  if (byteLength->IsSmi()) {
845  allocated_length = Smi::cast(*byteLength)->value();
846  } else {
847  ASSERT(byteLength->IsHeapNumber());
848  double value = HeapNumber::cast(*byteLength)->value();
849 
850  ASSERT(value >= 0);
851 
852  if (value > std::numeric_limits<size_t>::max()) {
853  return isolate->Throw(
854  *isolate->factory()->NewRangeError("invalid_array_buffer_length",
855  HandleVector<Object>(NULL, 0)));
856  }
857 
858  allocated_length = static_cast<size_t>(value);
859  }
860 
862  holder, allocated_length)) {
863  return isolate->Throw(*isolate->factory()->
864  NewRangeError("invalid_array_buffer_length",
865  HandleVector<Object>(NULL, 0)));
866  }
867 
868  return *holder;
869 }
870 
871 
872 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferGetByteLength) {
873  SealHandleScope shs(isolate);
874  ASSERT(args.length() == 1);
876  return holder->byte_length();
877 }
878 
879 
880 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferSliceImpl) {
881  HandleScope scope(isolate);
882  ASSERT(args.length() == 3);
885  CONVERT_DOUBLE_ARG_CHECKED(first, 2);
886  size_t start = static_cast<size_t>(first);
887  size_t target_length = NumberToSize(isolate, target->byte_length());
888 
889  if (target_length == 0) return isolate->heap()->undefined_value();
890 
891  size_t source_byte_length = NumberToSize(isolate, source->byte_length());
892  CHECK(start <= source_byte_length);
893  CHECK(source_byte_length - start >= target_length);
894  uint8_t* source_data = reinterpret_cast<uint8_t*>(source->backing_store());
895  uint8_t* target_data = reinterpret_cast<uint8_t*>(target->backing_store());
896  CopyBytes(target_data, source_data + start, target_length);
897  return isolate->heap()->undefined_value();
898 }
899 
900 
901 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferIsView) {
902  HandleScope scope(isolate);
903  ASSERT(args.length() == 1);
904  CONVERT_ARG_CHECKED(Object, object, 0);
905  return object->IsJSArrayBufferView()
906  ? isolate->heap()->true_value()
907  : isolate->heap()->false_value();
908 }
909 
910 
911 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferNeuter) {
912  HandleScope scope(isolate);
913  CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, array_buffer, 0);
914  if (array_buffer->backing_store() == NULL) {
915  CHECK(Smi::FromInt(0) == array_buffer->byte_length());
916  return isolate->heap()->undefined_value();
917  }
918  ASSERT(!array_buffer->is_external());
919  void* backing_store = array_buffer->backing_store();
920  size_t byte_length = NumberToSize(isolate, array_buffer->byte_length());
921  array_buffer->set_is_external(true);
922  Runtime::NeuterArrayBuffer(array_buffer);
923  V8::ArrayBufferAllocator()->Free(backing_store, byte_length);
924  return isolate->heap()->undefined_value();
925 }
926 
927 
929  int arrayId,
930  ExternalArrayType* array_type,
931  ElementsKind* external_elements_kind,
932  ElementsKind* fixed_elements_kind,
933  size_t* element_size) {
934  switch (arrayId) {
935 #define ARRAY_ID_CASE(Type, type, TYPE, ctype, size) \
936  case ARRAY_ID_##TYPE: \
937  *array_type = kExternal##Type##Array; \
938  *external_elements_kind = EXTERNAL_##TYPE##_ELEMENTS; \
939  *fixed_elements_kind = TYPE##_ELEMENTS; \
940  *element_size = size; \
941  break;
942 
944 #undef ARRAY_ID_CASE
945 
946  default:
947  UNREACHABLE();
948  }
949 }
950 
951 
952 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) {
953  HandleScope scope(isolate);
954  ASSERT(args.length() == 5);
956  CONVERT_SMI_ARG_CHECKED(arrayId, 1);
957  CONVERT_ARG_HANDLE_CHECKED(Object, maybe_buffer, 2);
958  CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset_object, 3);
959  CONVERT_ARG_HANDLE_CHECKED(Object, byte_length_object, 4);
960 
961  ASSERT(holder->GetInternalFieldCount() ==
963  for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
964  holder->SetInternalField(i, Smi::FromInt(0));
965  }
966 
967  ExternalArrayType array_type = kExternalInt8Array; // Bogus initialization.
968  size_t element_size = 1; // Bogus initialization.
969  ElementsKind external_elements_kind =
970  EXTERNAL_INT8_ELEMENTS; // Bogus initialization.
971  ElementsKind fixed_elements_kind = INT8_ELEMENTS; // Bogus initialization.
973  &array_type,
974  &external_elements_kind,
975  &fixed_elements_kind,
976  &element_size);
977 
978  holder->set_byte_offset(*byte_offset_object);
979  holder->set_byte_length(*byte_length_object);
980 
981  size_t byte_offset = NumberToSize(isolate, *byte_offset_object);
982  size_t byte_length = NumberToSize(isolate, *byte_length_object);
983 
984  CHECK_EQ(0, static_cast<int>(byte_length % element_size));
985  size_t length = byte_length / element_size;
986 
987  if (length > static_cast<unsigned>(Smi::kMaxValue)) {
988  return isolate->Throw(*isolate->factory()->
989  NewRangeError("invalid_typed_array_length",
990  HandleVector<Object>(NULL, 0)));
991  }
992 
993  Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length);
994  holder->set_length(*length_obj);
995  if (!maybe_buffer->IsNull()) {
996  Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(*maybe_buffer));
997 
998  size_t array_buffer_byte_length =
999  NumberToSize(isolate, buffer->byte_length());
1000  CHECK(byte_offset <= array_buffer_byte_length);
1001  CHECK(array_buffer_byte_length - byte_offset >= byte_length);
1002 
1003  holder->set_buffer(*buffer);
1004  holder->set_weak_next(buffer->weak_first_view());
1005  buffer->set_weak_first_view(*holder);
1006 
1007  Handle<ExternalArray> elements =
1008  isolate->factory()->NewExternalArray(
1009  static_cast<int>(length), array_type,
1010  static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
1011  Handle<Map> map =
1012  JSObject::GetElementsTransitionMap(holder, external_elements_kind);
1013  holder->set_map_and_elements(*map, *elements);
1014  ASSERT(IsExternalArrayElementsKind(holder->map()->elements_kind()));
1015  } else {
1016  holder->set_buffer(Smi::FromInt(0));
1017  holder->set_weak_next(isolate->heap()->undefined_value());
1018  Handle<FixedTypedArrayBase> elements =
1019  isolate->factory()->NewFixedTypedArray(
1020  static_cast<int>(length), array_type);
1021  holder->set_elements(*elements);
1022  }
1023  return isolate->heap()->undefined_value();
1024 }
1025 
1026 
1027 // Initializes a typed array from an array-like object.
1028 // If an array-like object happens to be a typed array of the same type,
1029 // initializes backing store using memove.
1030 //
1031 // Returns true if backing store was initialized or false otherwise.
1032 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitializeFromArrayLike) {
1033  HandleScope scope(isolate);
1034  ASSERT(args.length() == 4);
1036  CONVERT_SMI_ARG_CHECKED(arrayId, 1);
1037  CONVERT_ARG_HANDLE_CHECKED(Object, source, 2);
1038  CONVERT_ARG_HANDLE_CHECKED(Object, length_obj, 3);
1039 
1040  ASSERT(holder->GetInternalFieldCount() ==
1042  for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
1043  holder->SetInternalField(i, Smi::FromInt(0));
1044  }
1045 
1046  ExternalArrayType array_type = kExternalInt8Array; // Bogus initialization.
1047  size_t element_size = 1; // Bogus initialization.
1048  ElementsKind external_elements_kind =
1049  EXTERNAL_INT8_ELEMENTS; // Bogus intialization.
1050  ElementsKind fixed_elements_kind = INT8_ELEMENTS; // Bogus initialization.
1052  &array_type,
1053  &external_elements_kind,
1054  &fixed_elements_kind,
1055  &element_size);
1056 
1057  Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
1058  if (source->IsJSTypedArray() &&
1059  JSTypedArray::cast(*source)->type() == array_type) {
1060  length_obj = Handle<Object>(JSTypedArray::cast(*source)->length(), isolate);
1061  }
1062  size_t length = NumberToSize(isolate, *length_obj);
1063 
1064  if ((length > static_cast<unsigned>(Smi::kMaxValue)) ||
1065  (length > (kMaxInt / element_size))) {
1066  return isolate->Throw(*isolate->factory()->
1067  NewRangeError("invalid_typed_array_length",
1068  HandleVector<Object>(NULL, 0)));
1069  }
1070  size_t byte_length = length * element_size;
1071 
1072  // NOTE: not initializing backing store.
1073  // We assume that the caller of this function will initialize holder
1074  // with the loop
1075  // for(i = 0; i < length; i++) { holder[i] = source[i]; }
1076  // We assume that the caller of this function is always a typed array
1077  // constructor.
1078  // If source is a typed array, this loop will always run to completion,
1079  // so we are sure that the backing store will be initialized.
1080  // Otherwise, the indexing operation might throw, so the loop will not
1081  // run to completion and the typed array might remain partly initialized.
1082  // However we further assume that the caller of this function is a typed array
1083  // constructor, and the exception will propagate out of the constructor,
1084  // therefore uninitialized memory will not be accessible by a user program.
1085  //
1086  // TODO(dslomov): revise this once we support subclassing.
1087 
1089  isolate, buffer, byte_length, false)) {
1090  return isolate->Throw(*isolate->factory()->
1091  NewRangeError("invalid_array_buffer_length",
1092  HandleVector<Object>(NULL, 0)));
1093  }
1094 
1095  holder->set_buffer(*buffer);
1096  holder->set_byte_offset(Smi::FromInt(0));
1097  Handle<Object> byte_length_obj(
1098  isolate->factory()->NewNumberFromSize(byte_length));
1099  holder->set_byte_length(*byte_length_obj);
1100  holder->set_length(*length_obj);
1101  holder->set_weak_next(buffer->weak_first_view());
1102  buffer->set_weak_first_view(*holder);
1103 
1104  Handle<ExternalArray> elements =
1105  isolate->factory()->NewExternalArray(
1106  static_cast<int>(length), array_type,
1107  static_cast<uint8_t*>(buffer->backing_store()));
1109  holder, external_elements_kind);
1110  holder->set_map_and_elements(*map, *elements);
1111 
1112  if (source->IsJSTypedArray()) {
1113  Handle<JSTypedArray> typed_array(JSTypedArray::cast(*source));
1114 
1115  if (typed_array->type() == holder->type()) {
1116  uint8_t* backing_store =
1117  static_cast<uint8_t*>(
1118  typed_array->GetBuffer()->backing_store());
1119  size_t source_byte_offset =
1120  NumberToSize(isolate, typed_array->byte_offset());
1121  memcpy(
1122  buffer->backing_store(),
1123  backing_store + source_byte_offset,
1124  byte_length);
1125  return *isolate->factory()->true_value();
1126  } else {
1127  return *isolate->factory()->false_value();
1128  }
1129  }
1130 
1131  return *isolate->factory()->false_value();
1132 }
1133 
1134 
1135 #define TYPED_ARRAY_GETTER(getter, accessor) \
1136  RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayGet##getter) { \
1137  HandleScope scope(isolate); \
1138  ASSERT(args.length() == 1); \
1139  CONVERT_ARG_HANDLE_CHECKED(Object, holder, 0); \
1140  if (!holder->IsJSTypedArray()) \
1141  return isolate->Throw(*isolate->factory()->NewTypeError( \
1142  "not_typed_array", HandleVector<Object>(NULL, 0))); \
1143  Handle<JSTypedArray> typed_array(JSTypedArray::cast(*holder)); \
1144  return typed_array->accessor(); \
1145  }
1146 
1147 TYPED_ARRAY_GETTER(ByteLength, byte_length)
1148 TYPED_ARRAY_GETTER(ByteOffset, byte_offset)
1149 TYPED_ARRAY_GETTER(Length, length)
1150 
1151 #undef TYPED_ARRAY_GETTER
1152 
1153 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayGetBuffer) {
1154  HandleScope scope(isolate);
1155  ASSERT(args.length() == 1);
1156  CONVERT_ARG_HANDLE_CHECKED(Object, holder, 0);
1157  if (!holder->IsJSTypedArray())
1158  return isolate->Throw(*isolate->factory()->NewTypeError(
1159  "not_typed_array", HandleVector<Object>(NULL, 0)));
1160  Handle<JSTypedArray> typed_array(JSTypedArray::cast(*holder));
1161  return *typed_array->GetBuffer();
1162 }
1163 
1164 
1165 // Return codes for Runtime_TypedArraySetFastCases.
1166 // Should be synchronized with typedarray.js natives.
1168  // Set from typed array of the same type.
1169  // This is processed by TypedArraySetFastCases
1171  // Set from typed array of the different type, overlapping in memory.
1173  // Set from typed array of the different type, non-overlapping.
1175  // Set from non-typed array.
1177 };
1178 
1179 
1180 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArraySetFastCases) {
1181  HandleScope scope(isolate);
1182  CONVERT_ARG_HANDLE_CHECKED(Object, target_obj, 0);
1183  CONVERT_ARG_HANDLE_CHECKED(Object, source_obj, 1);
1184  CONVERT_ARG_HANDLE_CHECKED(Object, offset_obj, 2);
1185 
1186  if (!target_obj->IsJSTypedArray())
1187  return isolate->Throw(*isolate->factory()->NewTypeError(
1188  "not_typed_array", HandleVector<Object>(NULL, 0)));
1189 
1190  if (!source_obj->IsJSTypedArray())
1192 
1193  Handle<JSTypedArray> target(JSTypedArray::cast(*target_obj));
1194  Handle<JSTypedArray> source(JSTypedArray::cast(*source_obj));
1195  size_t offset = NumberToSize(isolate, *offset_obj);
1196  size_t target_length = NumberToSize(isolate, target->length());
1197  size_t source_length = NumberToSize(isolate, source->length());
1198  size_t target_byte_length = NumberToSize(isolate, target->byte_length());
1199  size_t source_byte_length = NumberToSize(isolate, source->byte_length());
1200  if (offset > target_length ||
1201  offset + source_length > target_length ||
1202  offset + source_length < offset) // overflow
1203  return isolate->Throw(*isolate->factory()->NewRangeError(
1204  "typed_array_set_source_too_large", HandleVector<Object>(NULL, 0)));
1205 
1206  size_t target_offset = NumberToSize(isolate, target->byte_offset());
1207  size_t source_offset = NumberToSize(isolate, source->byte_offset());
1208  uint8_t* target_base =
1209  static_cast<uint8_t*>(
1210  target->GetBuffer()->backing_store()) + target_offset;
1211  uint8_t* source_base =
1212  static_cast<uint8_t*>(
1213  source->GetBuffer()->backing_store()) + source_offset;
1214 
1215  // Typed arrays of the same type: use memmove.
1216  if (target->type() == source->type()) {
1217  memmove(target_base + offset * target->element_size(),
1218  source_base, source_byte_length);
1220  }
1221 
1222  // Typed arrays of different types over the same backing store
1223  if ((source_base <= target_base &&
1224  source_base + source_byte_length > target_base) ||
1225  (target_base <= source_base &&
1226  target_base + target_byte_length > source_base)) {
1227  // We do not support overlapping ArrayBuffers
1228  ASSERT(
1229  target->GetBuffer()->backing_store() ==
1230  source->GetBuffer()->backing_store());
1232  } else { // Non-overlapping typed arrays
1234  }
1235 }
1236 
1237 
1238 RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayMaxSizeInHeap) {
1239  ASSERT_OBJECT_SIZE(FLAG_typed_array_max_size_in_heap);
1240  return Smi::FromInt(FLAG_typed_array_max_size_in_heap);
1241 }
1242 
1243 
1244 RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewInitialize) {
1245  HandleScope scope(isolate);
1246  ASSERT(args.length() == 4);
1249  CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset, 2);
1250  CONVERT_ARG_HANDLE_CHECKED(Object, byte_length, 3);
1251 
1252  ASSERT(holder->GetInternalFieldCount() ==
1254  for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
1255  holder->SetInternalField(i, Smi::FromInt(0));
1256  }
1257 
1258  holder->set_buffer(*buffer);
1259  ASSERT(byte_offset->IsNumber());
1260  ASSERT(
1261  NumberToSize(isolate, buffer->byte_length()) >=
1262  NumberToSize(isolate, *byte_offset)
1263  + NumberToSize(isolate, *byte_length));
1264  holder->set_byte_offset(*byte_offset);
1265  ASSERT(byte_length->IsNumber());
1266  holder->set_byte_length(*byte_length);
1267 
1268  holder->set_weak_next(buffer->weak_first_view());
1269  buffer->set_weak_first_view(*holder);
1270 
1271  return isolate->heap()->undefined_value();
1272 }
1273 
1274 
1275 RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetBuffer) {
1276  HandleScope scope(isolate);
1277  ASSERT(args.length() == 1);
1278  CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
1279  return data_view->buffer();
1280 }
1281 
1282 
1283 RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteOffset) {
1284  HandleScope scope(isolate);
1285  ASSERT(args.length() == 1);
1286  CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
1287  return data_view->byte_offset();
1288 }
1289 
1290 
1291 RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteLength) {
1292  HandleScope scope(isolate);
1293  ASSERT(args.length() == 1);
1294  CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
1295  return data_view->byte_length();
1296 }
1297 
1298 
1299 inline static bool NeedToFlipBytes(bool is_little_endian) {
1300 #ifdef V8_TARGET_LITTLE_ENDIAN
1301  return !is_little_endian;
1302 #else
1303  return is_little_endian;
1304 #endif
1305 }
1306 
1307 
1308 template<int n>
1309 inline void CopyBytes(uint8_t* target, uint8_t* source) {
1310  for (int i = 0; i < n; i++) {
1311  *(target++) = *(source++);
1312  }
1313 }
1314 
1315 
1316 template<int n>
1317 inline void FlipBytes(uint8_t* target, uint8_t* source) {
1318  source = source + (n-1);
1319  for (int i = 0; i < n; i++) {
1320  *(target++) = *(source--);
1321  }
1322 }
1323 
1324 
1325 template<typename T>
1326 inline static bool DataViewGetValue(
1327  Isolate* isolate,
1328  Handle<JSDataView> data_view,
1329  Handle<Object> byte_offset_obj,
1330  bool is_little_endian,
1331  T* result) {
1332  size_t byte_offset = 0;
1333  if (!TryNumberToSize(isolate, *byte_offset_obj, &byte_offset)) {
1334  return false;
1335  }
1336  Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer()));
1337 
1338  size_t data_view_byte_offset =
1339  NumberToSize(isolate, data_view->byte_offset());
1340  size_t data_view_byte_length =
1341  NumberToSize(isolate, data_view->byte_length());
1342  if (byte_offset + sizeof(T) > data_view_byte_length ||
1343  byte_offset + sizeof(T) < byte_offset) { // overflow
1344  return false;
1345  }
1346 
1347  union Value {
1348  T data;
1349  uint8_t bytes[sizeof(T)];
1350  };
1351 
1352  Value value;
1353  size_t buffer_offset = data_view_byte_offset + byte_offset;
1354  ASSERT(
1355  NumberToSize(isolate, buffer->byte_length())
1356  >= buffer_offset + sizeof(T));
1357  uint8_t* source =
1358  static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset;
1359  if (NeedToFlipBytes(is_little_endian)) {
1360  FlipBytes<sizeof(T)>(value.bytes, source);
1361  } else {
1362  CopyBytes<sizeof(T)>(value.bytes, source);
1363  }
1364  *result = value.data;
1365  return true;
1366 }
1367 
1368 
1369 template<typename T>
1370 static bool DataViewSetValue(
1371  Isolate* isolate,
1372  Handle<JSDataView> data_view,
1373  Handle<Object> byte_offset_obj,
1374  bool is_little_endian,
1375  T data) {
1376  size_t byte_offset = 0;
1377  if (!TryNumberToSize(isolate, *byte_offset_obj, &byte_offset)) {
1378  return false;
1379  }
1380  Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer()));
1381 
1382  size_t data_view_byte_offset =
1383  NumberToSize(isolate, data_view->byte_offset());
1384  size_t data_view_byte_length =
1385  NumberToSize(isolate, data_view->byte_length());
1386  if (byte_offset + sizeof(T) > data_view_byte_length ||
1387  byte_offset + sizeof(T) < byte_offset) { // overflow
1388  return false;
1389  }
1390 
1391  union Value {
1392  T data;
1393  uint8_t bytes[sizeof(T)];
1394  };
1395 
1396  Value value;
1397  value.data = data;
1398  size_t buffer_offset = data_view_byte_offset + byte_offset;
1399  ASSERT(
1400  NumberToSize(isolate, buffer->byte_length())
1401  >= buffer_offset + sizeof(T));
1402  uint8_t* target =
1403  static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset;
1404  if (NeedToFlipBytes(is_little_endian)) {
1405  FlipBytes<sizeof(T)>(target, value.bytes);
1406  } else {
1407  CopyBytes<sizeof(T)>(target, value.bytes);
1408  }
1409  return true;
1410 }
1411 
1412 
1413 #define DATA_VIEW_GETTER(TypeName, Type, Converter) \
1414  RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGet##TypeName) { \
1415  HandleScope scope(isolate); \
1416  ASSERT(args.length() == 3); \
1417  CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); \
1418  CONVERT_ARG_HANDLE_CHECKED(Object, offset, 1); \
1419  CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 2); \
1420  Type result; \
1421  if (DataViewGetValue( \
1422  isolate, holder, offset, is_little_endian, &result)) { \
1423  return isolate->heap()->Converter(result); \
1424  } else { \
1425  return isolate->Throw(*isolate->factory()->NewRangeError( \
1426  "invalid_data_view_accessor_offset", \
1427  HandleVector<Object>(NULL, 0))); \
1428  } \
1429  }
1430 
1431 DATA_VIEW_GETTER(Uint8, uint8_t, NumberFromUint32)
1432 DATA_VIEW_GETTER(Int8, int8_t, NumberFromInt32)
1433 DATA_VIEW_GETTER(Uint16, uint16_t, NumberFromUint32)
1434 DATA_VIEW_GETTER(Int16, int16_t, NumberFromInt32)
1435 DATA_VIEW_GETTER(Uint32, uint32_t, NumberFromUint32)
1436 DATA_VIEW_GETTER(Int32, int32_t, NumberFromInt32)
1437 DATA_VIEW_GETTER(Float32, float, NumberFromDouble)
1438 DATA_VIEW_GETTER(Float64, double, NumberFromDouble)
1439 
1440 #undef DATA_VIEW_GETTER
1441 
1442 
1443 template <typename T>
1444 static T DataViewConvertValue(double value);
1445 
1446 
1447 template <>
1448 int8_t DataViewConvertValue<int8_t>(double value) {
1449  return static_cast<int8_t>(DoubleToInt32(value));
1450 }
1451 
1452 
1453 template <>
1454 int16_t DataViewConvertValue<int16_t>(double value) {
1455  return static_cast<int16_t>(DoubleToInt32(value));
1456 }
1457 
1458 
1459 template <>
1460 int32_t DataViewConvertValue<int32_t>(double value) {
1461  return DoubleToInt32(value);
1462 }
1463 
1464 
1465 template <>
1466 uint8_t DataViewConvertValue<uint8_t>(double value) {
1467  return static_cast<uint8_t>(DoubleToUint32(value));
1468 }
1469 
1470 
1471 template <>
1472 uint16_t DataViewConvertValue<uint16_t>(double value) {
1473  return static_cast<uint16_t>(DoubleToUint32(value));
1474 }
1475 
1476 
1477 template <>
1478 uint32_t DataViewConvertValue<uint32_t>(double value) {
1479  return DoubleToUint32(value);
1480 }
1481 
1482 
1483 template <>
1484 float DataViewConvertValue<float>(double value) {
1485  return static_cast<float>(value);
1486 }
1487 
1488 
1489 template <>
1490 double DataViewConvertValue<double>(double value) {
1491  return value;
1492 }
1493 
1494 
1495 #define DATA_VIEW_SETTER(TypeName, Type) \
1496  RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewSet##TypeName) { \
1497  HandleScope scope(isolate); \
1498  ASSERT(args.length() == 4); \
1499  CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); \
1500  CONVERT_ARG_HANDLE_CHECKED(Object, offset, 1); \
1501  CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); \
1502  CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 3); \
1503  Type v = DataViewConvertValue<Type>(value->Number()); \
1504  if (DataViewSetValue( \
1505  isolate, holder, offset, is_little_endian, v)) { \
1506  return isolate->heap()->undefined_value(); \
1507  } else { \
1508  return isolate->Throw(*isolate->factory()->NewRangeError( \
1509  "invalid_data_view_accessor_offset", \
1510  HandleVector<Object>(NULL, 0))); \
1511  } \
1512  }
1513 
1514 DATA_VIEW_SETTER(Uint8, uint8_t)
1515 DATA_VIEW_SETTER(Int8, int8_t)
1516 DATA_VIEW_SETTER(Uint16, uint16_t)
1517 DATA_VIEW_SETTER(Int16, int16_t)
1518 DATA_VIEW_SETTER(Uint32, uint32_t)
1519 DATA_VIEW_SETTER(Int32, int32_t)
1520 DATA_VIEW_SETTER(Float32, float)
1521 DATA_VIEW_SETTER(Float64, double)
1522 
1523 #undef DATA_VIEW_SETTER
1524 
1525 
1526 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInitialize) {
1527  HandleScope scope(isolate);
1528  ASSERT(args.length() == 1);
1529  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1530  Handle<ObjectHashSet> table = isolate->factory()->NewObjectHashSet(0);
1531  holder->set_table(*table);
1532  return *holder;
1533 }
1534 
1535 
1536 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAdd) {
1537  HandleScope scope(isolate);
1538  ASSERT(args.length() == 2);
1539  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1540  Handle<Object> key(args[1], isolate);
1541  Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1542  table = ObjectHashSet::Add(table, key);
1543  holder->set_table(*table);
1544  return isolate->heap()->undefined_value();
1545 }
1546 
1547 
1548 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetHas) {
1549  HandleScope scope(isolate);
1550  ASSERT(args.length() == 2);
1551  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1552  Handle<Object> key(args[1], isolate);
1553  Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1554  return isolate->heap()->ToBoolean(table->Contains(*key));
1555 }
1556 
1557 
1558 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDelete) {
1559  HandleScope scope(isolate);
1560  ASSERT(args.length() == 2);
1561  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1562  Handle<Object> key(args[1], isolate);
1563  Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1564  table = ObjectHashSet::Remove(table, key);
1565  holder->set_table(*table);
1566  return isolate->heap()->undefined_value();
1567 }
1568 
1569 
1570 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetGetSize) {
1571  HandleScope scope(isolate);
1572  ASSERT(args.length() == 1);
1573  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1574  Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1575  return Smi::FromInt(table->NumberOfElements());
1576 }
1577 
1578 
1579 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapInitialize) {
1580  HandleScope scope(isolate);
1581  ASSERT(args.length() == 1);
1582  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1583  Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
1584  holder->set_table(*table);
1585  return *holder;
1586 }
1587 
1588 
1589 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGet) {
1590  HandleScope scope(isolate);
1591  ASSERT(args.length() == 2);
1592  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1594  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1595  Handle<Object> lookup(table->Lookup(*key), isolate);
1596  return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
1597 }
1598 
1599 
1600 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapHas) {
1601  HandleScope scope(isolate);
1602  ASSERT(args.length() == 2);
1603  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1605  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1606  Handle<Object> lookup(table->Lookup(*key), isolate);
1607  return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1608 }
1609 
1610 
1611 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapDelete) {
1612  HandleScope scope(isolate);
1613  ASSERT(args.length() == 2);
1614  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1616  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1617  Handle<Object> lookup(table->Lookup(*key), isolate);
1618  Handle<ObjectHashTable> new_table =
1619  ObjectHashTable::Put(table, key, isolate->factory()->the_hole_value());
1620  holder->set_table(*new_table);
1621  return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1622 }
1623 
1624 
1625 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapSet) {
1626  HandleScope scope(isolate);
1627  ASSERT(args.length() == 3);
1628  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1631  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1632  Handle<ObjectHashTable> new_table = ObjectHashTable::Put(table, key, value);
1633  holder->set_table(*new_table);
1634  return isolate->heap()->undefined_value();
1635 }
1636 
1637 
1638 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGetSize) {
1639  HandleScope scope(isolate);
1640  ASSERT(args.length() == 1);
1641  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1642  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1643  return Smi::FromInt(table->NumberOfElements());
1644 }
1645 
1646 
1647 static JSWeakCollection* WeakCollectionInitialize(Isolate* isolate,
1648  Handle<JSWeakCollection> weak_collection) {
1649  ASSERT(weak_collection->map()->inobject_properties() == 0);
1650  Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
1651  weak_collection->set_table(*table);
1652  weak_collection->set_next(Smi::FromInt(0));
1653  return *weak_collection;
1654 }
1655 
1656 
1657 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionInitialize) {
1658  HandleScope scope(isolate);
1659  ASSERT(args.length() == 1);
1660  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1661  return WeakCollectionInitialize(isolate, weak_collection);
1662 }
1663 
1664 
1665 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionGet) {
1666  HandleScope scope(isolate);
1667  ASSERT(args.length() == 2);
1668  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1671  ObjectHashTable::cast(weak_collection->table()));
1672  Handle<Object> lookup(table->Lookup(*key), isolate);
1673  return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
1674 }
1675 
1676 
1677 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionHas) {
1678  HandleScope scope(isolate);
1679  ASSERT(args.length() == 2);
1680  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1683  ObjectHashTable::cast(weak_collection->table()));
1684  Handle<Object> lookup(table->Lookup(*key), isolate);
1685  return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1686 }
1687 
1688 
1689 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionDelete) {
1690  HandleScope scope(isolate);
1691  ASSERT(args.length() == 2);
1692  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1695  weak_collection->table()));
1696  Handle<Object> lookup(table->Lookup(*key), isolate);
1697  Handle<ObjectHashTable> new_table =
1698  ObjectHashTable::Put(table, key, isolate->factory()->the_hole_value());
1699  weak_collection->set_table(*new_table);
1700  return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1701 }
1702 
1703 
1704 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionSet) {
1705  HandleScope scope(isolate);
1706  ASSERT(args.length() == 3);
1707  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1709  Handle<Object> value(args[2], isolate);
1711  ObjectHashTable::cast(weak_collection->table()));
1712  Handle<ObjectHashTable> new_table = ObjectHashTable::Put(table, key, value);
1713  weak_collection->set_table(*new_table);
1714  return isolate->heap()->undefined_value();
1715 }
1716 
1717 
1718 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) {
1719  SealHandleScope shs(isolate);
1720  ASSERT(args.length() == 1);
1721  Object* obj = args[0];
1722  if (!obj->IsJSObject()) return isolate->heap()->null_value();
1723  return JSObject::cast(obj)->class_name();
1724 }
1725 
1726 
1727 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) {
1728  HandleScope scope(isolate);
1729  ASSERT(args.length() == 1);
1731  // We don't expect access checks to be needed on JSProxy objects.
1732  ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
1733  do {
1734  if (obj->IsAccessCheckNeeded() &&
1735  !isolate->MayNamedAccessWrapper(Handle<JSObject>::cast(obj),
1736  isolate->factory()->proto_string(),
1737  v8::ACCESS_GET)) {
1738  isolate->ReportFailedAccessCheckWrapper(Handle<JSObject>::cast(obj),
1739  v8::ACCESS_GET);
1741  return isolate->heap()->undefined_value();
1742  }
1743  obj = handle(obj->GetPrototype(isolate), isolate);
1744  } while (obj->IsJSObject() &&
1745  JSObject::cast(*obj)->map()->is_hidden_prototype());
1746  return *obj;
1747 }
1748 
1749 
1750 static inline Object* GetPrototypeSkipHiddenPrototypes(Isolate* isolate,
1751  Object* receiver) {
1752  Object* current = receiver->GetPrototype(isolate);
1753  while (current->IsJSObject() &&
1754  JSObject::cast(current)->map()->is_hidden_prototype()) {
1755  current = current->GetPrototype(isolate);
1756  }
1757  return current;
1758 }
1759 
1760 
1761 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetPrototype) {
1762  HandleScope scope(isolate);
1763  ASSERT(args.length() == 2);
1765  CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
1766  if (obj->IsAccessCheckNeeded() &&
1767  !isolate->MayNamedAccessWrapper(obj,
1768  isolate->factory()->proto_string(),
1769  v8::ACCESS_SET)) {
1770  isolate->ReportFailedAccessCheckWrapper(obj, v8::ACCESS_SET);
1772  return isolate->heap()->undefined_value();
1773  }
1774  if (obj->map()->is_observed()) {
1775  Handle<Object> old_value(
1776  GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate);
1777 
1778  Handle<Object> result = JSObject::SetPrototype(obj, prototype, true);
1779  RETURN_IF_EMPTY_HANDLE(isolate, result);
1780 
1781  Handle<Object> new_value(
1782  GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate);
1783  if (!new_value->SameValue(*old_value)) {
1784  JSObject::EnqueueChangeRecord(obj, "setPrototype",
1785  isolate->factory()->proto_string(),
1786  old_value);
1787  }
1788  return *result;
1789  }
1790  Handle<Object> result = JSObject::SetPrototype(obj, prototype, true);
1791  RETURN_IF_EMPTY_HANDLE(isolate, result);
1792  return *result;
1793 }
1794 
1795 
1796 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) {
1797  SealHandleScope shs(isolate);
1798  ASSERT(args.length() == 2);
1799  // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
1800  Object* O = args[0];
1801  Object* V = args[1];
1802  while (true) {
1803  Object* prototype = V->GetPrototype(isolate);
1804  if (prototype->IsNull()) return isolate->heap()->false_value();
1805  if (O == prototype) return isolate->heap()->true_value();
1806  V = prototype;
1807  }
1808 }
1809 
1810 
1811 static bool CheckAccessException(Object* callback,
1812  v8::AccessType access_type) {
1813  DisallowHeapAllocation no_gc;
1814  if (callback->IsAccessorInfo()) {
1815  AccessorInfo* info = AccessorInfo::cast(callback);
1816  return
1817  (access_type == v8::ACCESS_HAS &&
1818  (info->all_can_read() || info->all_can_write())) ||
1819  (access_type == v8::ACCESS_GET && info->all_can_read()) ||
1820  (access_type == v8::ACCESS_SET && info->all_can_write());
1821  }
1822  if (callback->IsAccessorPair()) {
1823  AccessorPair* info = AccessorPair::cast(callback);
1824  return
1825  (access_type == v8::ACCESS_HAS &&
1826  (info->all_can_read() || info->all_can_write())) ||
1827  (access_type == v8::ACCESS_GET && info->all_can_read()) ||
1828  (access_type == v8::ACCESS_SET && info->all_can_write());
1829  }
1830  return false;
1831 }
1832 
1833 
1834 template<class Key>
1835 static bool CheckGenericAccess(
1836  Handle<JSObject> receiver,
1837  Handle<JSObject> holder,
1838  Key key,
1839  v8::AccessType access_type,
1840  bool (Isolate::*mayAccess)(Handle<JSObject>, Key, v8::AccessType)) {
1841  Isolate* isolate = receiver->GetIsolate();
1842  for (Handle<JSObject> current = receiver;
1843  true;
1844  current = handle(JSObject::cast(current->GetPrototype()), isolate)) {
1845  if (current->IsAccessCheckNeeded() &&
1846  !(isolate->*mayAccess)(current, key, access_type)) {
1847  return false;
1848  }
1849  if (current.is_identical_to(holder)) break;
1850  }
1851  return true;
1852 }
1853 
1854 
1859 };
1860 
1861 
1862 static AccessCheckResult CheckPropertyAccess(Handle<JSObject> obj,
1863  Handle<Name> name,
1864  v8::AccessType access_type) {
1865  uint32_t index;
1866  if (name->AsArrayIndex(&index)) {
1867  // TODO(1095): we should traverse hidden prototype hierachy as well.
1868  if (CheckGenericAccess(
1869  obj, obj, index, access_type, &Isolate::MayIndexedAccessWrapper)) {
1870  return ACCESS_ALLOWED;
1871  }
1872 
1873  obj->GetIsolate()->ReportFailedAccessCheckWrapper(obj, access_type);
1874  return ACCESS_FORBIDDEN;
1875  }
1876 
1877  Isolate* isolate = obj->GetIsolate();
1878  LookupResult lookup(isolate);
1879  obj->LocalLookup(*name, &lookup, true);
1880 
1881  if (!lookup.IsProperty()) return ACCESS_ABSENT;
1882  Handle<JSObject> holder(lookup.holder(), isolate);
1883  if (CheckGenericAccess<Handle<Object> >(
1884  obj, holder, name, access_type, &Isolate::MayNamedAccessWrapper)) {
1885  return ACCESS_ALLOWED;
1886  }
1887 
1888  // Access check callback denied the access, but some properties
1889  // can have a special permissions which override callbacks descision
1890  // (currently see v8::AccessControl).
1891  // API callbacks can have per callback access exceptions.
1892  switch (lookup.type()) {
1893  case CALLBACKS:
1894  if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
1895  return ACCESS_ALLOWED;
1896  }
1897  break;
1898  case INTERCEPTOR:
1899  // If the object has an interceptor, try real named properties.
1900  // Overwrite the result to fetch the correct property later.
1901  holder->LookupRealNamedProperty(*name, &lookup);
1902  if (lookup.IsProperty() && lookup.IsPropertyCallbacks()) {
1903  if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
1904  return ACCESS_ALLOWED;
1905  }
1906  }
1907  break;
1908  default:
1909  break;
1910  }
1911 
1912  isolate->ReportFailedAccessCheckWrapper(obj, access_type);
1913  return ACCESS_FORBIDDEN;
1914 }
1915 
1916 
1917 // Enumerator used as indices into the array returned from GetOwnProperty
1927 };
1928 
1929 
1930 static Handle<Object> GetOwnProperty(Isolate* isolate,
1931  Handle<JSObject> obj,
1932  Handle<Name> name) {
1933  Heap* heap = isolate->heap();
1934  Factory* factory = isolate->factory();
1935  // Due to some WebKit tests, we want to make sure that we do not log
1936  // more than one access failure here.
1937  AccessCheckResult access_check_result =
1938  CheckPropertyAccess(obj, name, v8::ACCESS_HAS);
1940  switch (access_check_result) {
1941  case ACCESS_FORBIDDEN: return factory->false_value();
1942  case ACCESS_ALLOWED: break;
1943  case ACCESS_ABSENT: return factory->undefined_value();
1944  }
1945 
1947  if (attrs == ABSENT) {
1949  return factory->undefined_value();
1950  }
1951  ASSERT(!isolate->has_scheduled_exception());
1952  AccessorPair* raw_accessors = obj->GetLocalPropertyAccessorPair(*name);
1953  Handle<AccessorPair> accessors(raw_accessors, isolate);
1954  Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
1955  elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
1956  elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
1957  elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(raw_accessors != NULL));
1958 
1959  if (raw_accessors == NULL) {
1960  elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
1961  // GetProperty does access check.
1962  Handle<Object> value = GetProperty(isolate, obj, name);
1963  RETURN_IF_EMPTY_HANDLE_VALUE(isolate, value, Handle<Object>::null());
1964  elms->set(VALUE_INDEX, *value);
1965  } else {
1966  // Access checks are performed for both accessors separately.
1967  // When they fail, the respective field is not set in the descriptor.
1968  Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate);
1969  Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate);
1970 
1971  if (!getter->IsMap() && CheckPropertyAccess(obj, name, v8::ACCESS_GET)) {
1972  ASSERT(!isolate->has_scheduled_exception());
1973  elms->set(GETTER_INDEX, *getter);
1974  } else {
1976  }
1977 
1978  if (!setter->IsMap() && CheckPropertyAccess(obj, name, v8::ACCESS_SET)) {
1979  ASSERT(!isolate->has_scheduled_exception());
1980  elms->set(SETTER_INDEX, *setter);
1981  } else {
1983  }
1984  }
1985 
1986  return isolate->factory()->NewJSArrayWithElements(elms);
1987 }
1988 
1989 
1990 // Returns an array with the property description:
1991 // if args[1] is not a property on args[0]
1992 // returns undefined
1993 // if args[1] is a data property on args[0]
1994 // [false, value, Writeable, Enumerable, Configurable]
1995 // if args[1] is an accessor on args[0]
1996 // [true, GetFunction, SetFunction, Enumerable, Configurable]
1997 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) {
1998  HandleScope scope(isolate);
1999  ASSERT(args.length() == 2);
2001  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
2002  Handle<Object> result = GetOwnProperty(isolate, obj, name);
2003  RETURN_IF_EMPTY_HANDLE(isolate, result);
2004  return *result;
2005 }
2006 
2007 
2008 RUNTIME_FUNCTION(MaybeObject*, Runtime_PreventExtensions) {
2009  HandleScope scope(isolate);
2010  ASSERT(args.length() == 1);
2013  RETURN_IF_EMPTY_HANDLE(isolate, result);
2014  return *result;
2015 }
2016 
2017 
2018 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsExtensible) {
2019  SealHandleScope shs(isolate);
2020  ASSERT(args.length() == 1);
2021  CONVERT_ARG_CHECKED(JSObject, obj, 0);
2022  if (obj->IsJSGlobalProxy()) {
2023  Object* proto = obj->GetPrototype();
2024  if (proto->IsNull()) return isolate->heap()->false_value();
2025  ASSERT(proto->IsJSGlobalObject());
2026  obj = JSObject::cast(proto);
2027  }
2028  return isolate->heap()->ToBoolean(obj->map()->is_extensible());
2029 }
2030 
2031 
2032 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpCompile) {
2033  HandleScope scope(isolate);
2034  ASSERT(args.length() == 3);
2036  CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
2038  Handle<Object> result = RegExpImpl::Compile(re, pattern, flags);
2039  RETURN_IF_EMPTY_HANDLE(isolate, result);
2040  return *result;
2041 }
2042 
2043 
2044 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateApiFunction) {
2045  HandleScope scope(isolate);
2046  ASSERT(args.length() == 1);
2048  return *isolate->factory()->CreateApiFunction(data);
2049 }
2050 
2051 
2052 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsTemplate) {
2053  SealHandleScope shs(isolate);
2054  ASSERT(args.length() == 1);
2055  Object* arg = args[0];
2056  bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
2057  return isolate->heap()->ToBoolean(result);
2058 }
2059 
2060 
2061 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetTemplateField) {
2062  SealHandleScope shs(isolate);
2063  ASSERT(args.length() == 2);
2064  CONVERT_ARG_CHECKED(HeapObject, templ, 0);
2065  CONVERT_SMI_ARG_CHECKED(index, 1)
2066  int offset = index * kPointerSize + HeapObject::kHeaderSize;
2067  InstanceType type = templ->map()->instance_type();
2069  type == OBJECT_TEMPLATE_INFO_TYPE);
2070  RUNTIME_ASSERT(offset > 0);
2071  if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
2073  } else {
2075  }
2076  return *HeapObject::RawField(templ, offset);
2077 }
2078 
2079 
2080 RUNTIME_FUNCTION(MaybeObject*, Runtime_DisableAccessChecks) {
2081  SealHandleScope shs(isolate);
2082  ASSERT(args.length() == 1);
2083  CONVERT_ARG_CHECKED(HeapObject, object, 0);
2084  Map* old_map = object->map();
2085  bool needs_access_checks = old_map->is_access_check_needed();
2086  if (needs_access_checks) {
2087  // Copy map so it won't interfere constructor's initial map.
2088  Map* new_map;
2089  MaybeObject* maybe_new_map = old_map->Copy();
2090  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
2091 
2092  new_map->set_is_access_check_needed(false);
2093  object->set_map(new_map);
2094  }
2095  return isolate->heap()->ToBoolean(needs_access_checks);
2096 }
2097 
2098 
2099 RUNTIME_FUNCTION(MaybeObject*, Runtime_EnableAccessChecks) {
2100  SealHandleScope shs(isolate);
2101  ASSERT(args.length() == 1);
2102  CONVERT_ARG_CHECKED(HeapObject, object, 0);
2103  Map* old_map = object->map();
2104  if (!old_map->is_access_check_needed()) {
2105  // Copy map so it won't interfere constructor's initial map.
2106  Map* new_map;
2107  MaybeObject* maybe_new_map = old_map->Copy();
2108  if (!maybe_new_map->To(&new_map)) return maybe_new_map;
2109 
2110  new_map->set_is_access_check_needed(true);
2111  object->set_map(new_map);
2112  }
2113  return isolate->heap()->undefined_value();
2114 }
2115 
2116 
2117 // Transform getter or setter into something DefineAccessor can handle.
2118 static Handle<Object> InstantiateAccessorComponent(Isolate* isolate,
2119  Handle<Object> component) {
2120  if (component->IsUndefined()) return isolate->factory()->null_value();
2123  return Utils::OpenHandle(*Utils::ToLocal(info)->GetFunction());
2124 }
2125 
2126 
2127 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAccessorProperty) {
2128  HandleScope scope(isolate);
2129  ASSERT(args.length() == 6);
2131  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
2132  CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
2133  CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
2134  CONVERT_SMI_ARG_CHECKED(attribute, 4);
2135  CONVERT_SMI_ARG_CHECKED(access_control, 5);
2136  RUNTIME_ASSERT(getter->IsUndefined() || getter->IsFunctionTemplateInfo());
2137  RUNTIME_ASSERT(setter->IsUndefined() || setter->IsFunctionTemplateInfo());
2138  JSObject::DefineAccessor(object,
2139  name,
2140  InstantiateAccessorComponent(isolate, getter),
2141  InstantiateAccessorComponent(isolate, setter),
2142  static_cast<PropertyAttributes>(attribute),
2143  static_cast<v8::AccessControl>(access_control));
2144  return isolate->heap()->undefined_value();
2145 }
2146 
2147 
2148 static Failure* ThrowRedeclarationError(Isolate* isolate,
2149  const char* type,
2150  Handle<String> name) {
2151  HandleScope scope(isolate);
2152  Handle<Object> type_handle =
2153  isolate->factory()->NewStringFromAscii(CStrVector(type));
2154  Handle<Object> args[2] = { type_handle, name };
2155  Handle<Object> error =
2156  isolate->factory()->NewTypeError("redeclaration", HandleVector(args, 2));
2157  return isolate->Throw(*error);
2158 }
2159 
2160 
2161 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_DeclareGlobals) {
2162  HandleScope scope(isolate);
2163  ASSERT(args.length() == 3);
2165  isolate->context()->global_object());
2166 
2167  Handle<Context> context = args.at<Context>(0);
2169  CONVERT_SMI_ARG_CHECKED(flags, 2);
2170 
2171  // Traverse the name/value pairs and set the properties.
2172  int length = pairs->length();
2173  for (int i = 0; i < length; i += 2) {
2174  HandleScope scope(isolate);
2176  Handle<Object> value(pairs->get(i + 1), isolate);
2177 
2178  // We have to declare a global const property. To capture we only
2179  // assign to it when evaluating the assignment for "const x =
2180  // <expr>" the initial value is the hole.
2181  bool is_var = value->IsUndefined();
2182  bool is_const = value->IsTheHole();
2183  bool is_function = value->IsSharedFunctionInfo();
2184  ASSERT(is_var + is_const + is_function == 1);
2185 
2186  if (is_var || is_const) {
2187  // Lookup the property in the global object, and don't set the
2188  // value of the variable if the property is already there.
2189  // Do the lookup locally only, see ES5 erratum.
2190  LookupResult lookup(isolate);
2191  global->LocalLookup(*name, &lookup, true);
2192  if (lookup.IsFound()) {
2193  // We found an existing property. Unless it was an interceptor
2194  // that claims the property is absent, skip this declaration.
2195  if (!lookup.IsInterceptor()) continue;
2196  if (JSReceiver::GetPropertyAttribute(global, name) != ABSENT) continue;
2197  // Fall-through and introduce the absent property by using
2198  // SetProperty.
2199  }
2200  } else if (is_function) {
2201  // Copy the function and update its context. Use it as value.
2204  Handle<JSFunction> function =
2205  isolate->factory()->NewFunctionFromSharedFunctionInfo(
2206  shared, context, TENURED);
2207  value = function;
2208  }
2209 
2210  LookupResult lookup(isolate);
2211  global->LocalLookup(*name, &lookup, true);
2212 
2213  // Compute the property attributes. According to ECMA-262,
2214  // the property must be non-configurable except in eval.
2215  int attr = NONE;
2216  bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
2217  if (!is_eval) {
2218  attr |= DONT_DELETE;
2219  }
2220  bool is_native = DeclareGlobalsNativeFlag::decode(flags);
2221  if (is_const || (is_native && is_function)) {
2222  attr |= READ_ONLY;
2223  }
2224 
2225  StrictMode strict_mode = DeclareGlobalsStrictMode::decode(flags);
2226 
2227  if (!lookup.IsFound() || is_function) {
2228  // If the local property exists, check that we can reconfigure it
2229  // as required for function declarations.
2230  if (lookup.IsFound() && lookup.IsDontDelete()) {
2231  if (lookup.IsReadOnly() || lookup.IsDontEnum() ||
2232  lookup.IsPropertyCallbacks()) {
2233  return ThrowRedeclarationError(isolate, "function", name);
2234  }
2235  // If the existing property is not configurable, keep its attributes.
2236  attr = lookup.GetAttributes();
2237  }
2238  // Define or redefine own property.
2239  RETURN_IF_EMPTY_HANDLE(isolate,
2241  global, name, value, static_cast<PropertyAttributes>(attr)));
2242  } else {
2243  // Do a [[Put]] on the existing (own) property.
2244  RETURN_IF_EMPTY_HANDLE(isolate,
2246  global, name, value, static_cast<PropertyAttributes>(attr),
2247  strict_mode));
2248  }
2249  }
2250 
2251  ASSERT(!isolate->has_pending_exception());
2252  return isolate->heap()->undefined_value();
2253 }
2254 
2255 
2256 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_DeclareContextSlot) {
2257  HandleScope scope(isolate);
2258  ASSERT(args.length() == 4);
2259 
2260  // Declarations are always made in a function or native context. In the
2261  // case of eval code, the context passed is the context of the caller,
2262  // which may be some nested context and not the declaration context.
2263  RUNTIME_ASSERT(args[0]->IsContext());
2264  Handle<Context> context(Context::cast(args[0])->declaration_context());
2265 
2266  Handle<String> name(String::cast(args[1]));
2267  PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2));
2268  RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE);
2269  Handle<Object> initial_value(args[3], isolate);
2270 
2271  int index;
2272  PropertyAttributes attributes;
2274  BindingFlags binding_flags;
2275  Handle<Object> holder =
2276  context->Lookup(name, flags, &index, &attributes, &binding_flags);
2277 
2278  if (attributes != ABSENT) {
2279  // The name was declared before; check for conflicting re-declarations.
2280  // Note: this is actually inconsistent with what happens for globals (where
2281  // we silently ignore such declarations).
2282  if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
2283  // Functions are not read-only.
2284  ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
2285  const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
2286  return ThrowRedeclarationError(isolate, type, name);
2287  }
2288 
2289  // Initialize it if necessary.
2290  if (*initial_value != NULL) {
2291  if (index >= 0) {
2292  ASSERT(holder.is_identical_to(context));
2293  if (((attributes & READ_ONLY) == 0) ||
2294  context->get(index)->IsTheHole()) {
2295  context->set(index, *initial_value);
2296  }
2297  } else {
2298  // Slow case: The property is in the context extension object of a
2299  // function context or the global object of a native context.
2300  Handle<JSObject> object = Handle<JSObject>::cast(holder);
2302  isolate,
2303  JSReceiver::SetProperty(object, name, initial_value, mode, SLOPPY));
2304  }
2305  }
2306 
2307  } else {
2308  // The property is not in the function context. It needs to be
2309  // "declared" in the function context's extension context or as a
2310  // property of the the global object.
2311  Handle<JSObject> object;
2312  if (context->has_extension()) {
2313  object = Handle<JSObject>(JSObject::cast(context->extension()));
2314  } else {
2315  // Context extension objects are allocated lazily.
2316  ASSERT(context->IsFunctionContext());
2317  object = isolate->factory()->NewJSObject(
2318  isolate->context_extension_function());
2319  context->set_extension(*object);
2320  }
2321  ASSERT(*object != NULL);
2322 
2323  // Declare the property by setting it to the initial value if provided,
2324  // or undefined, and use the correct mode (e.g. READ_ONLY attribute for
2325  // constant declarations).
2326  ASSERT(!JSReceiver::HasLocalProperty(object, name));
2327  Handle<Object> value(isolate->heap()->undefined_value(), isolate);
2328  if (*initial_value != NULL) value = initial_value;
2329  // Declaring a const context slot is a conflicting declaration if
2330  // there is a callback with that name in a prototype. It is
2331  // allowed to introduce const variables in
2332  // JSContextExtensionObjects. They are treated specially in
2333  // SetProperty and no setters are invoked for those since they are
2334  // not real JSObjects.
2335  if (initial_value->IsTheHole() &&
2336  !object->IsJSContextExtensionObject()) {
2337  LookupResult lookup(isolate);
2338  object->Lookup(*name, &lookup);
2339  if (lookup.IsPropertyCallbacks()) {
2340  return ThrowRedeclarationError(isolate, "const", name);
2341  }
2342  }
2343  if (object->IsJSGlobalObject()) {
2344  // Define own property on the global object.
2345  RETURN_IF_EMPTY_HANDLE(isolate,
2346  JSObject::SetLocalPropertyIgnoreAttributes(object, name, value, mode));
2347  } else {
2348  RETURN_IF_EMPTY_HANDLE(isolate,
2349  JSReceiver::SetProperty(object, name, value, mode, SLOPPY));
2350  }
2351  }
2352 
2353  return isolate->heap()->undefined_value();
2354 }
2355 
2356 
2357 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
2358  HandleScope scope(isolate);
2359  // args[0] == name
2360  // args[1] == language_mode
2361  // args[2] == value (optional)
2362 
2363  // Determine if we need to assign to the variable if it already
2364  // exists (based on the number of arguments).
2365  RUNTIME_ASSERT(args.length() == 2 || args.length() == 3);
2366  bool assign = args.length() == 3;
2367 
2369  RUNTIME_ASSERT(args[1]->IsSmi());
2370  CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 1);
2371 
2372  // According to ECMA-262, section 12.2, page 62, the property must
2373  // not be deletable.
2374  PropertyAttributes attributes = DONT_DELETE;
2375 
2376  // Lookup the property locally in the global object. If it isn't
2377  // there, there is a property with this name in the prototype chain.
2378  // We follow Safari and Firefox behavior and only set the property
2379  // locally if there is an explicit initialization value that we have
2380  // to assign to the property.
2381  // Note that objects can have hidden prototypes, so we need to traverse
2382  // the whole chain of hidden prototypes to do a 'local' lookup.
2383  LookupResult lookup(isolate);
2384  isolate->context()->global_object()->LocalLookup(*name, &lookup, true);
2385  if (lookup.IsInterceptor()) {
2386  Handle<JSObject> holder(lookup.holder());
2387  PropertyAttributes intercepted =
2388  JSReceiver::GetPropertyAttribute(holder, name);
2389  if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
2390  // Found an interceptor that's not read only.
2391  if (assign) {
2394  holder, &lookup, name, value, attributes, strict_mode);
2395  RETURN_IF_EMPTY_HANDLE(isolate, result);
2396  return *result;
2397  } else {
2398  return isolate->heap()->undefined_value();
2399  }
2400  }
2401  }
2402 
2403  if (assign) {
2405  Handle<GlobalObject> global(isolate->context()->global_object());
2407  global, name, value, attributes, strict_mode);
2408  RETURN_IF_EMPTY_HANDLE(isolate, result);
2409  return *result;
2410  }
2411  return isolate->heap()->undefined_value();
2412 }
2413 
2414 
2415 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_InitializeConstGlobal) {
2416  SealHandleScope shs(isolate);
2417  // All constants are declared with an initial value. The name
2418  // of the constant is the first argument and the initial value
2419  // is the second.
2420  RUNTIME_ASSERT(args.length() == 2);
2422  Handle<Object> value = args.at<Object>(1);
2423 
2424  // Get the current global object from top.
2425  GlobalObject* global = isolate->context()->global_object();
2426 
2427  // According to ECMA-262, section 12.2, page 62, the property must
2428  // not be deletable. Since it's a const, it must be READ_ONLY too.
2429  PropertyAttributes attributes =
2430  static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
2431 
2432  // Lookup the property locally in the global object. If it isn't
2433  // there, we add the property and take special precautions to always
2434  // add it as a local property even in case of callbacks in the
2435  // prototype chain (this rules out using SetProperty).
2436  // We use SetLocalPropertyIgnoreAttributes instead
2437  LookupResult lookup(isolate);
2438  global->LocalLookup(*name, &lookup);
2439  if (!lookup.IsFound()) {
2440  HandleScope handle_scope(isolate);
2441  Handle<GlobalObject> global(isolate->context()->global_object());
2443  isolate,
2444  JSObject::SetLocalPropertyIgnoreAttributes(global, name, value,
2445  attributes));
2446  return *value;
2447  }
2448 
2449  if (!lookup.IsReadOnly()) {
2450  // Restore global object from context (in case of GC) and continue
2451  // with setting the value.
2452  HandleScope handle_scope(isolate);
2453  Handle<GlobalObject> global(isolate->context()->global_object());
2454 
2455  // BUG 1213575: Handle the case where we have to set a read-only
2456  // property through an interceptor and only do it if it's
2457  // uninitialized, e.g. the hole. Nirk...
2458  // Passing sloppy mode because the property is writable.
2460  isolate,
2461  JSReceiver::SetProperty(global, name, value, attributes, SLOPPY));
2462  return *value;
2463  }
2464 
2465  // Set the value, but only if we're assigning the initial value to a
2466  // constant. For now, we determine this by checking if the
2467  // current value is the hole.
2468  // Strict mode handling not needed (const is disallowed in strict mode).
2469  if (lookup.IsField()) {
2470  FixedArray* properties = global->properties();
2471  int index = lookup.GetFieldIndex().field_index();
2472  if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) {
2473  properties->set(index, *value);
2474  }
2475  } else if (lookup.IsNormal()) {
2476  if (global->GetNormalizedProperty(&lookup)->IsTheHole() ||
2477  !lookup.IsReadOnly()) {
2478  HandleScope scope(isolate);
2479  JSObject::SetNormalizedProperty(Handle<JSObject>(global), &lookup, value);
2480  }
2481  } else {
2482  // Ignore re-initialization of constants that have already been
2483  // assigned a constant value.
2484  ASSERT(lookup.IsReadOnly() && lookup.IsConstant());
2485  }
2486 
2487  // Use the set value as the result of the operation.
2488  return *value;
2489 }
2490 
2491 
2492 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_InitializeConstContextSlot) {
2493  HandleScope scope(isolate);
2494  ASSERT(args.length() == 3);
2495 
2496  Handle<Object> value(args[0], isolate);
2497  ASSERT(!value->IsTheHole());
2498 
2499  // Initializations are always done in a function or native context.
2500  RUNTIME_ASSERT(args[1]->IsContext());
2501  Handle<Context> context(Context::cast(args[1])->declaration_context());
2502 
2503  Handle<String> name(String::cast(args[2]));
2504 
2505  int index;
2506  PropertyAttributes attributes;
2508  BindingFlags binding_flags;
2509  Handle<Object> holder =
2510  context->Lookup(name, flags, &index, &attributes, &binding_flags);
2511 
2512  if (index >= 0) {
2513  ASSERT(holder->IsContext());
2514  // Property was found in a context. Perform the assignment if we
2515  // found some non-constant or an uninitialized constant.
2516  Handle<Context> context = Handle<Context>::cast(holder);
2517  if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) {
2518  context->set(index, *value);
2519  }
2520  return *value;
2521  }
2522 
2523  // The property could not be found, we introduce it as a property of the
2524  // global object.
2525  if (attributes == ABSENT) {
2527  isolate->context()->global_object());
2528  // Strict mode not needed (const disallowed in strict mode).
2530  isolate,
2531  JSReceiver::SetProperty(global, name, value, NONE, SLOPPY));
2532  return *value;
2533  }
2534 
2535  // The property was present in some function's context extension object,
2536  // as a property on the subject of a with, or as a property of the global
2537  // object.
2538  //
2539  // In most situations, eval-introduced consts should still be present in
2540  // the context extension object. However, because declaration and
2541  // initialization are separate, the property might have been deleted
2542  // before we reach the initialization point.
2543  //
2544  // Example:
2545  //
2546  // function f() { eval("delete x; const x;"); }
2547  //
2548  // In that case, the initialization behaves like a normal assignment.
2549  Handle<JSObject> object = Handle<JSObject>::cast(holder);
2550 
2551  if (*object == context->extension()) {
2552  // This is the property that was introduced by the const declaration.
2553  // Set it if it hasn't been set before. NOTE: We cannot use
2554  // GetProperty() to get the current value as it 'unholes' the value.
2555  LookupResult lookup(isolate);
2556  object->LocalLookupRealNamedProperty(*name, &lookup);
2557  ASSERT(lookup.IsFound()); // the property was declared
2558  ASSERT(lookup.IsReadOnly()); // and it was declared as read-only
2559 
2560  if (lookup.IsField()) {
2561  FixedArray* properties = object->properties();
2562  int index = lookup.GetFieldIndex().field_index();
2563  if (properties->get(index)->IsTheHole()) {
2564  properties->set(index, *value);
2565  }
2566  } else if (lookup.IsNormal()) {
2567  if (object->GetNormalizedProperty(&lookup)->IsTheHole()) {
2568  JSObject::SetNormalizedProperty(object, &lookup, value);
2569  }
2570  } else {
2571  // We should not reach here. Any real, named property should be
2572  // either a field or a dictionary slot.
2573  UNREACHABLE();
2574  }
2575  } else {
2576  // The property was found on some other object. Set it if it is not a
2577  // read-only property.
2578  if ((attributes & READ_ONLY) == 0) {
2579  // Strict mode not needed (const disallowed in strict mode).
2581  isolate,
2582  JSReceiver::SetProperty(object, name, value, attributes, SLOPPY));
2583  }
2584  }
2585 
2586  return *value;
2587 }
2588 
2589 
2590 RUNTIME_FUNCTION(MaybeObject*,
2591  Runtime_OptimizeObjectForAddingMultipleProperties) {
2592  HandleScope scope(isolate);
2593  ASSERT(args.length() == 2);
2595  CONVERT_SMI_ARG_CHECKED(properties, 1);
2596  if (object->HasFastProperties() && !object->IsJSGlobalProxy()) {
2598  }
2599  return *object;
2600 }
2601 
2602 
2603 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_RegExpExec) {
2604  HandleScope scope(isolate);
2605  ASSERT(args.length() == 4);
2607  CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
2608  // Due to the way the JS calls are constructed this must be less than the
2609  // length of a string, i.e. it is always a Smi. We check anyway for security.
2610  CONVERT_SMI_ARG_CHECKED(index, 2);
2611  CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
2612  RUNTIME_ASSERT(index >= 0);
2613  RUNTIME_ASSERT(index <= subject->length());
2614  isolate->counters()->regexp_entry_runtime()->Increment();
2615  Handle<Object> result = RegExpImpl::Exec(regexp,
2616  subject,
2617  index,
2618  last_match_info);
2619  RETURN_IF_EMPTY_HANDLE(isolate, result);
2620  return *result;
2621 }
2622 
2623 
2624 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_RegExpConstructResult) {
2625  SealHandleScope shs(isolate);
2626  ASSERT(args.length() == 3);
2627  CONVERT_SMI_ARG_CHECKED(elements_count, 0);
2628  if (elements_count < 0 ||
2629  elements_count > FixedArray::kMaxLength ||
2630  !Smi::IsValid(elements_count)) {
2631  return isolate->ThrowIllegalOperation();
2632  }
2633  Object* new_object;
2634  { MaybeObject* maybe_new_object =
2635  isolate->heap()->AllocateFixedArray(elements_count);
2636  if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
2637  }
2638  FixedArray* elements = FixedArray::cast(new_object);
2639  { MaybeObject* maybe_new_object = isolate->heap()->AllocateRaw(
2641  if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
2642  }
2643  {
2644  DisallowHeapAllocation no_gc;
2645  HandleScope scope(isolate);
2646  reinterpret_cast<HeapObject*>(new_object)->
2647  set_map(isolate->native_context()->regexp_result_map());
2648  }
2649  JSArray* array = JSArray::cast(new_object);
2650  array->set_properties(isolate->heap()->empty_fixed_array());
2651  array->set_elements(elements);
2652  array->set_length(Smi::FromInt(elements_count));
2653  // Write in-object properties after the length of the array.
2656  return array;
2657 }
2658 
2659 
2660 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) {
2661  HandleScope scope(isolate);
2662  ASSERT(args.length() == 5);
2664  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
2665  // If source is the empty string we set it to "(?:)" instead as
2666  // suggested by ECMA-262, 5th, section 15.10.4.1.
2667  if (source->length() == 0) source = isolate->factory()->query_colon_string();
2668 
2669  CONVERT_ARG_HANDLE_CHECKED(Object, global, 2);
2670  if (!global->IsTrue()) global = isolate->factory()->false_value();
2671 
2672  CONVERT_ARG_HANDLE_CHECKED(Object, ignoreCase, 3);
2673  if (!ignoreCase->IsTrue()) ignoreCase = isolate->factory()->false_value();
2674 
2675  CONVERT_ARG_HANDLE_CHECKED(Object, multiline, 4);
2676  if (!multiline->IsTrue()) multiline = isolate->factory()->false_value();
2677 
2678  Map* map = regexp->map();
2679  Object* constructor = map->constructor();
2680  if (constructor->IsJSFunction() &&
2681  JSFunction::cast(constructor)->initial_map() == map) {
2682  // If we still have the original map, set in-object properties directly.
2683  regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, *source);
2684  // Both true and false are immovable immortal objects so no need for write
2685  // barrier.
2686  regexp->InObjectPropertyAtPut(
2688  regexp->InObjectPropertyAtPut(
2690  regexp->InObjectPropertyAtPut(
2692  regexp->InObjectPropertyAtPut(
2694  return *regexp;
2695  }
2696 
2697  // Map has changed, so use generic, but slower, method.
2698  PropertyAttributes final =
2699  static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE);
2700  PropertyAttributes writable =
2701  static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
2702  Handle<Object> zero(Smi::FromInt(0), isolate);
2703  Factory* factory = isolate->factory();
2705  regexp, factory->source_string(), source, final));
2707  regexp, factory->global_string(), global, final));
2709  regexp, factory->ignore_case_string(), ignoreCase, final));
2711  regexp, factory->multiline_string(), multiline, final));
2713  regexp, factory->last_index_string(), zero, writable));
2714  return *regexp;
2715 }
2716 
2717 
2718 RUNTIME_FUNCTION(MaybeObject*, Runtime_FinishArrayPrototypeSetup) {
2719  HandleScope scope(isolate);
2720  ASSERT(args.length() == 1);
2721  CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0);
2722  // This is necessary to enable fast checks for absence of elements
2723  // on Array.prototype and below.
2724  prototype->set_elements(isolate->heap()->empty_fixed_array());
2725  return Smi::FromInt(0);
2726 }
2727 
2728 
2729 static Handle<JSFunction> InstallBuiltin(Isolate* isolate,
2730  Handle<JSObject> holder,
2731  const char* name,
2732  Builtins::Name builtin_name) {
2733  Handle<String> key = isolate->factory()->InternalizeUtf8String(name);
2734  Handle<Code> code(isolate->builtins()->builtin(builtin_name));
2735  Handle<JSFunction> optimized =
2736  isolate->factory()->NewFunction(key,
2739  code,
2740  false);
2741  optimized->shared()->DontAdaptArguments();
2742  JSReceiver::SetProperty(holder, key, optimized, NONE, STRICT);
2743  return optimized;
2744 }
2745 
2746 
2747 RUNTIME_FUNCTION(MaybeObject*, Runtime_SpecialArrayFunctions) {
2748  HandleScope scope(isolate);
2749  ASSERT(args.length() == 1);
2751 
2752  InstallBuiltin(isolate, holder, "pop", Builtins::kArrayPop);
2753  InstallBuiltin(isolate, holder, "push", Builtins::kArrayPush);
2754  InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift);
2755  InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift);
2756  InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice);
2757  InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
2758  InstallBuiltin(isolate, holder, "concat", Builtins::kArrayConcat);
2759 
2760  return *holder;
2761 }
2762 
2763 
2764 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsSloppyModeFunction) {
2765  SealHandleScope shs(isolate);
2766  ASSERT(args.length() == 1);
2767  CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
2768  if (!callable->IsJSFunction()) {
2769  HandleScope scope(isolate);
2770  bool threw = false;
2772  isolate, Handle<JSReceiver>(callable), &threw);
2773  if (threw) return Failure::Exception();
2774  callable = JSFunction::cast(*delegate);
2775  }
2776  JSFunction* function = JSFunction::cast(callable);
2777  SharedFunctionInfo* shared = function->shared();
2778  return isolate->heap()->ToBoolean(shared->strict_mode() == SLOPPY);
2779 }
2780 
2781 
2782 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultReceiver) {
2783  SealHandleScope shs(isolate);
2784  ASSERT(args.length() == 1);
2785  CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
2786 
2787  if (!callable->IsJSFunction()) {
2788  HandleScope scope(isolate);
2789  bool threw = false;
2791  isolate, Handle<JSReceiver>(callable), &threw);
2792  if (threw) return Failure::Exception();
2793  callable = JSFunction::cast(*delegate);
2794  }
2795  JSFunction* function = JSFunction::cast(callable);
2796 
2797  SharedFunctionInfo* shared = function->shared();
2798  if (shared->native() || shared->strict_mode() == STRICT) {
2799  return isolate->heap()->undefined_value();
2800  }
2801  // Returns undefined for strict or native functions, or
2802  // the associated global receiver for "normal" functions.
2803 
2804  Context* native_context =
2805  function->context()->global_object()->native_context();
2806  return native_context->global_object()->global_receiver();
2807 }
2808 
2809 
2810 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_MaterializeRegExpLiteral) {
2811  HandleScope scope(isolate);
2812  ASSERT(args.length() == 4);
2813  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
2814  int index = args.smi_at(1);
2815  Handle<String> pattern = args.at<String>(2);
2816  Handle<String> flags = args.at<String>(3);
2817 
2818  // Get the RegExp function from the context in the literals array.
2819  // This is the RegExp function from the context in which the
2820  // function was created. We do not use the RegExp function from the
2821  // current native context because this might be the RegExp function
2822  // from another context which we should not have access to.
2823  Handle<JSFunction> constructor =
2825  JSFunction::NativeContextFromLiterals(*literals)->regexp_function());
2826  // Compute the regular expression literal.
2827  bool has_pending_exception;
2828  Handle<Object> regexp =
2829  RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
2830  &has_pending_exception);
2831  if (has_pending_exception) {
2832  ASSERT(isolate->has_pending_exception());
2833  return Failure::Exception();
2834  }
2835  literals->set(index, *regexp);
2836  return *regexp;
2837 }
2838 
2839 
2840 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetName) {
2841  SealHandleScope shs(isolate);
2842  ASSERT(args.length() == 1);
2843 
2845  return f->shared()->name();
2846 }
2847 
2848 
2849 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetName) {
2850  SealHandleScope shs(isolate);
2851  ASSERT(args.length() == 2);
2852 
2854  CONVERT_ARG_CHECKED(String, name, 1);
2855  f->shared()->set_name(name);
2856  return isolate->heap()->undefined_value();
2857 }
2858 
2859 
2860 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionNameShouldPrintAsAnonymous) {
2861  SealHandleScope shs(isolate);
2862  ASSERT(args.length() == 1);
2864  return isolate->heap()->ToBoolean(
2865  f->shared()->name_should_print_as_anonymous());
2866 }
2867 
2868 
2869 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) {
2870  SealHandleScope shs(isolate);
2871  ASSERT(args.length() == 1);
2873  f->shared()->set_name_should_print_as_anonymous(true);
2874  return isolate->heap()->undefined_value();
2875 }
2876 
2877 
2878 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsGenerator) {
2879  SealHandleScope shs(isolate);
2880  ASSERT(args.length() == 1);
2882  return isolate->heap()->ToBoolean(f->shared()->is_generator());
2883 }
2884 
2885 
2886 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) {
2887  SealHandleScope shs(isolate);
2888  ASSERT(args.length() == 1);
2889 
2891  f->RemovePrototype();
2892 
2893  return isolate->heap()->undefined_value();
2894 }
2895 
2896 
2897 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScript) {
2898  HandleScope scope(isolate);
2899  ASSERT(args.length() == 1);
2900 
2902  Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate);
2903  if (!script->IsScript()) return isolate->heap()->undefined_value();
2904 
2905  return *GetScriptWrapper(Handle<Script>::cast(script));
2906 }
2907 
2908 
2909 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetSourceCode) {
2910  HandleScope scope(isolate);
2911  ASSERT(args.length() == 1);
2912 
2914  Handle<SharedFunctionInfo> shared(f->shared());
2915  return *shared->GetSourceCode();
2916 }
2917 
2918 
2919 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScriptSourcePosition) {
2920  SealHandleScope shs(isolate);
2921  ASSERT(args.length() == 1);
2922 
2924  int pos = fun->shared()->start_position();
2925  return Smi::FromInt(pos);
2926 }
2927 
2928 
2929 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetPositionForOffset) {
2930  SealHandleScope shs(isolate);
2931  ASSERT(args.length() == 2);
2932 
2934  CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]);
2935 
2936  RUNTIME_ASSERT(0 <= offset && offset < code->Size());
2937 
2938  Address pc = code->address() + offset;
2939  return Smi::FromInt(code->SourcePosition(pc));
2940 }
2941 
2942 
2943 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetInstanceClassName) {
2944  SealHandleScope shs(isolate);
2945  ASSERT(args.length() == 2);
2946 
2948  CONVERT_ARG_CHECKED(String, name, 1);
2949  fun->SetInstanceClassName(name);
2950  return isolate->heap()->undefined_value();
2951 }
2952 
2953 
2954 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetLength) {
2955  SealHandleScope shs(isolate);
2956  ASSERT(args.length() == 2);
2957 
2959  CONVERT_SMI_ARG_CHECKED(length, 1);
2960  fun->shared()->set_length(length);
2961  return isolate->heap()->undefined_value();
2962 }
2963 
2964 
2965 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) {
2966  HandleScope scope(isolate);
2967  ASSERT(args.length() == 2);
2968 
2971  ASSERT(fun->should_have_prototype());
2972  Accessors::FunctionSetPrototype(fun, value);
2973  return args[0]; // return TOS
2974 }
2975 
2976 
2977 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) {
2978  SealHandleScope shs(isolate);
2979  RUNTIME_ASSERT(args.length() == 1);
2980  CONVERT_ARG_CHECKED(JSFunction, function, 0);
2981 
2982  String* name = isolate->heap()->prototype_string();
2983 
2984  if (function->HasFastProperties()) {
2985  // Construct a new field descriptor with updated attributes.
2986  DescriptorArray* instance_desc = function->map()->instance_descriptors();
2987 
2988  int index = instance_desc->SearchWithCache(name, function->map());
2990  PropertyDetails details = instance_desc->GetDetails(index);
2991 
2992  CallbacksDescriptor new_desc(name,
2993  instance_desc->GetValue(index),
2994  static_cast<PropertyAttributes>(details.attributes() | READ_ONLY));
2995 
2996  // Create a new map featuring the new field descriptors array.
2997  Map* new_map;
2998  MaybeObject* maybe_map =
2999  function->map()->CopyReplaceDescriptor(
3000  instance_desc, &new_desc, index, OMIT_TRANSITION);
3001  if (!maybe_map->To(&new_map)) return maybe_map;
3002 
3003  function->set_map(new_map);
3004  } else { // Dictionary properties.
3005  // Directly manipulate the property details.
3006  int entry = function->property_dictionary()->FindEntry(name);
3008  PropertyDetails details = function->property_dictionary()->DetailsAt(entry);
3009  PropertyDetails new_details(
3010  static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
3011  details.type(),
3012  details.dictionary_index());
3013  function->property_dictionary()->DetailsAtPut(entry, new_details);
3014  }
3015  return function;
3016 }
3017 
3018 
3019 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) {
3020  SealHandleScope shs(isolate);
3021  ASSERT(args.length() == 1);
3022 
3024  return isolate->heap()->ToBoolean(f->shared()->IsApiFunction());
3025 }
3026 
3027 
3028 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) {
3029  SealHandleScope shs(isolate);
3030  ASSERT(args.length() == 1);
3031 
3033  return isolate->heap()->ToBoolean(f->IsBuiltin());
3034 }
3035 
3036 
3037 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
3038  HandleScope scope(isolate);
3039  ASSERT(args.length() == 2);
3040 
3042  Handle<Object> code = args.at<Object>(1);
3043 
3044  if (code->IsNull()) return *target;
3045  RUNTIME_ASSERT(code->IsJSFunction());
3047  Handle<SharedFunctionInfo> target_shared(target->shared());
3048  Handle<SharedFunctionInfo> source_shared(source->shared());
3049 
3050  if (!Compiler::EnsureCompiled(source, KEEP_EXCEPTION)) {
3051  return Failure::Exception();
3052  }
3053 
3054  // Mark both, the source and the target, as un-flushable because the
3055  // shared unoptimized code makes them impossible to enqueue in a list.
3056  ASSERT(target_shared->code()->gc_metadata() == NULL);
3057  ASSERT(source_shared->code()->gc_metadata() == NULL);
3058  target_shared->set_dont_flush(true);
3059  source_shared->set_dont_flush(true);
3060 
3061  // Set the code, scope info, formal parameter count, and the length
3062  // of the target shared function info.
3063  target_shared->ReplaceCode(source_shared->code());
3064  target_shared->set_scope_info(source_shared->scope_info());
3065  target_shared->set_length(source_shared->length());
3066  target_shared->set_formal_parameter_count(
3067  source_shared->formal_parameter_count());
3068  target_shared->set_script(source_shared->script());
3069  target_shared->set_start_position_and_type(
3070  source_shared->start_position_and_type());
3071  target_shared->set_end_position(source_shared->end_position());
3072  bool was_native = target_shared->native();
3073  target_shared->set_compiler_hints(source_shared->compiler_hints());
3074  target_shared->set_native(was_native);
3075 
3076  // Set the code of the target function.
3077  target->ReplaceCode(source_shared->code());
3078  ASSERT(target->next_function_link()->IsUndefined());
3079 
3080  // Make sure we get a fresh copy of the literal vector to avoid cross
3081  // context contamination.
3082  Handle<Context> context(source->context());
3083  int number_of_literals = source->NumberOfLiterals();
3084  Handle<FixedArray> literals =
3085  isolate->factory()->NewFixedArray(number_of_literals, TENURED);
3086  if (number_of_literals > 0) {
3088  context->native_context());
3089  }
3090  target->set_context(*context);
3091  target->set_literals(*literals);
3092 
3093  if (isolate->logger()->is_logging_code_events() ||
3094  isolate->cpu_profiler()->is_profiling()) {
3095  isolate->logger()->LogExistingFunction(
3096  source_shared, Handle<Code>(source_shared->code()));
3097  }
3098 
3099  return *target;
3100 }
3101 
3102 
3103 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetExpectedNumberOfProperties) {
3104  HandleScope scope(isolate);
3105  ASSERT(args.length() == 2);
3107  CONVERT_SMI_ARG_CHECKED(num, 1);
3108  RUNTIME_ASSERT(num >= 0);
3109  // If objects constructed from this function exist then changing
3110  // 'estimated_nof_properties' is dangerous since the previous value might
3111  // have been compiled into the fast construct stub. Moreover, the inobject
3112  // slack tracking logic might have adjusted the previous value, so even
3113  // passing the same value is risky.
3114  if (!func->shared()->live_objects_may_exist()) {
3115  func->shared()->set_expected_nof_properties(num);
3116  if (func->has_initial_map()) {
3117  Handle<Map> new_initial_map =
3118  func->GetIsolate()->factory()->CopyMap(
3119  Handle<Map>(func->initial_map()));
3120  new_initial_map->set_unused_property_fields(num);
3121  func->set_initial_map(*new_initial_map);
3122  }
3123  }
3124  return isolate->heap()->undefined_value();
3125 }
3126 
3127 
3128 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_CreateJSGeneratorObject) {
3129  HandleScope scope(isolate);
3130  ASSERT(args.length() == 0);
3131 
3132  JavaScriptFrameIterator it(isolate);
3133  JavaScriptFrame* frame = it.frame();
3134  Handle<JSFunction> function(frame->function());
3135  RUNTIME_ASSERT(function->shared()->is_generator());
3136 
3137  Handle<JSGeneratorObject> generator;
3138  if (frame->IsConstructor()) {
3139  generator = handle(JSGeneratorObject::cast(frame->receiver()));
3140  } else {
3141  generator = isolate->factory()->NewJSGeneratorObject(function);
3142  }
3143  generator->set_function(*function);
3144  generator->set_context(Context::cast(frame->context()));
3145  generator->set_receiver(frame->receiver());
3146  generator->set_continuation(0);
3147  generator->set_operand_stack(isolate->heap()->empty_fixed_array());
3148  generator->set_stack_handler_index(-1);
3149 
3150  return *generator;
3151 }
3152 
3153 
3154 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_SuspendJSGeneratorObject) {
3155  SealHandleScope shs(isolate);
3156  ASSERT(args.length() == 1);
3157  CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
3158 
3159  JavaScriptFrameIterator stack_iterator(isolate);
3160  JavaScriptFrame* frame = stack_iterator.frame();
3161  RUNTIME_ASSERT(frame->function()->shared()->is_generator());
3162  ASSERT_EQ(frame->function(), generator_object->function());
3163 
3164  // The caller should have saved the context and continuation already.
3165  ASSERT_EQ(generator_object->context(), Context::cast(frame->context()));
3166  ASSERT_LT(0, generator_object->continuation());
3167 
3168  // We expect there to be at least two values on the operand stack: the return
3169  // value of the yield expression, and the argument to this runtime call.
3170  // Neither of those should be saved.
3171  int operands_count = frame->ComputeOperandsCount();
3172  ASSERT_GE(operands_count, 2);
3173  operands_count -= 2;
3174 
3175  if (operands_count == 0) {
3176  // Although it's semantically harmless to call this function with an
3177  // operands_count of zero, it is also unnecessary.
3178  ASSERT_EQ(generator_object->operand_stack(),
3179  isolate->heap()->empty_fixed_array());
3180  ASSERT_EQ(generator_object->stack_handler_index(), -1);
3181  // If there are no operands on the stack, there shouldn't be a handler
3182  // active either.
3183  ASSERT(!frame->HasHandler());
3184  } else {
3185  int stack_handler_index = -1;
3186  MaybeObject* alloc = isolate->heap()->AllocateFixedArray(operands_count);
3187  FixedArray* operand_stack;
3188  if (!alloc->To(&operand_stack)) return alloc;
3189  frame->SaveOperandStack(operand_stack, &stack_handler_index);
3190  generator_object->set_operand_stack(operand_stack);
3191  generator_object->set_stack_handler_index(stack_handler_index);
3192  }
3193 
3194  return isolate->heap()->undefined_value();
3195 }
3196 
3197 
3198 // Note that this function is the slow path for resuming generators. It is only
3199 // called if the suspended activation had operands on the stack, stack handlers
3200 // needing rewinding, or if the resume should throw an exception. The fast path
3201 // is handled directly in FullCodeGenerator::EmitGeneratorResume(), which is
3202 // inlined into GeneratorNext and GeneratorThrow. EmitGeneratorResumeResume is
3203 // called in any case, as it needs to reconstruct the stack frame and make space
3204 // for arguments and operands.
3205 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_ResumeJSGeneratorObject) {
3206  SealHandleScope shs(isolate);
3207  ASSERT(args.length() == 3);
3208  CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
3209  CONVERT_ARG_CHECKED(Object, value, 1);
3210  CONVERT_SMI_ARG_CHECKED(resume_mode_int, 2);
3211  JavaScriptFrameIterator stack_iterator(isolate);
3212  JavaScriptFrame* frame = stack_iterator.frame();
3213 
3214  ASSERT_EQ(frame->function(), generator_object->function());
3215  ASSERT(frame->function()->is_compiled());
3216 
3219 
3220  Address pc = generator_object->function()->code()->instruction_start();
3221  int offset = generator_object->continuation();
3222  ASSERT(offset > 0);
3223  frame->set_pc(pc + offset);
3224  if (FLAG_enable_ool_constant_pool) {
3225  frame->set_constant_pool(
3226  generator_object->function()->code()->constant_pool());
3227  }
3228  generator_object->set_continuation(JSGeneratorObject::kGeneratorExecuting);
3229 
3230  FixedArray* operand_stack = generator_object->operand_stack();
3231  int operands_count = operand_stack->length();
3232  if (operands_count != 0) {
3233  frame->RestoreOperandStack(operand_stack,
3234  generator_object->stack_handler_index());
3235  generator_object->set_operand_stack(isolate->heap()->empty_fixed_array());
3236  generator_object->set_stack_handler_index(-1);
3237  }
3238 
3239  JSGeneratorObject::ResumeMode resume_mode =
3240  static_cast<JSGeneratorObject::ResumeMode>(resume_mode_int);
3241  switch (resume_mode) {
3243  return value;
3245  return isolate->Throw(value);
3246  }
3247 
3248  UNREACHABLE();
3249  return isolate->ThrowIllegalOperation();
3250 }
3251 
3252 
3253 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_ThrowGeneratorStateError) {
3254  HandleScope scope(isolate);
3255  ASSERT(args.length() == 1);
3257  int continuation = generator->continuation();
3258  const char* message = continuation == JSGeneratorObject::kGeneratorClosed ?
3259  "generator_finished" : "generator_running";
3260  Vector< Handle<Object> > argv = HandleVector<Object>(NULL, 0);
3261  Handle<Object> error = isolate->factory()->NewError(message, argv);
3262  return isolate->Throw(*error);
3263 }
3264 
3265 
3266 RUNTIME_FUNCTION(MaybeObject*, Runtime_ObjectFreeze) {
3267  HandleScope scope(isolate);
3268  ASSERT(args.length() == 1);
3270  Handle<Object> result = JSObject::Freeze(object);
3271  RETURN_IF_EMPTY_HANDLE(isolate, result);
3272  return *result;
3273 }
3274 
3275 
3276 MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate,
3277  Object* char_code) {
3278  if (char_code->IsNumber()) {
3279  return isolate->heap()->LookupSingleCharacterStringFromCode(
3280  NumberToUint32(char_code) & 0xffff);
3281  }
3282  return isolate->heap()->empty_string();
3283 }
3284 
3285 
3286 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StringCharCodeAt) {
3287  SealHandleScope shs(isolate);
3288  ASSERT(args.length() == 2);
3289 
3290  CONVERT_ARG_CHECKED(String, subject, 0);
3291  CONVERT_NUMBER_CHECKED(uint32_t, i, Uint32, args[1]);
3292 
3293  // Flatten the string. If someone wants to get a char at an index
3294  // in a cons string, it is likely that more indices will be
3295  // accessed.
3296  Object* flat;
3297  { MaybeObject* maybe_flat = subject->TryFlatten();
3298  if (!maybe_flat->ToObject(&flat)) return maybe_flat;
3299  }
3300  subject = String::cast(flat);
3301 
3302  if (i >= static_cast<uint32_t>(subject->length())) {
3303  return isolate->heap()->nan_value();
3304  }
3305 
3306  return Smi::FromInt(subject->Get(i));
3307 }
3308 
3309 
3310 RUNTIME_FUNCTION(MaybeObject*, Runtime_CharFromCode) {
3311  SealHandleScope shs(isolate);
3312  ASSERT(args.length() == 1);
3313  return CharFromCode(isolate, args[0]);
3314 }
3315 
3316 
3318  public:
3319  explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity)
3320  : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)),
3321  length_(0),
3322  has_non_smi_elements_(false) {
3323  // Require a non-zero initial size. Ensures that doubling the size to
3324  // extend the array will work.
3325  ASSERT(initial_capacity > 0);
3326  }
3327 
3328  explicit FixedArrayBuilder(Handle<FixedArray> backing_store)
3329  : array_(backing_store),
3330  length_(0),
3331  has_non_smi_elements_(false) {
3332  // Require a non-zero initial size. Ensures that doubling the size to
3333  // extend the array will work.
3334  ASSERT(backing_store->length() > 0);
3335  }
3336 
3337  bool HasCapacity(int elements) {
3338  int length = array_->length();
3339  int required_length = length_ + elements;
3340  return (length >= required_length);
3341  }
3342 
3343  void EnsureCapacity(int elements) {
3344  int length = array_->length();
3345  int required_length = length_ + elements;
3346  if (length < required_length) {
3347  int new_length = length;
3348  do {
3349  new_length *= 2;
3350  } while (new_length < required_length);
3351  Handle<FixedArray> extended_array =
3352  array_->GetIsolate()->factory()->NewFixedArrayWithHoles(new_length);
3353  array_->CopyTo(0, *extended_array, 0, length_);
3354  array_ = extended_array;
3355  }
3356  }
3357 
3358  void Add(Object* value) {
3359  ASSERT(!value->IsSmi());
3360  ASSERT(length_ < capacity());
3361  array_->set(length_, value);
3362  length_++;
3363  has_non_smi_elements_ = true;
3364  }
3365 
3366  void Add(Smi* value) {
3367  ASSERT(value->IsSmi());
3368  ASSERT(length_ < capacity());
3369  array_->set(length_, value);
3370  length_++;
3371  }
3372 
3374  return array_;
3375  }
3376 
3377  int length() {
3378  return length_;
3379  }
3380 
3381  int capacity() {
3382  return array_->length();
3383  }
3384 
3386  JSArray::SetContent(target_array, array_);
3387  target_array->set_length(Smi::FromInt(length_));
3388  return target_array;
3389  }
3390 
3391 
3392  private:
3393  Handle<FixedArray> array_;
3394  int length_;
3395  bool has_non_smi_elements_;
3396 };
3397 
3398 
3399 // Forward declarations.
3402 
3403 template <typename schar>
3404 static inline void StringBuilderConcatHelper(String*,
3405  schar*,
3406  FixedArray*,
3407  int);
3408 
3411 typedef BitField<int,
3415 
3416 
3418  public:
3420  Handle<String> subject,
3421  int estimated_part_count)
3422  : heap_(heap),
3423  array_builder_(heap->isolate(), estimated_part_count),
3424  subject_(subject),
3425  character_count_(0),
3426  is_ascii_(subject->IsOneByteRepresentation()) {
3427  // Require a non-zero initial size. Ensures that doubling the size to
3428  // extend the array will work.
3429  ASSERT(estimated_part_count > 0);
3430  }
3431 
3432  static inline void AddSubjectSlice(FixedArrayBuilder* builder,
3433  int from,
3434  int to) {
3435  ASSERT(from >= 0);
3436  int length = to - from;
3437  ASSERT(length > 0);
3440  int encoded_slice = StringBuilderSubstringLength::encode(length) |
3442  builder->Add(Smi::FromInt(encoded_slice));
3443  } else {
3444  // Otherwise encode as two smis.
3445  builder->Add(Smi::FromInt(-length));
3446  builder->Add(Smi::FromInt(from));
3447  }
3448  }
3449 
3450 
3451  void EnsureCapacity(int elements) {
3452  array_builder_.EnsureCapacity(elements);
3453  }
3454 
3455 
3456  void AddSubjectSlice(int from, int to) {
3457  AddSubjectSlice(&array_builder_, from, to);
3458  IncrementCharacterCount(to - from);
3459  }
3460 
3461 
3462  void AddString(Handle<String> string) {
3463  int length = string->length();
3464  ASSERT(length > 0);
3465  AddElement(*string);
3466  if (!string->IsOneByteRepresentation()) {
3467  is_ascii_ = false;
3468  }
3469  IncrementCharacterCount(length);
3470  }
3471 
3472 
3474  if (array_builder_.length() == 0) {
3475  return heap_->isolate()->factory()->empty_string();
3476  }
3477 
3478  Handle<String> joined_string;
3479  if (is_ascii_) {
3480  Handle<SeqOneByteString> seq = NewRawOneByteString(character_count_);
3482  DisallowHeapAllocation no_gc;
3483  uint8_t* char_buffer = seq->GetChars();
3484  StringBuilderConcatHelper(*subject_,
3485  char_buffer,
3486  *array_builder_.array(),
3487  array_builder_.length());
3488  joined_string = Handle<String>::cast(seq);
3489  } else {
3490  // Non-ASCII.
3491  Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_);
3493  DisallowHeapAllocation no_gc;
3494  uc16* char_buffer = seq->GetChars();
3495  StringBuilderConcatHelper(*subject_,
3496  char_buffer,
3497  *array_builder_.array(),
3498  array_builder_.length());
3499  joined_string = Handle<String>::cast(seq);
3500  }
3501  return joined_string;
3502  }
3503 
3504 
3506  if (character_count_ > String::kMaxLength - by) {
3508  character_count_ = kMaxInt;
3509  } else {
3510  character_count_ += by;
3511  }
3512  }
3513 
3514  private:
3515  Handle<SeqOneByteString> NewRawOneByteString(int length) {
3516  return heap_->isolate()->factory()->NewRawOneByteString(length);
3517  }
3518 
3519 
3520  Handle<SeqTwoByteString> NewRawTwoByteString(int length) {
3521  return heap_->isolate()->factory()->NewRawTwoByteString(length);
3522  }
3523 
3524 
3525  void AddElement(Object* element) {
3526  ASSERT(element->IsSmi() || element->IsString());
3527  ASSERT(array_builder_.capacity() > array_builder_.length());
3528  array_builder_.Add(element);
3529  }
3530 
3531  Heap* heap_;
3532  FixedArrayBuilder array_builder_;
3533  Handle<String> subject_;
3534  int character_count_;
3535  bool is_ascii_;
3536 };
3537 
3538 
3540  public:
3542  : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {}
3543 
3544  // Return whether the replacement is simple.
3545  bool Compile(Handle<String> replacement,
3546  int capture_count,
3547  int subject_length);
3548 
3549  // Use Apply only if Compile returned false.
3550  void Apply(ReplacementStringBuilder* builder,
3551  int match_from,
3552  int match_to,
3553  int32_t* match);
3554 
3555  // Number of distinct parts of the replacement pattern.
3556  int parts() {
3557  return parts_.length();
3558  }
3559 
3560  Zone* zone() const { return zone_; }
3561 
3562  private:
3563  enum PartType {
3564  SUBJECT_PREFIX = 1,
3565  SUBJECT_SUFFIX,
3566  SUBJECT_CAPTURE,
3567  REPLACEMENT_SUBSTRING,
3568  REPLACEMENT_STRING,
3569 
3570  NUMBER_OF_PART_TYPES
3571  };
3572 
3573  struct ReplacementPart {
3574  static inline ReplacementPart SubjectMatch() {
3575  return ReplacementPart(SUBJECT_CAPTURE, 0);
3576  }
3577  static inline ReplacementPart SubjectCapture(int capture_index) {
3578  return ReplacementPart(SUBJECT_CAPTURE, capture_index);
3579  }
3580  static inline ReplacementPart SubjectPrefix() {
3581  return ReplacementPart(SUBJECT_PREFIX, 0);
3582  }
3583  static inline ReplacementPart SubjectSuffix(int subject_length) {
3584  return ReplacementPart(SUBJECT_SUFFIX, subject_length);
3585  }
3586  static inline ReplacementPart ReplacementString() {
3587  return ReplacementPart(REPLACEMENT_STRING, 0);
3588  }
3589  static inline ReplacementPart ReplacementSubString(int from, int to) {
3590  ASSERT(from >= 0);
3591  ASSERT(to > from);
3592  return ReplacementPart(-from, to);
3593  }
3594 
3595  // If tag <= 0 then it is the negation of a start index of a substring of
3596  // the replacement pattern, otherwise it's a value from PartType.
3597  ReplacementPart(int tag, int data)
3598  : tag(tag), data(data) {
3599  // Must be non-positive or a PartType value.
3600  ASSERT(tag < NUMBER_OF_PART_TYPES);
3601  }
3602  // Either a value of PartType or a non-positive number that is
3603  // the negation of an index into the replacement string.
3604  int tag;
3605  // The data value's interpretation depends on the value of tag:
3606  // tag == SUBJECT_PREFIX ||
3607  // tag == SUBJECT_SUFFIX: data is unused.
3608  // tag == SUBJECT_CAPTURE: data is the number of the capture.
3609  // tag == REPLACEMENT_SUBSTRING ||
3610  // tag == REPLACEMENT_STRING: data is index into array of substrings
3611  // of the replacement string.
3612  // tag <= 0: Temporary representation of the substring of the replacement
3613  // string ranging over -tag .. data.
3614  // Is replaced by REPLACEMENT_{SUB,}STRING when we create the
3615  // substring objects.
3616  int data;
3617  };
3618 
3619  template<typename Char>
3620  bool ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
3621  Vector<Char> characters,
3622  int capture_count,
3623  int subject_length,
3624  Zone* zone) {
3625  int length = characters.length();
3626  int last = 0;
3627  for (int i = 0; i < length; i++) {
3628  Char c = characters[i];
3629  if (c == '$') {
3630  int next_index = i + 1;
3631  if (next_index == length) { // No next character!
3632  break;
3633  }
3634  Char c2 = characters[next_index];
3635  switch (c2) {
3636  case '$':
3637  if (i > last) {
3638  // There is a substring before. Include the first "$".
3639  parts->Add(ReplacementPart::ReplacementSubString(last, next_index),
3640  zone);
3641  last = next_index + 1; // Continue after the second "$".
3642  } else {
3643  // Let the next substring start with the second "$".
3644  last = next_index;
3645  }
3646  i = next_index;
3647  break;
3648  case '`':
3649  if (i > last) {
3650  parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3651  }
3652  parts->Add(ReplacementPart::SubjectPrefix(), zone);
3653  i = next_index;
3654  last = i + 1;
3655  break;
3656  case '\'':
3657  if (i > last) {
3658  parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3659  }
3660  parts->Add(ReplacementPart::SubjectSuffix(subject_length), zone);
3661  i = next_index;
3662  last = i + 1;
3663  break;
3664  case '&':
3665  if (i > last) {
3666  parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3667  }
3668  parts->Add(ReplacementPart::SubjectMatch(), zone);
3669  i = next_index;
3670  last = i + 1;
3671  break;
3672  case '0':
3673  case '1':
3674  case '2':
3675  case '3':
3676  case '4':
3677  case '5':
3678  case '6':
3679  case '7':
3680  case '8':
3681  case '9': {
3682  int capture_ref = c2 - '0';
3683  if (capture_ref > capture_count) {
3684  i = next_index;
3685  continue;
3686  }
3687  int second_digit_index = next_index + 1;
3688  if (second_digit_index < length) {
3689  // Peek ahead to see if we have two digits.
3690  Char c3 = characters[second_digit_index];
3691  if ('0' <= c3 && c3 <= '9') { // Double digits.
3692  int double_digit_ref = capture_ref * 10 + c3 - '0';
3693  if (double_digit_ref <= capture_count) {
3694  next_index = second_digit_index;
3695  capture_ref = double_digit_ref;
3696  }
3697  }
3698  }
3699  if (capture_ref > 0) {
3700  if (i > last) {
3701  parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3702  }
3703  ASSERT(capture_ref <= capture_count);
3704  parts->Add(ReplacementPart::SubjectCapture(capture_ref), zone);
3705  last = next_index + 1;
3706  }
3707  i = next_index;
3708  break;
3709  }
3710  default:
3711  i = next_index;
3712  break;
3713  }
3714  }
3715  }
3716  if (length > last) {
3717  if (last == 0) {
3718  // Replacement is simple. Do not use Apply to do the replacement.
3719  return true;
3720  } else {
3721  parts->Add(ReplacementPart::ReplacementSubString(last, length), zone);
3722  }
3723  }
3724  return false;
3725  }
3726 
3727  ZoneList<ReplacementPart> parts_;
3728  ZoneList<Handle<String> > replacement_substrings_;
3729  Zone* zone_;
3730 };
3731 
3732 
3734  int capture_count,
3735  int subject_length) {
3736  {
3737  DisallowHeapAllocation no_gc;
3738  String::FlatContent content = replacement->GetFlatContent();
3739  ASSERT(content.IsFlat());
3740  bool simple = false;
3741  if (content.IsAscii()) {
3742  simple = ParseReplacementPattern(&parts_,
3743  content.ToOneByteVector(),
3744  capture_count,
3745  subject_length,
3746  zone());
3747  } else {
3748  ASSERT(content.IsTwoByte());
3749  simple = ParseReplacementPattern(&parts_,
3750  content.ToUC16Vector(),
3751  capture_count,
3752  subject_length,
3753  zone());
3754  }
3755  if (simple) return true;
3756  }
3757 
3758  Isolate* isolate = replacement->GetIsolate();
3759  // Find substrings of replacement string and create them as String objects.
3760  int substring_index = 0;
3761  for (int i = 0, n = parts_.length(); i < n; i++) {
3762  int tag = parts_[i].tag;
3763  if (tag <= 0) { // A replacement string slice.
3764  int from = -tag;
3765  int to = parts_[i].data;
3766  replacement_substrings_.Add(
3767  isolate->factory()->NewSubString(replacement, from, to), zone());
3768  parts_[i].tag = REPLACEMENT_SUBSTRING;
3769  parts_[i].data = substring_index;
3770  substring_index++;
3771  } else if (tag == REPLACEMENT_STRING) {
3772  replacement_substrings_.Add(replacement, zone());
3773  parts_[i].data = substring_index;
3774  substring_index++;
3775  }
3776  }
3777  return false;
3778 }
3779 
3780 
3782  int match_from,
3783  int match_to,
3784  int32_t* match) {
3785  ASSERT_LT(0, parts_.length());
3786  for (int i = 0, n = parts_.length(); i < n; i++) {
3787  ReplacementPart part = parts_[i];
3788  switch (part.tag) {
3789  case SUBJECT_PREFIX:
3790  if (match_from > 0) builder->AddSubjectSlice(0, match_from);
3791  break;
3792  case SUBJECT_SUFFIX: {
3793  int subject_length = part.data;
3794  if (match_to < subject_length) {
3795  builder->AddSubjectSlice(match_to, subject_length);
3796  }
3797  break;
3798  }
3799  case SUBJECT_CAPTURE: {
3800  int capture = part.data;
3801  int from = match[capture * 2];
3802  int to = match[capture * 2 + 1];
3803  if (from >= 0 && to > from) {
3804  builder->AddSubjectSlice(from, to);
3805  }
3806  break;
3807  }
3808  case REPLACEMENT_SUBSTRING:
3809  case REPLACEMENT_STRING:
3810  builder->AddString(replacement_substrings_[part.data]);
3811  break;
3812  default:
3813  UNREACHABLE();
3814  }
3815  }
3816 }
3817 
3818 
3820  char pattern,
3821  ZoneList<int>* indices,
3822  unsigned int limit,
3823  Zone* zone) {
3824  ASSERT(limit > 0);
3825  // Collect indices of pattern in subject using memchr.
3826  // Stop after finding at most limit values.
3827  const uint8_t* subject_start = subject.start();
3828  const uint8_t* subject_end = subject_start + subject.length();
3829  const uint8_t* pos = subject_start;
3830  while (limit > 0) {
3831  pos = reinterpret_cast<const uint8_t*>(
3832  memchr(pos, pattern, subject_end - pos));
3833  if (pos == NULL) return;
3834  indices->Add(static_cast<int>(pos - subject_start), zone);
3835  pos++;
3836  limit--;
3837  }
3838 }
3839 
3840 
3842  uc16 pattern,
3843  ZoneList<int>* indices,
3844  unsigned int limit,
3845  Zone* zone) {
3846  ASSERT(limit > 0);
3847  const uc16* subject_start = subject.start();
3848  const uc16* subject_end = subject_start + subject.length();
3849  for (const uc16* pos = subject_start; pos < subject_end && limit > 0; pos++) {
3850  if (*pos == pattern) {
3851  indices->Add(static_cast<int>(pos - subject_start), zone);
3852  limit--;
3853  }
3854  }
3855 }
3856 
3857 
3858 template <typename SubjectChar, typename PatternChar>
3860  Vector<const SubjectChar> subject,
3861  Vector<const PatternChar> pattern,
3862  ZoneList<int>* indices,
3863  unsigned int limit,
3864  Zone* zone) {
3865  ASSERT(limit > 0);
3866  // Collect indices of pattern in subject.
3867  // Stop after finding at most limit values.
3868  int pattern_length = pattern.length();
3869  int index = 0;
3870  StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
3871  while (limit > 0) {
3872  index = search.Search(subject, index);
3873  if (index < 0) return;
3874  indices->Add(index, zone);
3875  index += pattern_length;
3876  limit--;
3877  }
3878 }
3879 
3880 
3882  String* subject,
3883  String* pattern,
3884  ZoneList<int>* indices,
3885  unsigned int limit,
3886  Zone* zone) {
3887  {
3888  DisallowHeapAllocation no_gc;
3889  String::FlatContent subject_content = subject->GetFlatContent();
3890  String::FlatContent pattern_content = pattern->GetFlatContent();
3891  ASSERT(subject_content.IsFlat());
3892  ASSERT(pattern_content.IsFlat());
3893  if (subject_content.IsAscii()) {
3894  Vector<const uint8_t> subject_vector = subject_content.ToOneByteVector();
3895  if (pattern_content.IsAscii()) {
3896  Vector<const uint8_t> pattern_vector =
3897  pattern_content.ToOneByteVector();
3898  if (pattern_vector.length() == 1) {
3899  FindAsciiStringIndices(subject_vector,
3900  pattern_vector[0],
3901  indices,
3902  limit,
3903  zone);
3904  } else {
3905  FindStringIndices(isolate,
3906  subject_vector,
3907  pattern_vector,
3908  indices,
3909  limit,
3910  zone);
3911  }
3912  } else {
3913  FindStringIndices(isolate,
3914  subject_vector,
3915  pattern_content.ToUC16Vector(),
3916  indices,
3917  limit,
3918  zone);
3919  }
3920  } else {
3921  Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
3922  if (pattern_content.IsAscii()) {
3923  Vector<const uint8_t> pattern_vector =
3924  pattern_content.ToOneByteVector();
3925  if (pattern_vector.length() == 1) {
3926  FindTwoByteStringIndices(subject_vector,
3927  pattern_vector[0],
3928  indices,
3929  limit,
3930  zone);
3931  } else {
3932  FindStringIndices(isolate,
3933  subject_vector,
3934  pattern_vector,
3935  indices,
3936  limit,
3937  zone);
3938  }
3939  } else {
3940  Vector<const uc16> pattern_vector = pattern_content.ToUC16Vector();
3941  if (pattern_vector.length() == 1) {
3942  FindTwoByteStringIndices(subject_vector,
3943  pattern_vector[0],
3944  indices,
3945  limit,
3946  zone);
3947  } else {
3948  FindStringIndices(isolate,
3949  subject_vector,
3950  pattern_vector,
3951  indices,
3952  limit,
3953  zone);
3954  }
3955  }
3956  }
3957  }
3958 }
3959 
3960 
3961 template<typename ResultSeqString>
3962 MUST_USE_RESULT static MaybeObject* StringReplaceGlobalAtomRegExpWithString(
3963  Isolate* isolate,
3964  Handle<String> subject,
3965  Handle<JSRegExp> pattern_regexp,
3966  Handle<String> replacement,
3967  Handle<JSArray> last_match_info) {
3968  ASSERT(subject->IsFlat());
3969  ASSERT(replacement->IsFlat());
3970 
3971  ZoneScope zone_scope(isolate->runtime_zone());
3972  ZoneList<int> indices(8, zone_scope.zone());
3973  ASSERT_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag());
3974  String* pattern =
3976  int subject_len = subject->length();
3977  int pattern_len = pattern->length();
3978  int replacement_len = replacement->length();
3979 
3981  isolate, *subject, pattern, &indices, 0xffffffff, zone_scope.zone());
3982 
3983  int matches = indices.length();
3984  if (matches == 0) return *subject;
3985 
3986  // Detect integer overflow.
3987  int64_t result_len_64 =
3988  (static_cast<int64_t>(replacement_len) -
3989  static_cast<int64_t>(pattern_len)) *
3990  static_cast<int64_t>(matches) +
3991  static_cast<int64_t>(subject_len);
3992  int result_len;
3993  if (result_len_64 > static_cast<int64_t>(String::kMaxLength)) {
3995  result_len = kMaxInt; // Provoke exception.
3996  } else {
3997  result_len = static_cast<int>(result_len_64);
3998  }
3999 
4000  int subject_pos = 0;
4001  int result_pos = 0;
4002 
4003  Handle<String> result_seq;
4004  if (ResultSeqString::kHasAsciiEncoding) {
4005  result_seq = isolate->factory()->NewRawOneByteString(result_len);
4006  } else {
4007  result_seq = isolate->factory()->NewRawTwoByteString(result_len);
4008  }
4009  RETURN_IF_EMPTY_HANDLE(isolate, result_seq);
4010  Handle<ResultSeqString> result = Handle<ResultSeqString>::cast(result_seq);
4011 
4012  for (int i = 0; i < matches; i++) {
4013  // Copy non-matched subject content.
4014  if (subject_pos < indices.at(i)) {
4015  String::WriteToFlat(*subject,
4016  result->GetChars() + result_pos,
4017  subject_pos,
4018  indices.at(i));
4019  result_pos += indices.at(i) - subject_pos;
4020  }
4021 
4022  // Replace match.
4023  if (replacement_len > 0) {
4024  String::WriteToFlat(*replacement,
4025  result->GetChars() + result_pos,
4026  0,
4027  replacement_len);
4028  result_pos += replacement_len;
4029  }
4030 
4031  subject_pos = indices.at(i) + pattern_len;
4032  }
4033  // Add remaining subject content at the end.
4034  if (subject_pos < subject_len) {
4035  String::WriteToFlat(*subject,
4036  result->GetChars() + result_pos,
4037  subject_pos,
4038  subject_len);
4039  }
4040 
4041  int32_t match_indices[] = { indices.at(matches - 1),
4042  indices.at(matches - 1) + pattern_len };
4043  RegExpImpl::SetLastMatchInfo(last_match_info, subject, 0, match_indices);
4044 
4045  return *result;
4046 }
4047 
4048 
4049 MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithString(
4050  Isolate* isolate,
4051  Handle<String> subject,
4052  Handle<JSRegExp> regexp,
4053  Handle<String> replacement,
4054  Handle<JSArray> last_match_info) {
4055  ASSERT(subject->IsFlat());
4056  ASSERT(replacement->IsFlat());
4057 
4058  int capture_count = regexp->CaptureCount();
4059  int subject_length = subject->length();
4060 
4061  // CompiledReplacement uses zone allocation.
4062  ZoneScope zone_scope(isolate->runtime_zone());
4063  CompiledReplacement compiled_replacement(zone_scope.zone());
4064  bool simple_replace = compiled_replacement.Compile(replacement,
4065  capture_count,
4066  subject_length);
4067 
4068  // Shortcut for simple non-regexp global replacements
4069  if (regexp->TypeTag() == JSRegExp::ATOM && simple_replace) {
4070  if (subject->HasOnlyOneByteChars() &&
4071  replacement->HasOnlyOneByteChars()) {
4072  return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
4073  isolate, subject, regexp, replacement, last_match_info);
4074  } else {
4075  return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>(
4076  isolate, subject, regexp, replacement, last_match_info);
4077  }
4078  }
4079 
4080  RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4081  if (global_cache.HasException()) return Failure::Exception();
4082 
4083  int32_t* current_match = global_cache.FetchNext();
4084  if (current_match == NULL) {
4085  if (global_cache.HasException()) return Failure::Exception();
4086  return *subject;
4087  }
4088 
4089  // Guessing the number of parts that the final result string is built
4090  // from. Global regexps can match any number of times, so we guess
4091  // conservatively.
4092  int expected_parts = (compiled_replacement.parts() + 1) * 4 + 1;
4093  ReplacementStringBuilder builder(isolate->heap(),
4094  subject,
4095  expected_parts);
4096 
4097  // Number of parts added by compiled replacement plus preceeding
4098  // string and possibly suffix after last match. It is possible for
4099  // all components to use two elements when encoded as two smis.
4100  const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2);
4101 
4102  int prev = 0;
4103 
4104  do {
4105  builder.EnsureCapacity(parts_added_per_loop);
4106 
4107  int start = current_match[0];
4108  int end = current_match[1];
4109 
4110  if (prev < start) {
4111  builder.AddSubjectSlice(prev, start);
4112  }
4113 
4114  if (simple_replace) {
4115  builder.AddString(replacement);
4116  } else {
4117  compiled_replacement.Apply(&builder,
4118  start,
4119  end,
4120  current_match);
4121  }
4122  prev = end;
4123 
4124  current_match = global_cache.FetchNext();
4125  } while (current_match != NULL);
4126 
4127  if (global_cache.HasException()) return Failure::Exception();
4128 
4129  if (prev < subject_length) {
4130  builder.EnsureCapacity(2);
4131  builder.AddSubjectSlice(prev, subject_length);
4132  }
4133 
4134  RegExpImpl::SetLastMatchInfo(last_match_info,
4135  subject,
4136  capture_count,
4137  global_cache.LastSuccessfulMatch());
4138 
4139  Handle<String> result = builder.ToString();
4140  RETURN_IF_EMPTY_HANDLE(isolate, result);
4141  return *result;
4142 }
4143 
4144 
4145 template <typename ResultSeqString>
4146 MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithEmptyString(
4147  Isolate* isolate,
4148  Handle<String> subject,
4149  Handle<JSRegExp> regexp,
4150  Handle<JSArray> last_match_info) {
4151  ASSERT(subject->IsFlat());
4152 
4153  // Shortcut for simple non-regexp global replacements
4154  if (regexp->TypeTag() == JSRegExp::ATOM) {
4155  Handle<String> empty_string = isolate->factory()->empty_string();
4156  if (subject->IsOneByteRepresentation()) {
4157  return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
4158  isolate, subject, regexp, empty_string, last_match_info);
4159  } else {
4160  return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>(
4161  isolate, subject, regexp, empty_string, last_match_info);
4162  }
4163  }
4164 
4165  RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4166  if (global_cache.HasException()) return Failure::Exception();
4167 
4168  int32_t* current_match = global_cache.FetchNext();
4169  if (current_match == NULL) {
4170  if (global_cache.HasException()) return Failure::Exception();
4171  return *subject;
4172  }
4173 
4174  int start = current_match[0];
4175  int end = current_match[1];
4176  int capture_count = regexp->CaptureCount();
4177  int subject_length = subject->length();
4178 
4179  int new_length = subject_length - (end - start);
4180  if (new_length == 0) return isolate->heap()->empty_string();
4181 
4182  Handle<ResultSeqString> answer;
4183  if (ResultSeqString::kHasAsciiEncoding) {
4185  isolate->factory()->NewRawOneByteString(new_length));
4186  } else {
4188  isolate->factory()->NewRawTwoByteString(new_length));
4189  }
4190  ASSERT(!answer.is_null());
4191 
4192  int prev = 0;
4193  int position = 0;
4194 
4195  do {
4196  start = current_match[0];
4197  end = current_match[1];
4198  if (prev < start) {
4199  // Add substring subject[prev;start] to answer string.
4200  String::WriteToFlat(*subject, answer->GetChars() + position, prev, start);
4201  position += start - prev;
4202  }
4203  prev = end;
4204 
4205  current_match = global_cache.FetchNext();
4206  } while (current_match != NULL);
4207 
4208  if (global_cache.HasException()) return Failure::Exception();
4209 
4210  RegExpImpl::SetLastMatchInfo(last_match_info,
4211  subject,
4212  capture_count,
4213  global_cache.LastSuccessfulMatch());
4214 
4215  if (prev < subject_length) {
4216  // Add substring subject[prev;length] to answer string.
4218  *subject, answer->GetChars() + position, prev, subject_length);
4219  position += subject_length - prev;
4220  }
4221 
4222  if (position == 0) return isolate->heap()->empty_string();
4223 
4224  // Shorten string and fill
4225  int string_size = ResultSeqString::SizeFor(position);
4226  int allocated_string_size = ResultSeqString::SizeFor(new_length);
4227  int delta = allocated_string_size - string_size;
4228 
4229  answer->set_length(position);
4230  if (delta == 0) return *answer;
4231 
4232  Address end_of_string = answer->address() + string_size;
4233  Heap* heap = isolate->heap();
4234  heap->CreateFillerObjectAt(end_of_string, delta);
4235  heap->AdjustLiveBytes(answer->address(), -delta, Heap::FROM_MUTATOR);
4236  return *answer;
4237 }
4238 
4239 
4240 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceGlobalRegExpWithString) {
4241  HandleScope scope(isolate);
4242  ASSERT(args.length() == 4);
4243 
4244  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4245  CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2);
4247  CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
4248 
4249  ASSERT(regexp->GetFlags().is_global());
4250 
4251  if (!subject->IsFlat()) subject = FlattenGetString(subject);
4252 
4253  if (replacement->length() == 0) {
4254  if (subject->HasOnlyOneByteChars()) {
4255  return StringReplaceGlobalRegExpWithEmptyString<SeqOneByteString>(
4256  isolate, subject, regexp, last_match_info);
4257  } else {
4258  return StringReplaceGlobalRegExpWithEmptyString<SeqTwoByteString>(
4259  isolate, subject, regexp, last_match_info);
4260  }
4261  }
4262 
4263  if (!replacement->IsFlat()) replacement = FlattenGetString(replacement);
4264 
4265  return StringReplaceGlobalRegExpWithString(
4266  isolate, subject, regexp, replacement, last_match_info);
4267 }
4268 
4269 
4271  Handle<String> subject,
4272  Handle<String> search,
4273  Handle<String> replace,
4274  bool* found,
4275  int recursion_limit) {
4276  if (recursion_limit == 0) return Handle<String>::null();
4277  if (subject->IsConsString()) {
4278  ConsString* cons = ConsString::cast(*subject);
4279  Handle<String> first = Handle<String>(cons->first());
4280  Handle<String> second = Handle<String>(cons->second());
4281  Handle<String> new_first =
4283  first,
4284  search,
4285  replace,
4286  found,
4287  recursion_limit - 1);
4288  if (new_first.is_null()) return new_first;
4289  if (*found) return isolate->factory()->NewConsString(new_first, second);
4290 
4291  Handle<String> new_second =
4293  second,
4294  search,
4295  replace,
4296  found,
4297  recursion_limit - 1);
4298  if (new_second.is_null()) return new_second;
4299  if (*found) return isolate->factory()->NewConsString(first, new_second);
4300 
4301  return subject;
4302  } else {
4303  int index = Runtime::StringMatch(isolate, subject, search, 0);
4304  if (index == -1) return subject;
4305  *found = true;
4306  Handle<String> first = isolate->factory()->NewSubString(subject, 0, index);
4307  Handle<String> cons1 = isolate->factory()->NewConsString(first, replace);
4308  RETURN_IF_EMPTY_HANDLE_VALUE(isolate, cons1, Handle<String>());
4309  Handle<String> second =
4310  isolate->factory()->NewSubString(subject, index + 1, subject->length());
4311  return isolate->factory()->NewConsString(cons1, second);
4312  }
4313 }
4314 
4315 
4316 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) {
4317  HandleScope scope(isolate);
4318  ASSERT(args.length() == 3);
4319  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4320  CONVERT_ARG_HANDLE_CHECKED(String, search, 1);
4321  CONVERT_ARG_HANDLE_CHECKED(String, replace, 2);
4322 
4323  // If the cons string tree is too deep, we simply abort the recursion and
4324  // retry with a flattened subject string.
4325  const int kRecursionLimit = 0x1000;
4326  bool found = false;
4328  subject,
4329  search,
4330  replace,
4331  &found,
4332  kRecursionLimit);
4333  if (!result.is_null()) return *result;
4334  if (isolate->has_pending_exception()) return Failure::Exception();
4335  return *StringReplaceOneCharWithString(isolate,
4336  FlattenGetString(subject),
4337  search,
4338  replace,
4339  &found,
4340  kRecursionLimit);
4341 }
4342 
4343 
4344 // Perform string match of pattern on subject, starting at start index.
4345 // Caller must ensure that 0 <= start_index <= sub->length(),
4346 // and should check that pat->length() + start_index <= sub->length().
4348  Handle<String> sub,
4349  Handle<String> pat,
4350  int start_index) {
4351  ASSERT(0 <= start_index);
4352  ASSERT(start_index <= sub->length());
4353 
4354  int pattern_length = pat->length();
4355  if (pattern_length == 0) return start_index;
4356 
4357  int subject_length = sub->length();
4358  if (start_index + pattern_length > subject_length) return -1;
4359 
4360  if (!sub->IsFlat()) FlattenString(sub);
4361  if (!pat->IsFlat()) FlattenString(pat);
4362 
4363  DisallowHeapAllocation no_gc; // ensure vectors stay valid
4364  // Extract flattened substrings of cons strings before determining asciiness.
4365  String::FlatContent seq_sub = sub->GetFlatContent();
4366  String::FlatContent seq_pat = pat->GetFlatContent();
4367 
4368  // dispatch on type of strings
4369  if (seq_pat.IsAscii()) {
4370  Vector<const uint8_t> pat_vector = seq_pat.ToOneByteVector();
4371  if (seq_sub.IsAscii()) {
4372  return SearchString(isolate,
4373  seq_sub.ToOneByteVector(),
4374  pat_vector,
4375  start_index);
4376  }
4377  return SearchString(isolate,
4378  seq_sub.ToUC16Vector(),
4379  pat_vector,
4380  start_index);
4381  }
4382  Vector<const uc16> pat_vector = seq_pat.ToUC16Vector();
4383  if (seq_sub.IsAscii()) {
4384  return SearchString(isolate,
4385  seq_sub.ToOneByteVector(),
4386  pat_vector,
4387  start_index);
4388  }
4389  return SearchString(isolate,
4390  seq_sub.ToUC16Vector(),
4391  pat_vector,
4392  start_index);
4393 }
4394 
4395 
4396 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringIndexOf) {
4397  HandleScope scope(isolate);
4398  ASSERT(args.length() == 3);
4399 
4402 
4403  Object* index = args[2];
4404  uint32_t start_index;
4405  if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
4406 
4407  RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
4408  int position =
4409  Runtime::StringMatch(isolate, sub, pat, start_index);
4410  return Smi::FromInt(position);
4411 }
4412 
4413 
4414 template <typename schar, typename pchar>
4415 static int StringMatchBackwards(Vector<const schar> subject,
4416  Vector<const pchar> pattern,
4417  int idx) {
4418  int pattern_length = pattern.length();
4419  ASSERT(pattern_length >= 1);
4420  ASSERT(idx + pattern_length <= subject.length());
4421 
4422  if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
4423  for (int i = 0; i < pattern_length; i++) {
4424  uc16 c = pattern[i];
4425  if (c > String::kMaxOneByteCharCode) {
4426  return -1;
4427  }
4428  }
4429  }
4430 
4431  pchar pattern_first_char = pattern[0];
4432  for (int i = idx; i >= 0; i--) {
4433  if (subject[i] != pattern_first_char) continue;
4434  int j = 1;
4435  while (j < pattern_length) {
4436  if (pattern[j] != subject[i+j]) {
4437  break;
4438  }
4439  j++;
4440  }
4441  if (j == pattern_length) {
4442  return i;
4443  }
4444  }
4445  return -1;
4446 }
4447 
4448 
4449 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
4450  HandleScope scope(isolate);
4451  ASSERT(args.length() == 3);
4452 
4455 
4456  Object* index = args[2];
4457  uint32_t start_index;
4458  if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
4459 
4460  uint32_t pat_length = pat->length();
4461  uint32_t sub_length = sub->length();
4462 
4463  if (start_index + pat_length > sub_length) {
4464  start_index = sub_length - pat_length;
4465  }
4466 
4467  if (pat_length == 0) {
4468  return Smi::FromInt(start_index);
4469  }
4470 
4471  if (!sub->IsFlat()) FlattenString(sub);
4472  if (!pat->IsFlat()) FlattenString(pat);
4473 
4474  int position = -1;
4475  DisallowHeapAllocation no_gc; // ensure vectors stay valid
4476 
4477  String::FlatContent sub_content = sub->GetFlatContent();
4478  String::FlatContent pat_content = pat->GetFlatContent();
4479 
4480  if (pat_content.IsAscii()) {
4481  Vector<const uint8_t> pat_vector = pat_content.ToOneByteVector();
4482  if (sub_content.IsAscii()) {
4483  position = StringMatchBackwards(sub_content.ToOneByteVector(),
4484  pat_vector,
4485  start_index);
4486  } else {
4487  position = StringMatchBackwards(sub_content.ToUC16Vector(),
4488  pat_vector,
4489  start_index);
4490  }
4491  } else {
4492  Vector<const uc16> pat_vector = pat_content.ToUC16Vector();
4493  if (sub_content.IsAscii()) {
4494  position = StringMatchBackwards(sub_content.ToOneByteVector(),
4495  pat_vector,
4496  start_index);
4497  } else {
4498  position = StringMatchBackwards(sub_content.ToUC16Vector(),
4499  pat_vector,
4500  start_index);
4501  }
4502  }
4503 
4504  return Smi::FromInt(position);
4505 }
4506 
4507 
4508 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
4509  SealHandleScope shs(isolate);
4510  ASSERT(args.length() == 2);
4511 
4512  CONVERT_ARG_CHECKED(String, str1, 0);
4513  CONVERT_ARG_CHECKED(String, str2, 1);
4514 
4515  if (str1 == str2) return Smi::FromInt(0); // Equal.
4516  int str1_length = str1->length();
4517  int str2_length = str2->length();
4518 
4519  // Decide trivial cases without flattening.
4520  if (str1_length == 0) {
4521  if (str2_length == 0) return Smi::FromInt(0); // Equal.
4522  return Smi::FromInt(-str2_length);
4523  } else {
4524  if (str2_length == 0) return Smi::FromInt(str1_length);
4525  }
4526 
4527  int end = str1_length < str2_length ? str1_length : str2_length;
4528 
4529  // No need to flatten if we are going to find the answer on the first
4530  // character. At this point we know there is at least one character
4531  // in each string, due to the trivial case handling above.
4532  int d = str1->Get(0) - str2->Get(0);
4533  if (d != 0) return Smi::FromInt(d);
4534 
4535  str1->TryFlatten();
4536  str2->TryFlatten();
4537 
4538  ConsStringIteratorOp* op1 =
4539  isolate->runtime_state()->string_locale_compare_it1();
4540  ConsStringIteratorOp* op2 =
4541  isolate->runtime_state()->string_locale_compare_it2();
4542  // TODO(dcarney) Can do array compares here more efficiently.
4543  StringCharacterStream stream1(str1, op1);
4544  StringCharacterStream stream2(str2, op2);
4545 
4546  for (int i = 0; i < end; i++) {
4547  uint16_t char1 = stream1.GetNext();
4548  uint16_t char2 = stream2.GetNext();
4549  if (char1 != char2) return Smi::FromInt(char1 - char2);
4550  }
4551 
4552  return Smi::FromInt(str1_length - str2_length);
4553 }
4554 
4555 
4556 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_SubString) {
4557  HandleScope scope(isolate);
4558  ASSERT(args.length() == 3);
4559 
4560  CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
4561  int start, end;
4562  // We have a fast integer-only case here to avoid a conversion to double in
4563  // the common case where from and to are Smis.
4564  if (args[1]->IsSmi() && args[2]->IsSmi()) {
4565  CONVERT_SMI_ARG_CHECKED(from_number, 1);
4566  CONVERT_SMI_ARG_CHECKED(to_number, 2);
4567  start = from_number;
4568  end = to_number;
4569  } else {
4570  CONVERT_DOUBLE_ARG_CHECKED(from_number, 1);
4571  CONVERT_DOUBLE_ARG_CHECKED(to_number, 2);
4572  start = FastD2IChecked(from_number);
4573  end = FastD2IChecked(to_number);
4574  }
4575  RUNTIME_ASSERT(end >= start);
4576  RUNTIME_ASSERT(start >= 0);
4577  RUNTIME_ASSERT(end <= string->length());
4578  isolate->counters()->sub_string_runtime()->Increment();
4579 
4580  return *isolate->factory()->NewSubString(string, start, end);
4581 }
4582 
4583 
4584 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) {
4585  HandleScope handles(isolate);
4586  ASSERT_EQ(3, args.length());
4587 
4588  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4590  CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2);
4591 
4592  RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4593  if (global_cache.HasException()) return Failure::Exception();
4594 
4595  int capture_count = regexp->CaptureCount();
4596 
4597  ZoneScope zone_scope(isolate->runtime_zone());
4598  ZoneList<int> offsets(8, zone_scope.zone());
4599 
4600  while (true) {
4601  int32_t* match = global_cache.FetchNext();
4602  if (match == NULL) break;
4603  offsets.Add(match[0], zone_scope.zone()); // start
4604  offsets.Add(match[1], zone_scope.zone()); // end
4605  }
4606 
4607  if (global_cache.HasException()) return Failure::Exception();
4608 
4609  if (offsets.length() == 0) {
4610  // Not a single match.
4611  return isolate->heap()->null_value();
4612  }
4613 
4614  RegExpImpl::SetLastMatchInfo(regexp_info,
4615  subject,
4616  capture_count,
4617  global_cache.LastSuccessfulMatch());
4618 
4619  int matches = offsets.length() / 2;
4620  Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches);
4621  Handle<String> substring =
4622  isolate->factory()->NewSubString(subject, offsets.at(0), offsets.at(1));
4623  elements->set(0, *substring);
4624  for (int i = 1; i < matches; i++) {
4625  HandleScope temp_scope(isolate);
4626  int from = offsets.at(i * 2);
4627  int to = offsets.at(i * 2 + 1);
4628  Handle<String> substring =
4629  isolate->factory()->NewProperSubString(subject, from, to);
4630  elements->set(i, *substring);
4631  }
4632  Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements);
4633  result->set_length(Smi::FromInt(matches));
4634  return *result;
4635 }
4636 
4637 
4638 // Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain
4639 // separate last match info. See comment on that function.
4640 template<bool has_capture>
4641 static MaybeObject* SearchRegExpMultiple(
4642  Isolate* isolate,
4643  Handle<String> subject,
4644  Handle<JSRegExp> regexp,
4645  Handle<JSArray> last_match_array,
4646  Handle<JSArray> result_array) {
4647  ASSERT(subject->IsFlat());
4648  ASSERT_NE(has_capture, regexp->CaptureCount() == 0);
4649 
4650  int capture_count = regexp->CaptureCount();
4651  int subject_length = subject->length();
4652 
4653  static const int kMinLengthToCache = 0x1000;
4654 
4655  if (subject_length > kMinLengthToCache) {
4657  isolate->heap(),
4658  *subject,
4659  regexp->data(),
4661  if (*cached_answer != Smi::FromInt(0)) {
4662  Handle<FixedArray> cached_fixed_array =
4663  Handle<FixedArray>(FixedArray::cast(*cached_answer));
4664  // The cache FixedArray is a COW-array and can therefore be reused.
4665  JSArray::SetContent(result_array, cached_fixed_array);
4666  // The actual length of the result array is stored in the last element of
4667  // the backing store (the backing FixedArray may have a larger capacity).
4668  Object* cached_fixed_array_last_element =
4669  cached_fixed_array->get(cached_fixed_array->length() - 1);
4670  Smi* js_array_length = Smi::cast(cached_fixed_array_last_element);
4671  result_array->set_length(js_array_length);
4673  last_match_array, subject, capture_count, NULL);
4674  return *result_array;
4675  }
4676  }
4677 
4678  RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4679  if (global_cache.HasException()) return Failure::Exception();
4680 
4681  Handle<FixedArray> result_elements;
4682  if (result_array->HasFastObjectElements()) {
4683  result_elements =
4684  Handle<FixedArray>(FixedArray::cast(result_array->elements()));
4685  }
4686  if (result_elements.is_null() || result_elements->length() < 16) {
4687  result_elements = isolate->factory()->NewFixedArrayWithHoles(16);
4688  }
4689 
4690  FixedArrayBuilder builder(result_elements);
4691 
4692  // Position to search from.
4693  int match_start = -1;
4694  int match_end = 0;
4695  bool first = true;
4696 
4697  // Two smis before and after the match, for very long strings.
4698  static const int kMaxBuilderEntriesPerRegExpMatch = 5;
4699 
4700  while (true) {
4701  int32_t* current_match = global_cache.FetchNext();
4702  if (current_match == NULL) break;
4703  match_start = current_match[0];
4704  builder.EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
4705  if (match_end < match_start) {
4707  match_end,
4708  match_start);
4709  }
4710  match_end = current_match[1];
4711  {
4712  // Avoid accumulating new handles inside loop.
4713  HandleScope temp_scope(isolate);
4714  Handle<String> match;
4715  if (!first) {
4716  match = isolate->factory()->NewProperSubString(subject,
4717  match_start,
4718  match_end);
4719  } else {
4720  match = isolate->factory()->NewSubString(subject,
4721  match_start,
4722  match_end);
4723  first = false;
4724  }
4725 
4726  if (has_capture) {
4727  // Arguments array to replace function is match, captures, index and
4728  // subject, i.e., 3 + capture count in total.
4729  Handle<FixedArray> elements =
4730  isolate->factory()->NewFixedArray(3 + capture_count);
4731 
4732  elements->set(0, *match);
4733  for (int i = 1; i <= capture_count; i++) {
4734  int start = current_match[i * 2];
4735  if (start >= 0) {
4736  int end = current_match[i * 2 + 1];
4737  ASSERT(start <= end);
4738  Handle<String> substring =
4739  isolate->factory()->NewSubString(subject, start, end);
4740  elements->set(i, *substring);
4741  } else {
4742  ASSERT(current_match[i * 2 + 1] < 0);
4743  elements->set(i, isolate->heap()->undefined_value());
4744  }
4745  }
4746  elements->set(capture_count + 1, Smi::FromInt(match_start));
4747  elements->set(capture_count + 2, *subject);
4748  builder.Add(*isolate->factory()->NewJSArrayWithElements(elements));
4749  } else {
4750  builder.Add(*match);
4751  }
4752  }
4753  }
4754 
4755  if (global_cache.HasException()) return Failure::Exception();
4756 
4757  if (match_start >= 0) {
4758  // Finished matching, with at least one match.
4759  if (match_end < subject_length) {
4761  match_end,
4762  subject_length);
4763  }
4764 
4766  last_match_array, subject, capture_count, NULL);
4767 
4768  if (subject_length > kMinLengthToCache) {
4769  // Store the length of the result array into the last element of the
4770  // backing FixedArray.
4771  builder.EnsureCapacity(1);
4772  Handle<FixedArray> fixed_array = builder.array();
4773  fixed_array->set(fixed_array->length() - 1,
4774  Smi::FromInt(builder.length()));
4775  // Cache the result and turn the FixedArray into a COW array.
4776  RegExpResultsCache::Enter(isolate->heap(),
4777  *subject,
4778  regexp->data(),
4779  *fixed_array,
4781  }
4782  return *builder.ToJSArray(result_array);
4783  } else {
4784  return isolate->heap()->null_value(); // No matches at all.
4785  }
4786 }
4787 
4788 
4789 // This is only called for StringReplaceGlobalRegExpWithFunction. This sets
4790 // lastMatchInfoOverride to maintain the last match info, so we don't need to
4791 // set any other last match array info.
4792 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) {
4793  HandleScope handles(isolate);
4794  ASSERT(args.length() == 4);
4795 
4796  CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
4797  if (!subject->IsFlat()) FlattenString(subject);
4799  CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2);
4800  CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3);
4801 
4802  ASSERT(regexp->GetFlags().is_global());
4803 
4804  if (regexp->CaptureCount() == 0) {
4805  return SearchRegExpMultiple<false>(
4806  isolate, subject, regexp, last_match_info, result_array);
4807  } else {
4808  return SearchRegExpMultiple<true>(
4809  isolate, subject, regexp, last_match_info, result_array);
4810  }
4811 }
4812 
4813 
4814 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) {
4815  SealHandleScope shs(isolate);
4816  ASSERT(args.length() == 2);
4817  CONVERT_SMI_ARG_CHECKED(radix, 1);
4818  RUNTIME_ASSERT(2 <= radix && radix <= 36);
4819 
4820  // Fast case where the result is a one character string.
4821  if (args[0]->IsSmi()) {
4822  int value = args.smi_at(0);
4823  if (value >= 0 && value < radix) {
4824  // Character array used for conversion.
4825  static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
4826  return isolate->heap()->
4827  LookupSingleCharacterStringFromCode(kCharTable[value]);
4828  }
4829  }
4830 
4831  // Slow case.
4832  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4833  if (std::isnan(value)) {
4834  return *isolate->factory()->nan_string();
4835  }
4836  if (std::isinf(value)) {
4837  if (value < 0) {
4838  return *isolate->factory()->minus_infinity_string();
4839  }
4840  return *isolate->factory()->infinity_string();
4841  }
4842  char* str = DoubleToRadixCString(value, radix);
4843  MaybeObject* result =
4844  isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4845  DeleteArray(str);
4846  return result;
4847 }
4848 
4849 
4850 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) {
4851  SealHandleScope shs(isolate);
4852  ASSERT(args.length() == 2);
4853 
4854  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4855  CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4856  int f = FastD2IChecked(f_number);
4857  RUNTIME_ASSERT(f >= 0);
4858  char* str = DoubleToFixedCString(value, f);
4859  MaybeObject* res =
4860  isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4861  DeleteArray(str);
4862  return res;
4863 }
4864 
4865 
4866 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) {
4867  SealHandleScope shs(isolate);
4868  ASSERT(args.length() == 2);
4869 
4870  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4871  CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4872  int f = FastD2IChecked(f_number);
4873  RUNTIME_ASSERT(f >= -1 && f <= 20);
4874  char* str = DoubleToExponentialCString(value, f);
4875  MaybeObject* res =
4876  isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4877  DeleteArray(str);
4878  return res;
4879 }
4880 
4881 
4882 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) {
4883  SealHandleScope shs(isolate);
4884  ASSERT(args.length() == 2);
4885 
4886  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4887  CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4888  int f = FastD2IChecked(f_number);
4889  RUNTIME_ASSERT(f >= 1 && f <= 21);
4890  char* str = DoubleToPrecisionCString(value, f);
4891  MaybeObject* res =
4892  isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4893  DeleteArray(str);
4894  return res;
4895 }
4896 
4897 
4898 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsValidSmi) {
4899  HandleScope shs(isolate);
4900  ASSERT(args.length() == 1);
4901 
4902  CONVERT_NUMBER_CHECKED(int32_t, number, Int32, args[0]);
4903  if (Smi::IsValid(number)) {
4904  return isolate->heap()->true_value();
4905  } else {
4906  return isolate->heap()->false_value();
4907  }
4908 }
4909 
4910 
4911 // Returns a single character string where first character equals
4912 // string->Get(index).
4913 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
4914  if (index < static_cast<uint32_t>(string->length())) {
4915  string->TryFlatten();
4917  string->GetIsolate(),
4918  string->Get(index));
4919  }
4920  return Execution::CharAt(string, index);
4921 }
4922 
4923 
4925  Handle<Object> object,
4926  uint32_t index) {
4927  // Handle [] indexing on Strings
4928  if (object->IsString()) {
4929  Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
4930  if (!result->IsUndefined()) return result;
4931  }
4932 
4933  // Handle [] indexing on String objects
4934  if (object->IsStringObjectWithCharacterAt(index)) {
4935  Handle<JSValue> js_value = Handle<JSValue>::cast(object);
4936  Handle<Object> result =
4937  GetCharAt(Handle<String>(String::cast(js_value->value())), index);
4938  if (!result->IsUndefined()) return result;
4939  }
4940 
4941  Handle<Object> result;
4942  if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
4943  Handle<Object> proto(object->GetPrototype(isolate), isolate);
4944  return Object::GetElement(isolate, proto, index);
4945  } else {
4946  return Object::GetElement(isolate, object, index);
4947  }
4948 }
4949 
4950 
4951 static Handle<Name> ToName(Isolate* isolate, Handle<Object> key) {
4952  if (key->IsName()) {
4953  return Handle<Name>::cast(key);
4954  } else {
4955  bool has_pending_exception = false;
4956  Handle<Object> converted =
4957  Execution::ToString(isolate, key, &has_pending_exception);
4958  if (has_pending_exception) return Handle<Name>();
4959  return Handle<Name>::cast(converted);
4960  }
4961 }
4962 
4963 
4964 MaybeObject* Runtime::HasObjectProperty(Isolate* isolate,
4965  Handle<JSReceiver> object,
4966  Handle<Object> key) {
4967  HandleScope scope(isolate);
4968 
4969  // Check if the given key is an array index.
4970  uint32_t index;
4971  if (key->ToArrayIndex(&index)) {
4972  return isolate->heap()->ToBoolean(JSReceiver::HasElement(object, index));
4973  }
4974 
4975  // Convert the key to a name - possibly by calling back into JavaScript.
4976  Handle<Name> name = ToName(isolate, key);
4977  RETURN_IF_EMPTY_HANDLE(isolate, name);
4978 
4979  return isolate->heap()->ToBoolean(JSReceiver::HasProperty(object, name));
4980 }
4981 
4983  Isolate* isolate,
4984  Handle<Object> object,
4985  Handle<Object> key) {
4987  GetObjectProperty(isolate, object, key));
4988 }
4989 
4990 MaybeObject* Runtime::GetObjectProperty(Isolate* isolate,
4991  Handle<Object> object,
4992  Handle<Object> key) {
4993  HandleScope scope(isolate);
4994 
4995  if (object->IsUndefined() || object->IsNull()) {
4996  Handle<Object> args[2] = { key, object };
4997  Handle<Object> error =
4998  isolate->factory()->NewTypeError("non_object_property_load",
4999  HandleVector(args, 2));
5000  return isolate->Throw(*error);
5001  }
5002 
5003  // Check if the given key is an array index.
5004  uint32_t index;
5005  if (key->ToArrayIndex(&index)) {
5006  Handle<Object> result = GetElementOrCharAt(isolate, object, index);
5007  RETURN_IF_EMPTY_HANDLE(isolate, result);
5008  return *result;
5009  }
5010 
5011  // Convert the key to a name - possibly by calling back into JavaScript.
5012  Handle<Name> name = ToName(isolate, key);
5013  RETURN_IF_EMPTY_HANDLE(isolate, name);
5014 
5015  // Check if the name is trivially convertible to an index and get
5016  // the element if so.
5017  if (name->AsArrayIndex(&index)) {
5018  Handle<Object> result = GetElementOrCharAt(isolate, object, index);
5019  RETURN_IF_EMPTY_HANDLE(isolate, result);
5020  return *result;
5021  } else {
5022  return object->GetProperty(*name);
5023  }
5024 }
5025 
5026 
5027 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetProperty) {
5028  SealHandleScope shs(isolate);
5029  ASSERT(args.length() == 2);
5030 
5031  Handle<Object> object = args.at<Object>(0);
5032  Handle<Object> key = args.at<Object>(1);
5033 
5034  return Runtime::GetObjectProperty(isolate, object, key);
5035 }
5036 
5037 
5038 // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
5039 RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
5040  SealHandleScope shs(isolate);
5041  ASSERT(args.length() == 2);
5042 
5043  // Fast cases for getting named properties of the receiver JSObject
5044  // itself.
5045  //
5046  // The global proxy objects has to be excluded since LocalLookup on
5047  // the global proxy object can return a valid result even though the
5048  // global proxy object never has properties. This is the case
5049  // because the global proxy object forwards everything to its hidden
5050  // prototype including local lookups.
5051  //
5052  // Additionally, we need to make sure that we do not cache results
5053  // for objects that require access checks.
5054  if (args[0]->IsJSObject()) {
5055  if (!args[0]->IsJSGlobalProxy() &&
5056  !args[0]->IsAccessCheckNeeded() &&
5057  args[1]->IsName()) {
5058  JSObject* receiver = JSObject::cast(args[0]);
5059  Name* key = Name::cast(args[1]);
5060  if (receiver->HasFastProperties()) {
5061  // Attempt to use lookup cache.
5062  Map* receiver_map = receiver->map();
5063  KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache();
5064  int offset = keyed_lookup_cache->Lookup(receiver_map, key);
5065  if (offset != -1) {
5066  // Doubles are not cached, so raw read the value.
5067  Object* value = receiver->RawFastPropertyAt(offset);
5068  return value->IsTheHole()
5069  ? isolate->heap()->undefined_value()
5070  : value;
5071  }
5072  // Lookup cache miss. Perform lookup and update the cache if
5073  // appropriate.
5074  LookupResult result(isolate);
5075  receiver->LocalLookup(key, &result);
5076  if (result.IsField()) {
5077  int offset = result.GetFieldIndex().field_index();
5078  // Do not track double fields in the keyed lookup cache. Reading
5079  // double values requires boxing.
5080  if (!result.representation().IsDouble()) {
5081  keyed_lookup_cache->Update(receiver_map, key, offset);
5082  }
5083  return receiver->FastPropertyAt(result.representation(), offset);
5084  }
5085  } else {
5086  // Attempt dictionary lookup.
5087  NameDictionary* dictionary = receiver->property_dictionary();
5088  int entry = dictionary->FindEntry(key);
5089  if ((entry != NameDictionary::kNotFound) &&
5090  (dictionary->DetailsAt(entry).type() == NORMAL)) {
5091  Object* value = dictionary->ValueAt(entry);
5092  if (!receiver->IsGlobalObject()) return value;
5093  value = PropertyCell::cast(value)->value();
5094  if (!value->IsTheHole()) return value;
5095  // If value is the hole do the general lookup.
5096  }
5097  }
5098  } else if (FLAG_smi_only_arrays && args.at<Object>(1)->IsSmi()) {
5099  // JSObject without a name key. If the key is a Smi, check for a
5100  // definite out-of-bounds access to elements, which is a strong indicator
5101  // that subsequent accesses will also call the runtime. Proactively
5102  // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
5103  // doubles for those future calls in the case that the elements would
5104  // become FAST_DOUBLE_ELEMENTS.
5105  Handle<JSObject> js_object(args.at<JSObject>(0));
5106  ElementsKind elements_kind = js_object->GetElementsKind();
5107  if (IsFastDoubleElementsKind(elements_kind)) {
5108  FixedArrayBase* elements = js_object->elements();
5109  if (args.at<Smi>(1)->value() >= elements->length()) {
5110  if (IsFastHoleyElementsKind(elements_kind)) {
5111  elements_kind = FAST_HOLEY_ELEMENTS;
5112  } else {
5113  elements_kind = FAST_ELEMENTS;
5114  }
5115  MaybeObject* maybe_object = TransitionElements(js_object,
5116  elements_kind,
5117  isolate);
5118  if (maybe_object->IsFailure()) return maybe_object;
5119  }
5120  } else {
5121  ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) ||
5122  !IsFastElementsKind(elements_kind));
5123  }
5124  }
5125  } else if (args[0]->IsString() && args[1]->IsSmi()) {
5126  // Fast case for string indexing using [] with a smi index.
5127  HandleScope scope(isolate);
5128  Handle<String> str = args.at<String>(0);
5129  int index = args.smi_at(1);
5130  if (index >= 0 && index < str->length()) {
5131  Handle<Object> result = GetCharAt(str, index);
5132  return *result;
5133  }
5134  }
5135 
5136  // Fall back to GetObjectProperty.
5137  return Runtime::GetObjectProperty(isolate,
5138  args.at<Object>(0),
5139  args.at<Object>(1));
5140 }
5141 
5142 
5143 static bool IsValidAccessor(Handle<Object> obj) {
5144  return obj->IsUndefined() || obj->IsSpecFunction() || obj->IsNull();
5145 }
5146 
5147 
5148 // Implements part of 8.12.9 DefineOwnProperty.
5149 // There are 3 cases that lead here:
5150 // Step 4b - define a new accessor property.
5151 // Steps 9c & 12 - replace an existing data property with an accessor property.
5152 // Step 12 - update an existing accessor property with an accessor or generic
5153 // descriptor.
5154 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) {
5155  HandleScope scope(isolate);
5156  ASSERT(args.length() == 5);
5158  RUNTIME_ASSERT(!obj->IsNull());
5159  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
5160  CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
5161  RUNTIME_ASSERT(IsValidAccessor(getter));
5162  CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
5163  RUNTIME_ASSERT(IsValidAccessor(setter));
5164  CONVERT_SMI_ARG_CHECKED(unchecked, 4);
5165  RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5166  PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
5167 
5168  bool fast = obj->HasFastProperties();
5169  JSObject::DefineAccessor(obj, name, getter, setter, attr);
5171  if (fast) JSObject::TransformToFastProperties(obj, 0);
5172  return isolate->heap()->undefined_value();
5173 }
5174 
5175 
5176 // Implements part of 8.12.9 DefineOwnProperty.
5177 // There are 3 cases that lead here:
5178 // Step 4a - define a new data property.
5179 // Steps 9b & 12 - replace an existing accessor property with a data property.
5180 // Step 12 - update an existing data property with a data or generic
5181 // descriptor.
5182 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
5183  HandleScope scope(isolate);
5184  ASSERT(args.length() == 4);
5185  CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
5186  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
5187  CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2);
5188  CONVERT_SMI_ARG_CHECKED(unchecked, 3);
5189  RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5190  PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
5191 
5192  LookupResult lookup(isolate);
5193  js_object->LocalLookupRealNamedProperty(*name, &lookup);
5194 
5195  // Special case for callback properties.
5196  if (lookup.IsPropertyCallbacks()) {
5197  Handle<Object> callback(lookup.GetCallbackObject(), isolate);
5198  // To be compatible with Safari we do not change the value on API objects
5199  // in Object.defineProperty(). Firefox disagrees here, and actually changes
5200  // the value.
5201  if (callback->IsAccessorInfo()) {
5202  return isolate->heap()->undefined_value();
5203  }
5204  // Avoid redefining foreign callback as data property, just use the stored
5205  // setter to update the value instead.
5206  // TODO(mstarzinger): So far this only works if property attributes don't
5207  // change, this should be fixed once we cleanup the underlying code.
5208  if (callback->IsForeign() && lookup.GetAttributes() == attr) {
5209  Handle<Object> result_object =
5211  callback,
5212  name,
5213  obj_value,
5214  handle(lookup.holder()),
5215  STRICT);
5216  RETURN_IF_EMPTY_HANDLE(isolate, result_object);
5217  return *result_object;
5218  }
5219  }
5220 
5221  // Take special care when attributes are different and there is already
5222  // a property. For simplicity we normalize the property which enables us
5223  // to not worry about changing the instance_descriptor and creating a new
5224  // map. The current version of SetObjectProperty does not handle attributes
5225  // correctly in the case where a property is a field and is reset with
5226  // new attributes.
5227  if (lookup.IsFound() &&
5228  (attr != lookup.GetAttributes() || lookup.IsPropertyCallbacks())) {
5229  // New attributes - normalize to avoid writing to instance descriptor
5230  if (js_object->IsJSGlobalProxy()) {
5231  // Since the result is a property, the prototype will exist so
5232  // we don't have to check for null.
5233  js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype()));
5234  }
5236  // Use IgnoreAttributes version since a readonly property may be
5237  // overridden and SetProperty does not allow this.
5239  js_object, name, obj_value, attr);
5240  RETURN_IF_EMPTY_HANDLE(isolate, result);
5241  return *result;
5242  }
5243 
5244  Handle<Object> result = Runtime::ForceSetObjectProperty(isolate, js_object,
5245  name,
5246  obj_value,
5247  attr);
5248  RETURN_IF_EMPTY_HANDLE(isolate, result);
5249  return *result;
5250 }
5251 
5252 
5253 // Return property without being observable by accessors or interceptors.
5254 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDataProperty) {
5255  SealHandleScope shs(isolate);
5256  ASSERT(args.length() == 2);
5259  LookupResult lookup(isolate);
5260  object->LookupRealNamedProperty(*key, &lookup);
5261  if (!lookup.IsFound()) return isolate->heap()->undefined_value();
5262  switch (lookup.type()) {
5263  case NORMAL:
5264  return lookup.holder()->GetNormalizedProperty(&lookup);
5265  case FIELD:
5266  return lookup.holder()->FastPropertyAt(
5267  lookup.representation(),
5268  lookup.GetFieldIndex().field_index());
5269  case CONSTANT:
5270  return lookup.GetConstant();
5271  case CALLBACKS:
5272  case HANDLER:
5273  case INTERCEPTOR:
5274  case TRANSITION:
5275  return isolate->heap()->undefined_value();
5276  case NONEXISTENT:
5277  UNREACHABLE();
5278  }
5279  return isolate->heap()->undefined_value();
5280 }
5281 
5282 
5284  Handle<Object> object,
5285  Handle<Object> key,
5286  Handle<Object> value,
5287  PropertyAttributes attr,
5288  StrictMode strict_mode) {
5289  SetPropertyMode set_mode = attr == NONE ? SET_PROPERTY : DEFINE_PROPERTY;
5290 
5291  if (object->IsUndefined() || object->IsNull()) {
5292  Handle<Object> args[2] = { key, object };
5293  Handle<Object> error =
5294  isolate->factory()->NewTypeError("non_object_property_store",
5295  HandleVector(args, 2));
5296  isolate->Throw(*error);
5297  return Handle<Object>();
5298  }
5299 
5300  if (object->IsJSProxy()) {
5301  bool has_pending_exception = false;
5302  Handle<Object> name_object = key->IsSymbol()
5303  ? key : Execution::ToString(isolate, key, &has_pending_exception);
5304  if (has_pending_exception) return Handle<Object>(); // exception
5305  Handle<Name> name = Handle<Name>::cast(name_object);
5306  return JSReceiver::SetProperty(Handle<JSProxy>::cast(object), name, value,
5307  attr,
5308  strict_mode);
5309  }
5310 
5311  // If the object isn't a JavaScript object, we ignore the store.
5312  if (!object->IsJSObject()) return value;
5313 
5314  Handle<JSObject> js_object = Handle<JSObject>::cast(object);
5315 
5316  // Check if the given key is an array index.
5317  uint32_t index;
5318  if (key->ToArrayIndex(&index)) {
5319  // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
5320  // of a string using [] notation. We need to support this too in
5321  // JavaScript.
5322  // In the case of a String object we just need to redirect the assignment to
5323  // the underlying string if the index is in range. Since the underlying
5324  // string does nothing with the assignment then we can ignore such
5325  // assignments.
5326  if (js_object->IsStringObjectWithCharacterAt(index)) {
5327  return value;
5328  }
5329 
5330  js_object->ValidateElements();
5331  if (js_object->HasExternalArrayElements() ||
5332  js_object->HasFixedTypedArrayElements()) {
5333  if (!value->IsNumber() && !value->IsUndefined()) {
5334  bool has_exception;
5335  Handle<Object> number =
5336  Execution::ToNumber(isolate, value, &has_exception);
5337  if (has_exception) return Handle<Object>(); // exception
5338  value = number;
5339  }
5340  }
5341  Handle<Object> result = JSObject::SetElement(js_object, index, value, attr,
5342  strict_mode,
5343  true,
5344  set_mode);
5345  js_object->ValidateElements();
5346  return result.is_null() ? result : value;
5347  }
5348 
5349  if (key->IsName()) {
5350  Handle<Name> name = Handle<Name>::cast(key);
5351  if (name->AsArrayIndex(&index)) {
5352  if (js_object->HasExternalArrayElements()) {
5353  if (!value->IsNumber() && !value->IsUndefined()) {
5354  bool has_exception;
5355  Handle<Object> number =
5356  Execution::ToNumber(isolate, value, &has_exception);
5357  if (has_exception) return Handle<Object>(); // exception
5358  value = number;
5359  }
5360  }
5361  return JSObject::SetElement(js_object, index, value, attr, strict_mode,
5362  true,
5363  set_mode);
5364  } else {
5365  if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
5366  return JSReceiver::SetProperty(js_object, name, value, attr, strict_mode);
5367  }
5368  }
5369 
5370  // Call-back into JavaScript to convert the key to a string.
5371  bool has_pending_exception = false;
5372  Handle<Object> converted =
5373  Execution::ToString(isolate, key, &has_pending_exception);
5374  if (has_pending_exception) return Handle<Object>(); // exception
5375  Handle<String> name = Handle<String>::cast(converted);
5376 
5377  if (name->AsArrayIndex(&index)) {
5378  return JSObject::SetElement(js_object, index, value, attr, strict_mode,
5379  true,
5380  set_mode);
5381  } else {
5382  return JSReceiver::SetProperty(js_object, name, value, attr, strict_mode);
5383  }
5384 }
5385 
5386 
5388  Handle<JSObject> js_object,
5389  Handle<Object> key,
5390  Handle<Object> value,
5391  PropertyAttributes attr) {
5392  // Check if the given key is an array index.
5393  uint32_t index;
5394  if (key->ToArrayIndex(&index)) {
5395  // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
5396  // of a string using [] notation. We need to support this too in
5397  // JavaScript.
5398  // In the case of a String object we just need to redirect the assignment to
5399  // the underlying string if the index is in range. Since the underlying
5400  // string does nothing with the assignment then we can ignore such
5401  // assignments.
5402  if (js_object->IsStringObjectWithCharacterAt(index)) {
5403  return value;
5404  }
5405 
5406  return JSObject::SetElement(js_object, index, value, attr, SLOPPY,
5407  false,
5408  DEFINE_PROPERTY);
5409  }
5410 
5411  if (key->IsName()) {
5412  Handle<Name> name = Handle<Name>::cast(key);
5413  if (name->AsArrayIndex(&index)) {
5414  return JSObject::SetElement(js_object, index, value, attr, SLOPPY,
5415  false,
5416  DEFINE_PROPERTY);
5417  } else {
5418  if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
5419  return JSObject::SetLocalPropertyIgnoreAttributes(js_object, name,
5420  value, attr);
5421  }
5422  }
5423 
5424  // Call-back into JavaScript to convert the key to a string.
5425  bool has_pending_exception = false;
5426  Handle<Object> converted =
5427  Execution::ToString(isolate, key, &has_pending_exception);
5428  if (has_pending_exception) return Handle<Object>(); // exception
5429  Handle<String> name = Handle<String>::cast(converted);
5430 
5431  if (name->AsArrayIndex(&index)) {
5432  return JSObject::SetElement(js_object, index, value, attr, SLOPPY,
5433  false,
5434  DEFINE_PROPERTY);
5435  } else {
5436  return JSObject::SetLocalPropertyIgnoreAttributes(js_object, name, value,
5437  attr);
5438  }
5439 }
5440 
5441 
5443  Handle<JSReceiver> receiver,
5444  Handle<Object> key,
5445  JSReceiver::DeleteMode mode) {
5446  HandleScope scope(isolate);
5447 
5448  // Check if the given key is an array index.
5449  uint32_t index;
5450  if (key->ToArrayIndex(&index)) {
5451  // In Firefox/SpiderMonkey, Safari and Opera you can access the
5452  // characters of a string using [] notation. In the case of a
5453  // String object we just need to redirect the deletion to the
5454  // underlying string if the index is in range. Since the
5455  // underlying string does nothing with the deletion, we can ignore
5456  // such deletions.
5457  if (receiver->IsStringObjectWithCharacterAt(index)) {
5458  return isolate->heap()->true_value();
5459  }
5460 
5461  Handle<Object> result = JSReceiver::DeleteElement(receiver, index, mode);
5462  RETURN_IF_EMPTY_HANDLE(isolate, result);
5463  return *result;
5464  }
5465 
5467  if (key->IsName()) {
5468  name = Handle<Name>::cast(key);
5469  } else {
5470  // Call-back into JavaScript to convert the key to a string.
5471  bool has_pending_exception = false;
5472  Handle<Object> converted = Execution::ToString(
5473  isolate, key, &has_pending_exception);
5474  if (has_pending_exception) return Failure::Exception();
5475  name = Handle<String>::cast(converted);
5476  }
5477 
5478  if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
5479  Handle<Object> result = JSReceiver::DeleteProperty(receiver, name, mode);
5480  RETURN_IF_EMPTY_HANDLE(isolate, result);
5481  return *result;
5482 }
5483 
5484 
5485 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetHiddenProperty) {
5486  HandleScope scope(isolate);
5487  RUNTIME_ASSERT(args.length() == 3);
5488 
5492  return *JSObject::SetHiddenProperty(object, key, value);
5493 }
5494 
5495 
5496 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) {
5497  HandleScope scope(isolate);
5498  RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
5499 
5500  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
5503  CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3);
5505  (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5506  // Compute attributes.
5507  PropertyAttributes attributes =
5508  static_cast<PropertyAttributes>(unchecked_attributes);
5509 
5510  StrictMode strict_mode = SLOPPY;
5511  if (args.length() == 5) {
5512  CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode_arg, 4);
5513  strict_mode = strict_mode_arg;
5514  }
5515 
5516  Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key,
5517  value,
5518  attributes,
5519  strict_mode);
5520  RETURN_IF_EMPTY_HANDLE(isolate, result);
5521  return *result;
5522 }
5523 
5524 
5525 RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsKind) {
5526  HandleScope scope(isolate);
5527  RUNTIME_ASSERT(args.length() == 2);
5530  JSObject::TransitionElementsKind(array, map->elements_kind());
5531  return *array;
5532 }
5533 
5534 
5535 // Set the native flag on the function.
5536 // This is used to decide if we should transform null and undefined
5537 // into the global object when doing call and apply.
5538 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) {
5539  SealHandleScope shs(isolate);
5540  RUNTIME_ASSERT(args.length() == 1);
5541 
5542  CONVERT_ARG_CHECKED(Object, object, 0);
5543 
5544  if (object->IsJSFunction()) {
5545  JSFunction* func = JSFunction::cast(object);
5546  func->shared()->set_native(true);
5547  }
5548  return isolate->heap()->undefined_value();
5549 }
5550 
5551 
5552 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInlineBuiltinFlag) {
5553  SealHandleScope shs(isolate);
5554  RUNTIME_ASSERT(args.length() == 1);
5555 
5556  Handle<Object> object = args.at<Object>(0);
5557 
5558  if (object->IsJSFunction()) {
5559  JSFunction* func = JSFunction::cast(*object);
5560  func->shared()->set_inline_builtin(true);
5561  }
5562  return isolate->heap()->undefined_value();
5563 }
5564 
5565 
5566 RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) {
5567  HandleScope scope(isolate);
5568  RUNTIME_ASSERT(args.length() == 5);
5570  CONVERT_SMI_ARG_CHECKED(store_index, 1);
5571  Handle<Object> value = args.at<Object>(2);
5572  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 3);
5573  CONVERT_SMI_ARG_CHECKED(literal_index, 4);
5574 
5575  Object* raw_literal_cell = literals->get(literal_index);
5576  JSArray* boilerplate = NULL;
5577  if (raw_literal_cell->IsAllocationSite()) {
5578  AllocationSite* site = AllocationSite::cast(raw_literal_cell);
5579  boilerplate = JSArray::cast(site->transition_info());
5580  } else {
5581  boilerplate = JSArray::cast(raw_literal_cell);
5582  }
5583  Handle<JSArray> boilerplate_object(boilerplate);
5584  ElementsKind elements_kind = object->GetElementsKind();
5585  ASSERT(IsFastElementsKind(elements_kind));
5586  // Smis should never trigger transitions.
5587  ASSERT(!value->IsSmi());
5588 
5589  if (value->IsNumber()) {
5590  ASSERT(IsFastSmiElementsKind(elements_kind));
5591  ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
5595  boilerplate_object->GetElementsKind(),
5596  transitioned_kind)) {
5597  JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
5598  }
5599  JSObject::TransitionElementsKind(object, transitioned_kind);
5600  ASSERT(IsFastDoubleElementsKind(object->GetElementsKind()));
5601  FixedDoubleArray* double_array = FixedDoubleArray::cast(object->elements());
5602  HeapNumber* number = HeapNumber::cast(*value);
5603  double_array->set(store_index, number->Number());
5604  } else {
5605  ASSERT(IsFastSmiElementsKind(elements_kind) ||
5606  IsFastDoubleElementsKind(elements_kind));
5607  ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
5609  : FAST_ELEMENTS;
5610  JSObject::TransitionElementsKind(object, transitioned_kind);
5612  boilerplate_object->GetElementsKind(),
5613  transitioned_kind)) {
5614  JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
5615  }
5616  FixedArray* object_array = FixedArray::cast(object->elements());
5617  object_array->set(store_index, *value);
5618  }
5619  return *object;
5620 }
5621 
5622 
5623 // Check whether debugger and is about to step into the callback that is passed
5624 // to a built-in function such as Array.forEach.
5625 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugCallbackSupportsStepping) {
5626  SealHandleScope shs(isolate);
5627 #ifdef ENABLE_DEBUGGER_SUPPORT
5628  if (!isolate->IsDebuggerActive() || !isolate->debug()->StepInActive()) {
5629  return isolate->heap()->false_value();
5630  }
5631  CONVERT_ARG_CHECKED(Object, callback, 0);
5632  // We do not step into the callback if it's a builtin or not even a function.
5633  if (!callback->IsJSFunction() || JSFunction::cast(callback)->IsBuiltin()) {
5634  return isolate->heap()->false_value();
5635  }
5636  return isolate->heap()->true_value();
5637 #else
5638  return isolate->heap()->false_value();
5639 #endif // ENABLE_DEBUGGER_SUPPORT
5640 }
5641 
5642 
5643 // Set one shot breakpoints for the callback function that is passed to a
5644 // built-in function such as Array.forEach to enable stepping into the callback.
5645 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrepareStepInIfStepping) {
5646  SealHandleScope shs(isolate);
5647 #ifdef ENABLE_DEBUGGER_SUPPORT
5648  Debug* debug = isolate->debug();
5649  if (!debug->IsStepping()) return isolate->heap()->undefined_value();
5650  CONVERT_ARG_HANDLE_CHECKED(JSFunction, callback, 0);
5651  HandleScope scope(isolate);
5652  // When leaving the callback, step out has been activated, but not performed
5653  // if we do not leave the builtin. To be able to step into the callback
5654  // again, we need to clear the step out at this point.
5655  debug->ClearStepOut();
5656  debug->FloodWithOneShot(callback);
5657 #endif // ENABLE_DEBUGGER_SUPPORT
5658  return isolate->heap()->undefined_value();
5659 }
5660 
5661 
5662 // Set a local property, even if it is READ_ONLY. If the property does not
5663 // exist, it will be added with attributes NONE.
5664 RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) {
5665  HandleScope scope(isolate);
5666  RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
5668  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
5670  // Compute attributes.
5671  PropertyAttributes attributes = NONE;
5672  if (args.length() == 4) {
5673  CONVERT_SMI_ARG_CHECKED(unchecked_value, 3);
5674  // Only attribute bits should be set.
5676  (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5677  attributes = static_cast<PropertyAttributes>(unchecked_value);
5678  }
5680  object, name, value, attributes);
5681  RETURN_IF_EMPTY_HANDLE(isolate, result);
5682  return *result;
5683 }
5684 
5685 
5686 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteProperty) {
5687  HandleScope scope(isolate);
5688  ASSERT(args.length() == 3);
5691  CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2);
5692  JSReceiver::DeleteMode delete_mode = strict_mode == STRICT
5694  Handle<Object> result = JSReceiver::DeleteProperty(object, key, delete_mode);
5695  RETURN_IF_EMPTY_HANDLE(isolate, result);
5696  return *result;
5697 }
5698 
5699 
5700 static MaybeObject* HasLocalPropertyImplementation(Isolate* isolate,
5701  Handle<JSObject> object,
5702  Handle<Name> key) {
5703  if (JSReceiver::HasLocalProperty(object, key)) {
5704  return isolate->heap()->true_value();
5705  }
5706  // Handle hidden prototypes. If there's a hidden prototype above this thing
5707  // then we have to check it for properties, because they are supposed to
5708  // look like they are on this object.
5709  Handle<Object> proto(object->GetPrototype(), isolate);
5710  if (proto->IsJSObject() &&
5711  Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) {
5712  return HasLocalPropertyImplementation(isolate,
5713  Handle<JSObject>::cast(proto),
5714  key);
5715  }
5717  return isolate->heap()->false_value();
5718 }
5719 
5720 
5721 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) {
5722  HandleScope scope(isolate);
5723  ASSERT(args.length() == 2);
5725  Handle<Object> object = args.at<Object>(0);
5726 
5727  uint32_t index;
5728  const bool key_is_array_index = key->AsArrayIndex(&index);
5729 
5730  // Only JS objects can have properties.
5731  if (object->IsJSObject()) {
5732  Handle<JSObject> js_obj = Handle<JSObject>::cast(object);
5733  // Fast case: either the key is a real named property or it is not
5734  // an array index and there are no interceptors or hidden
5735  // prototypes.
5736  if (JSObject::HasRealNamedProperty(js_obj, key)) {
5737  ASSERT(!isolate->has_scheduled_exception());
5738  return isolate->heap()->true_value();
5739  } else {
5741  }
5742  Map* map = js_obj->map();
5743  if (!key_is_array_index &&
5744  !map->has_named_interceptor() &&
5745  !HeapObject::cast(map->prototype())->map()->is_hidden_prototype()) {
5746  return isolate->heap()->false_value();
5747  }
5748  // Slow case.
5749  return HasLocalPropertyImplementation(isolate,
5750  Handle<JSObject>(js_obj),
5751  Handle<Name>(key));
5752  } else if (object->IsString() && key_is_array_index) {
5753  // Well, there is one exception: Handle [] on strings.
5754  Handle<String> string = Handle<String>::cast(object);
5755  if (index < static_cast<uint32_t>(string->length())) {
5756  return isolate->heap()->true_value();
5757  }
5758  }
5759  return isolate->heap()->false_value();
5760 }
5761 
5762 
5763 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) {
5764  HandleScope scope(isolate);
5765  ASSERT(args.length() == 2);
5766  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
5768 
5769  bool result = JSReceiver::HasProperty(receiver, key);
5771  if (isolate->has_pending_exception()) return Failure::Exception();
5772  return isolate->heap()->ToBoolean(result);
5773 }
5774 
5775 
5776 RUNTIME_FUNCTION(MaybeObject*, Runtime_HasElement) {
5777  HandleScope scope(isolate);
5778  ASSERT(args.length() == 2);
5779  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
5780  CONVERT_SMI_ARG_CHECKED(index, 1);
5781 
5782  bool result = JSReceiver::HasElement(receiver, index);
5784  if (isolate->has_pending_exception()) return Failure::Exception();
5785  return isolate->heap()->ToBoolean(result);
5786 }
5787 
5788 
5789 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) {
5790  HandleScope scope(isolate);
5791  ASSERT(args.length() == 2);
5792 
5795 
5797  if (att == ABSENT || (att & DONT_ENUM) != 0) {
5799  return isolate->heap()->false_value();
5800  }
5801  ASSERT(!isolate->has_scheduled_exception());
5802  return isolate->heap()->true_value();
5803 }
5804 
5805 
5806 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNames) {
5807  HandleScope scope(isolate);
5808  ASSERT(args.length() == 1);
5810  bool threw = false;
5811  Handle<JSArray> result = GetKeysFor(object, &threw);
5812  if (threw) return Failure::Exception();
5813  return *result;
5814 }
5815 
5816 
5817 // Returns either a FixedArray as Runtime_GetPropertyNames,
5818 // or, if the given object has an enum cache that contains
5819 // all enumerable properties of the object and its prototypes
5820 // have none, the map of the object. This is used to speed up
5821 // the check for deletions during a for-in.
5822 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNamesFast) {
5823  SealHandleScope shs(isolate);
5824  ASSERT(args.length() == 1);
5825 
5826  CONVERT_ARG_CHECKED(JSReceiver, raw_object, 0);
5827 
5828  if (raw_object->IsSimpleEnum()) return raw_object->map();
5829 
5830  HandleScope scope(isolate);
5831  Handle<JSReceiver> object(raw_object);
5832  bool threw = false;
5833  Handle<FixedArray> content =
5834  GetKeysInFixedArrayFor(object, INCLUDE_PROTOS, &threw);
5835  if (threw) return Failure::Exception();
5836 
5837  // Test again, since cache may have been built by preceding call.
5838  if (object->IsSimpleEnum()) return object->map();
5839 
5840  return *content;
5841 }
5842 
5843 
5844 // Find the length of the prototype chain that is to to handled as one. If a
5845 // prototype object is hidden it is to be viewed as part of the the object it
5846 // is prototype for.
5847 static int LocalPrototypeChainLength(JSObject* obj) {
5848  int count = 1;
5849  Object* proto = obj->GetPrototype();
5850  while (proto->IsJSObject() &&
5851  JSObject::cast(proto)->map()->is_hidden_prototype()) {
5852  count++;
5853  proto = JSObject::cast(proto)->GetPrototype();
5854  }
5855  return count;
5856 }
5857 
5858 
5859 // Return the names of the local named properties.
5860 // args[0]: object
5861 // args[1]: PropertyAttributes as int
5862 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) {
5863  HandleScope scope(isolate);
5864  ASSERT(args.length() == 2);
5865  if (!args[0]->IsJSObject()) {
5866  return isolate->heap()->undefined_value();
5867  }
5869  CONVERT_SMI_ARG_CHECKED(filter_value, 1);
5870  PropertyAttributes filter = static_cast<PropertyAttributes>(filter_value);
5871 
5872  // Skip the global proxy as it has no properties and always delegates to the
5873  // real global object.
5874  if (obj->IsJSGlobalProxy()) {
5875  // Only collect names if access is permitted.
5876  if (obj->IsAccessCheckNeeded() &&
5877  !isolate->MayNamedAccessWrapper(obj,
5878  isolate->factory()->undefined_value(),
5879  v8::ACCESS_KEYS)) {
5880  isolate->ReportFailedAccessCheckWrapper(obj, v8::ACCESS_KEYS);
5882  return *isolate->factory()->NewJSArray(0);
5883  }
5884  obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
5885  }
5886 
5887  // Find the number of objects making up this.
5888  int length = LocalPrototypeChainLength(*obj);
5889 
5890  // Find the number of local properties for each of the objects.
5891  ScopedVector<int> local_property_count(length);
5892  int total_property_count = 0;
5893  Handle<JSObject> jsproto = obj;
5894  for (int i = 0; i < length; i++) {
5895  // Only collect names if access is permitted.
5896  if (jsproto->IsAccessCheckNeeded() &&
5897  !isolate->MayNamedAccessWrapper(jsproto,
5898  isolate->factory()->undefined_value(),
5899  v8::ACCESS_KEYS)) {
5900  isolate->ReportFailedAccessCheckWrapper(jsproto, v8::ACCESS_KEYS);
5902  return *isolate->factory()->NewJSArray(0);
5903  }
5904  int n;
5905  n = jsproto->NumberOfLocalProperties(filter);
5906  local_property_count[i] = n;
5907  total_property_count += n;
5908  if (i < length - 1) {
5909  jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
5910  }
5911  }
5912 
5913  // Allocate an array with storage for all the property names.
5914  Handle<FixedArray> names =
5915  isolate->factory()->NewFixedArray(total_property_count);
5916 
5917  // Get the property names.
5918  jsproto = obj;
5919  int next_copy_index = 0;
5920  int hidden_strings = 0;
5921  for (int i = 0; i < length; i++) {
5922  jsproto->GetLocalPropertyNames(*names, next_copy_index, filter);
5923  if (i > 0) {
5924  // Names from hidden prototypes may already have been added
5925  // for inherited function template instances. Count the duplicates
5926  // and stub them out; the final copy pass at the end ignores holes.
5927  for (int j = next_copy_index;
5928  j < next_copy_index + local_property_count[i];
5929  j++) {
5930  Object* name_from_hidden_proto = names->get(j);
5931  for (int k = 0; k < next_copy_index; k++) {
5932  if (names->get(k) != isolate->heap()->hidden_string()) {
5933  Object* name = names->get(k);
5934  if (name_from_hidden_proto == name) {
5935  names->set(j, isolate->heap()->hidden_string());
5936  hidden_strings++;
5937  break;
5938  }
5939  }
5940  }
5941  }
5942  }
5943  next_copy_index += local_property_count[i];
5944 
5945  // Hidden properties only show up if the filter does not skip strings.
5946  if ((filter & STRING) == 0 && JSObject::HasHiddenProperties(jsproto)) {
5947  hidden_strings++;
5948  }
5949  if (i < length - 1) {
5950  jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
5951  }
5952  }
5953 
5954  // Filter out name of hidden properties object and
5955  // hidden prototype duplicates.
5956  if (hidden_strings > 0) {
5957  Handle<FixedArray> old_names = names;
5958  names = isolate->factory()->NewFixedArray(
5959  names->length() - hidden_strings);
5960  int dest_pos = 0;
5961  for (int i = 0; i < total_property_count; i++) {
5962  Object* name = old_names->get(i);
5963  if (name == isolate->heap()->hidden_string()) {
5964  hidden_strings--;
5965  continue;
5966  }
5967  names->set(dest_pos++, name);
5968  }
5969  ASSERT_EQ(0, hidden_strings);
5970  }
5971 
5972  return *isolate->factory()->NewJSArrayWithElements(names);
5973 }
5974 
5975 
5976 // Return the names of the local indexed properties.
5977 // args[0]: object
5978 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalElementNames) {
5979  HandleScope scope(isolate);
5980  ASSERT(args.length() == 1);
5981  if (!args[0]->IsJSObject()) {
5982  return isolate->heap()->undefined_value();
5983  }
5985 
5986  int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
5987  Handle<FixedArray> names = isolate->factory()->NewFixedArray(n);
5988  obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
5989  return *isolate->factory()->NewJSArrayWithElements(names);
5990 }
5991 
5992 
5993 // Return information on whether an object has a named or indexed interceptor.
5994 // args[0]: object
5995 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetInterceptorInfo) {
5996  HandleScope scope(isolate);
5997  ASSERT(args.length() == 1);
5998  if (!args[0]->IsJSObject()) {
5999  return Smi::FromInt(0);
6000  }
6002 
6003  int result = 0;
6004  if (obj->HasNamedInterceptor()) result |= 2;
6005  if (obj->HasIndexedInterceptor()) result |= 1;
6006 
6007  return Smi::FromInt(result);
6008 }
6009 
6010 
6011 // Return property names from named interceptor.
6012 // args[0]: object
6013 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetNamedInterceptorPropertyNames) {
6014  HandleScope scope(isolate);
6015  ASSERT(args.length() == 1);
6017 
6018  if (obj->HasNamedInterceptor()) {
6020  if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
6021  }
6022  return isolate->heap()->undefined_value();
6023 }
6024 
6025 
6026 // Return element names from indexed interceptor.
6027 // args[0]: object
6028 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetIndexedInterceptorElementNames) {
6029  HandleScope scope(isolate);
6030  ASSERT(args.length() == 1);
6032 
6033  if (obj->HasIndexedInterceptor()) {
6035  if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
6036  }
6037  return isolate->heap()->undefined_value();
6038 }
6039 
6040 
6041 RUNTIME_FUNCTION(MaybeObject*, Runtime_LocalKeys) {
6042  HandleScope scope(isolate);
6043  ASSERT_EQ(args.length(), 1);
6044  CONVERT_ARG_CHECKED(JSObject, raw_object, 0);
6045  Handle<JSObject> object(raw_object);
6046 
6047  if (object->IsJSGlobalProxy()) {
6048  // Do access checks before going to the global object.
6049  if (object->IsAccessCheckNeeded() &&
6050  !isolate->MayNamedAccessWrapper(object,
6051  isolate->factory()->undefined_value(),
6052  v8::ACCESS_KEYS)) {
6053  isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_KEYS);
6055  return *isolate->factory()->NewJSArray(0);
6056  }
6057 
6058  Handle<Object> proto(object->GetPrototype(), isolate);
6059  // If proxy is detached we simply return an empty array.
6060  if (proto->IsNull()) return *isolate->factory()->NewJSArray(0);
6061  object = Handle<JSObject>::cast(proto);
6062  }
6063 
6064  bool threw = false;
6065  Handle<FixedArray> contents =
6066  GetKeysInFixedArrayFor(object, LOCAL_ONLY, &threw);
6067  if (threw) return Failure::Exception();
6068 
6069  // Some fast paths through GetKeysInFixedArrayFor reuse a cached
6070  // property array and since the result is mutable we have to create
6071  // a fresh clone on each invocation.
6072  int length = contents->length();
6073  Handle<FixedArray> copy = isolate->factory()->NewFixedArray(length);
6074  for (int i = 0; i < length; i++) {
6075  Object* entry = contents->get(i);
6076  if (entry->IsString()) {
6077  copy->set(i, entry);
6078  } else {
6079  ASSERT(entry->IsNumber());
6080  HandleScope scope(isolate);
6081  Handle<Object> entry_handle(entry, isolate);
6082  Handle<Object> entry_str =
6083  isolate->factory()->NumberToString(entry_handle);
6084  copy->set(i, *entry_str);
6085  }
6086  }
6087  return *isolate->factory()->NewJSArrayWithElements(copy);
6088 }
6089 
6090 
6091 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
6092  SealHandleScope shs(isolate);
6093  ASSERT(args.length() == 1);
6094 
6095  // Compute the frame holding the arguments.
6096  JavaScriptFrameIterator it(isolate);
6097  it.AdvanceToArgumentsFrame();
6098  JavaScriptFrame* frame = it.frame();
6099 
6100  // Get the actual number of provided arguments.
6101  const uint32_t n = frame->ComputeParametersCount();
6102 
6103  // Try to convert the key to an index. If successful and within
6104  // index return the the argument from the frame.
6105  uint32_t index;
6106  if (args[0]->ToArrayIndex(&index) && index < n) {
6107  return frame->GetParameter(index);
6108  }
6109 
6110  if (args[0]->IsSymbol()) {
6111  // Lookup in the initial Object.prototype object.
6112  return isolate->initial_object_prototype()->GetProperty(
6113  Symbol::cast(args[0]));
6114  }
6115 
6116  // Convert the key to a string.
6117  HandleScope scope(isolate);
6118  bool exception = false;
6119  Handle<Object> converted =
6120  Execution::ToString(isolate, args.at<Object>(0), &exception);
6121  if (exception) return Failure::Exception();
6122  Handle<String> key = Handle<String>::cast(converted);
6123 
6124  // Try to convert the string key into an array index.
6125  if (key->AsArrayIndex(&index)) {
6126  if (index < n) {
6127  return frame->GetParameter(index);
6128  } else {
6129  Handle<Object> initial_prototype(isolate->initial_object_prototype());
6130  Handle<Object> result =
6131  Object::GetElement(isolate, initial_prototype, index);
6132  RETURN_IF_EMPTY_HANDLE(isolate, result);
6133  return *result;
6134  }
6135  }
6136 
6137  // Handle special arguments properties.
6138  if (key->Equals(isolate->heap()->length_string())) return Smi::FromInt(n);
6139  if (key->Equals(isolate->heap()->callee_string())) {
6140  JSFunction* function = frame->function();
6141  if (function->shared()->strict_mode() == STRICT) {
6142  return isolate->Throw(*isolate->factory()->NewTypeError(
6143  "strict_arguments_callee", HandleVector<Object>(NULL, 0)));
6144  }
6145  return function;
6146  }
6147 
6148  // Lookup in the initial Object.prototype object.
6149  return isolate->initial_object_prototype()->GetProperty(*key);
6150 }
6151 
6152 
6153 RUNTIME_FUNCTION(MaybeObject*, Runtime_ToFastProperties) {
6154  HandleScope scope(isolate);
6155  ASSERT(args.length() == 1);
6156  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
6157  if (object->IsJSObject() && !object->IsGlobalObject()) {
6159  }
6160  return *object;
6161 }
6162 
6163 
6164 RUNTIME_FUNCTION(MaybeObject*, Runtime_ToBool) {
6165  SealHandleScope shs(isolate);
6166  ASSERT(args.length() == 1);
6167 
6168  return isolate->heap()->ToBoolean(args[0]->BooleanValue());
6169 }
6170 
6171 
6172 // Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
6173 // Possible optimizations: put the type string into the oddballs.
6174 RUNTIME_FUNCTION(MaybeObject*, Runtime_Typeof) {
6175  SealHandleScope shs(isolate);
6176 
6177  Object* obj = args[0];
6178  if (obj->IsNumber()) return isolate->heap()->number_string();
6179  HeapObject* heap_obj = HeapObject::cast(obj);
6180 
6181  // typeof an undetectable object is 'undefined'
6182  if (heap_obj->map()->is_undetectable()) {
6183  return isolate->heap()->undefined_string();
6184  }
6185 
6186  InstanceType instance_type = heap_obj->map()->instance_type();
6187  if (instance_type < FIRST_NONSTRING_TYPE) {
6188  return isolate->heap()->string_string();
6189  }
6190 
6191  switch (instance_type) {
6192  case ODDBALL_TYPE:
6193  if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
6194  return isolate->heap()->boolean_string();
6195  }
6196  if (heap_obj->IsNull()) {
6197  return FLAG_harmony_typeof
6198  ? isolate->heap()->null_string()
6199  : isolate->heap()->object_string();
6200  }
6201  ASSERT(heap_obj->IsUndefined());
6202  return isolate->heap()->undefined_string();
6203  case SYMBOL_TYPE:
6204  return isolate->heap()->symbol_string();
6205  case JS_FUNCTION_TYPE:
6207  return isolate->heap()->function_string();
6208  default:
6209  // For any kind of object not handled above, the spec rule for
6210  // host objects gives that it is okay to return "object"
6211  return isolate->heap()->object_string();
6212  }
6213 }
6214 
6215 
6216 static bool AreDigits(const uint8_t*s, int from, int to) {
6217  for (int i = from; i < to; i++) {
6218  if (s[i] < '0' || s[i] > '9') return false;
6219  }
6220 
6221  return true;
6222 }
6223 
6224 
6225 static int ParseDecimalInteger(const uint8_t*s, int from, int to) {
6226  ASSERT(to - from < 10); // Overflow is not possible.
6227  ASSERT(from < to);
6228  int d = s[from] - '0';
6229 
6230  for (int i = from + 1; i < to; i++) {
6231  d = 10 * d + (s[i] - '0');
6232  }
6233 
6234  return d;
6235 }
6236 
6237 
6238 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
6239  SealHandleScope shs(isolate);
6240  ASSERT(args.length() == 1);
6241  CONVERT_ARG_CHECKED(String, subject, 0);
6242  subject->TryFlatten();
6243 
6244  // Fast case: short integer or some sorts of junk values.
6245  int len = subject->length();
6246  if (subject->IsSeqOneByteString()) {
6247  if (len == 0) return Smi::FromInt(0);
6248 
6249  uint8_t const* data = SeqOneByteString::cast(subject)->GetChars();
6250  bool minus = (data[0] == '-');
6251  int start_pos = (minus ? 1 : 0);
6252 
6253  if (start_pos == len) {
6254  return isolate->heap()->nan_value();
6255  } else if (data[start_pos] > '9') {
6256  // Fast check for a junk value. A valid string may start from a
6257  // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit or
6258  // the 'I' character ('Infinity'). All of that have codes not greater than
6259  // '9' except 'I' and &nbsp;.
6260  if (data[start_pos] != 'I' && data[start_pos] != 0xa0) {
6261  return isolate->heap()->nan_value();
6262  }
6263  } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
6264  // The maximal/minimal smi has 10 digits. If the string has less digits we
6265  // know it will fit into the smi-data type.
6266  int d = ParseDecimalInteger(data, start_pos, len);
6267  if (minus) {
6268  if (d == 0) return isolate->heap()->minus_zero_value();
6269  d = -d;
6270  } else if (!subject->HasHashCode() &&
6271  len <= String::kMaxArrayIndexSize &&
6272  (len == 1 || data[0] != '0')) {
6273  // String hash is not calculated yet but all the data are present.
6274  // Update the hash field to speed up sequential convertions.
6275  uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
6276 #ifdef DEBUG
6277  subject->Hash(); // Force hash calculation.
6278  ASSERT_EQ(static_cast<int>(subject->hash_field()),
6279  static_cast<int>(hash));
6280 #endif
6281  subject->set_hash_field(hash);
6282  }
6283  return Smi::FromInt(d);
6284  }
6285  }
6286 
6287  // Slower case.
6288  int flags = ALLOW_HEX;
6289  if (FLAG_harmony_numeric_literals) {
6290  // The current spec draft has not updated "ToNumber Applied to the String
6291  // Type", https://bugs.ecmascript.org/show_bug.cgi?id=1584
6292  flags |= ALLOW_OCTAL | ALLOW_BINARY;
6293  }
6294  return isolate->heap()->NumberFromDouble(
6295  StringToDouble(isolate->unicode_cache(), subject, flags));
6296 }
6297 
6298 
6299 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewString) {
6300  SealHandleScope shs(isolate);
6301  CONVERT_SMI_ARG_CHECKED(length, 0);
6302  CONVERT_BOOLEAN_ARG_CHECKED(is_one_byte, 1);
6303  if (length == 0) return isolate->heap()->empty_string();
6304  if (is_one_byte) {
6305  return isolate->heap()->AllocateRawOneByteString(length);
6306  } else {
6307  return isolate->heap()->AllocateRawTwoByteString(length);
6308  }
6309 }
6310 
6311 
6312 RUNTIME_FUNCTION(MaybeObject*, Runtime_TruncateString) {
6313  HandleScope scope(isolate);
6315  CONVERT_SMI_ARG_CHECKED(new_length, 1);
6316  return *SeqString::Truncate(string, new_length);
6317 }
6318 
6319 
6320 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIEscape) {
6321  HandleScope scope(isolate);
6322  ASSERT(args.length() == 1);
6323  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
6324  Handle<String> string = FlattenGetString(source);
6325  ASSERT(string->IsFlat());
6326  Handle<String> result = string->IsOneByteRepresentationUnderneath()
6327  ? URIEscape::Escape<uint8_t>(isolate, source)
6328  : URIEscape::Escape<uc16>(isolate, source);
6329  RETURN_IF_EMPTY_HANDLE(isolate, result);
6330  return *result;
6331 }
6332 
6333 
6334 RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) {
6335  HandleScope scope(isolate);
6336  ASSERT(args.length() == 1);
6337  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
6338  Handle<String> string = FlattenGetString(source);
6339  ASSERT(string->IsFlat());
6340  return string->IsOneByteRepresentationUnderneath()
6341  ? *URIUnescape::Unescape<uint8_t>(isolate, source)
6342  : *URIUnescape::Unescape<uc16>(isolate, source);
6343 }
6344 
6345 
6346 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONString) {
6347  HandleScope scope(isolate);
6348  CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
6349  ASSERT(args.length() == 1);
6350  return BasicJsonStringifier::StringifyString(isolate, string);
6351 }
6352 
6353 
6354 RUNTIME_FUNCTION(MaybeObject*, Runtime_BasicJSONStringify) {
6355  HandleScope scope(isolate);
6356  ASSERT(args.length() == 1);
6357  BasicJsonStringifier stringifier(isolate);
6358  return stringifier.Stringify(Handle<Object>(args[0], isolate));
6359 }
6360 
6361 
6362 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) {
6363  SealHandleScope shs(isolate);
6364 
6365  CONVERT_ARG_CHECKED(String, s, 0);
6366  CONVERT_SMI_ARG_CHECKED(radix, 1);
6367 
6368  s->TryFlatten();
6369 
6370  RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
6371  double value = StringToInt(isolate->unicode_cache(), s, radix);
6372  return isolate->heap()->NumberFromDouble(value);
6373 }
6374 
6375 
6376 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) {
6377  SealHandleScope shs(isolate);
6378  CONVERT_ARG_CHECKED(String, str, 0);
6379 
6380  // ECMA-262 section 15.1.2.3, empty string is NaN
6381  double value = StringToDouble(isolate->unicode_cache(),
6383 
6384  // Create a number object from the value.
6385  return isolate->heap()->NumberFromDouble(value);
6386 }
6387 
6388 
6389 static inline bool ToUpperOverflows(uc32 character) {
6390  // y with umlauts and the micro sign are the only characters that stop
6391  // fitting into one-byte when converting to uppercase.
6392  static const uc32 yuml_code = 0xff;
6393  static const uc32 micro_code = 0xb5;
6394  return (character == yuml_code || character == micro_code);
6395 }
6396 
6397 
6398 template <class Converter>
6399 MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
6400  Isolate* isolate,
6401  String* string,
6402  SeqString* result,
6403  int result_length,
6405  DisallowHeapAllocation no_gc;
6406  // We try this twice, once with the assumption that the result is no longer
6407  // than the input and, if that assumption breaks, again with the exact
6408  // length. This may not be pretty, but it is nicer than what was here before
6409  // and I hereby claim my vaffel-is.
6410  //
6411  // NOTE: This assumes that the upper/lower case of an ASCII
6412  // character is also ASCII. This is currently the case, but it
6413  // might break in the future if we implement more context and locale
6414  // dependent upper/lower conversions.
6415  bool has_changed_character = false;
6416 
6417  // Convert all characters to upper case, assuming that they will fit
6418  // in the buffer
6419  Access<ConsStringIteratorOp> op(
6420  isolate->runtime_state()->string_iterator());
6421  StringCharacterStream stream(string, op.value());
6422  unibrow::uchar chars[Converter::kMaxWidth];
6423  // We can assume that the string is not empty
6424  uc32 current = stream.GetNext();
6425  bool ignore_overflow = Converter::kIsToLower || result->IsSeqTwoByteString();
6426  for (int i = 0; i < result_length;) {
6427  bool has_next = stream.HasMore();
6428  uc32 next = has_next ? stream.GetNext() : 0;
6429  int char_length = mapping->get(current, next, chars);
6430  if (char_length == 0) {
6431  // The case conversion of this character is the character itself.
6432  result->Set(i, current);
6433  i++;
6434  } else if (char_length == 1 &&
6435  (ignore_overflow || !ToUpperOverflows(current))) {
6436  // Common case: converting the letter resulted in one character.
6437  ASSERT(static_cast<uc32>(chars[0]) != current);
6438  result->Set(i, chars[0]);
6439  has_changed_character = true;
6440  i++;
6441  } else if (result_length == string->length()) {
6442  bool overflows = ToUpperOverflows(current);
6443  // We've assumed that the result would be as long as the
6444  // input but here is a character that converts to several
6445  // characters. No matter, we calculate the exact length
6446  // of the result and try the whole thing again.
6447  //
6448  // Note that this leaves room for optimization. We could just
6449  // memcpy what we already have to the result string. Also,
6450  // the result string is the last object allocated we could
6451  // "realloc" it and probably, in the vast majority of cases,
6452  // extend the existing string to be able to hold the full
6453  // result.
6454  int next_length = 0;
6455  if (has_next) {
6456  next_length = mapping->get(next, 0, chars);
6457  if (next_length == 0) next_length = 1;
6458  }
6459  int current_length = i + char_length + next_length;
6460  while (stream.HasMore()) {
6461  current = stream.GetNext();
6462  overflows |= ToUpperOverflows(current);
6463  // NOTE: we use 0 as the next character here because, while
6464  // the next character may affect what a character converts to,
6465  // it does not in any case affect the length of what it convert
6466  // to.
6467  int char_length = mapping->get(current, 0, chars);
6468  if (char_length == 0) char_length = 1;
6469  current_length += char_length;
6470  if (current_length > String::kMaxLength) {
6471  AllowHeapAllocation allocate_error_and_return;
6472  return isolate->ThrowInvalidStringLength();
6473  }
6474  }
6475  // Try again with the real length. Return signed if we need
6476  // to allocate a two-byte string for to uppercase.
6477  return (overflows && !ignore_overflow) ? Smi::FromInt(-current_length)
6478  : Smi::FromInt(current_length);
6479  } else {
6480  for (int j = 0; j < char_length; j++) {
6481  result->Set(i, chars[j]);
6482  i++;
6483  }
6484  has_changed_character = true;
6485  }
6486  current = next;
6487  }
6488  if (has_changed_character) {
6489  return result;
6490  } else {
6491  // If we didn't actually change anything in doing the conversion
6492  // we simple return the result and let the converted string
6493  // become garbage; there is no reason to keep two identical strings
6494  // alive.
6495  return string;
6496  }
6497 }
6498 
6499 
6500 namespace {
6501 
6502 static const uintptr_t kOneInEveryByte = kUintptrAllBitsSet / 0xFF;
6503 static const uintptr_t kAsciiMask = kOneInEveryByte << 7;
6504 
6505 // Given a word and two range boundaries returns a word with high bit
6506 // set in every byte iff the corresponding input byte was strictly in
6507 // the range (m, n). All the other bits in the result are cleared.
6508 // This function is only useful when it can be inlined and the
6509 // boundaries are statically known.
6510 // Requires: all bytes in the input word and the boundaries must be
6511 // ASCII (less than 0x7F).
6512 static inline uintptr_t AsciiRangeMask(uintptr_t w, char m, char n) {
6513  // Use strict inequalities since in edge cases the function could be
6514  // further simplified.
6515  ASSERT(0 < m && m < n);
6516  // Has high bit set in every w byte less than n.
6517  uintptr_t tmp1 = kOneInEveryByte * (0x7F + n) - w;
6518  // Has high bit set in every w byte greater than m.
6519  uintptr_t tmp2 = w + kOneInEveryByte * (0x7F - m);
6520  return (tmp1 & tmp2 & (kOneInEveryByte * 0x80));
6521 }
6522 
6523 
6524 #ifdef DEBUG
6525 static bool CheckFastAsciiConvert(char* dst,
6526  const char* src,
6527  int length,
6528  bool changed,
6529  bool is_to_lower) {
6530  bool expected_changed = false;
6531  for (int i = 0; i < length; i++) {
6532  if (dst[i] == src[i]) continue;
6533  expected_changed = true;
6534  if (is_to_lower) {
6535  ASSERT('A' <= src[i] && src[i] <= 'Z');
6536  ASSERT(dst[i] == src[i] + ('a' - 'A'));
6537  } else {
6538  ASSERT('a' <= src[i] && src[i] <= 'z');
6539  ASSERT(dst[i] == src[i] - ('a' - 'A'));
6540  }
6541  }
6542  return (expected_changed == changed);
6543 }
6544 #endif
6545 
6546 
6547 template<class Converter>
6548 static bool FastAsciiConvert(char* dst,
6549  const char* src,
6550  int length,
6551  bool* changed_out) {
6552 #ifdef DEBUG
6553  char* saved_dst = dst;
6554  const char* saved_src = src;
6555 #endif
6556  DisallowHeapAllocation no_gc;
6557  // We rely on the distance between upper and lower case letters
6558  // being a known power of 2.
6559  ASSERT('a' - 'A' == (1 << 5));
6560  // Boundaries for the range of input characters than require conversion.
6561  static const char lo = Converter::kIsToLower ? 'A' - 1 : 'a' - 1;
6562  static const char hi = Converter::kIsToLower ? 'Z' + 1 : 'z' + 1;
6563  bool changed = false;
6564  uintptr_t or_acc = 0;
6565  const char* const limit = src + length;
6566 #ifdef V8_HOST_CAN_READ_UNALIGNED
6567  // Process the prefix of the input that requires no conversion one
6568  // (machine) word at a time.
6569  while (src <= limit - sizeof(uintptr_t)) {
6570  const uintptr_t w = *reinterpret_cast<const uintptr_t*>(src);
6571  or_acc |= w;
6572  if (AsciiRangeMask(w, lo, hi) != 0) {
6573  changed = true;
6574  break;
6575  }
6576  *reinterpret_cast<uintptr_t*>(dst) = w;
6577  src += sizeof(uintptr_t);
6578  dst += sizeof(uintptr_t);
6579  }
6580  // Process the remainder of the input performing conversion when
6581  // required one word at a time.
6582  while (src <= limit - sizeof(uintptr_t)) {
6583  const uintptr_t w = *reinterpret_cast<const uintptr_t*>(src);
6584  or_acc |= w;
6585  uintptr_t m = AsciiRangeMask(w, lo, hi);
6586  // The mask has high (7th) bit set in every byte that needs
6587  // conversion and we know that the distance between cases is
6588  // 1 << 5.
6589  *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2);
6590  src += sizeof(uintptr_t);
6591  dst += sizeof(uintptr_t);
6592  }
6593 #endif
6594  // Process the last few bytes of the input (or the whole input if
6595  // unaligned access is not supported).
6596  while (src < limit) {
6597  char c = *src;
6598  or_acc |= c;
6599  if (lo < c && c < hi) {
6600  c ^= (1 << 5);
6601  changed = true;
6602  }
6603  *dst = c;
6604  ++src;
6605  ++dst;
6606  }
6607  if ((or_acc & kAsciiMask) != 0) {
6608  return false;
6609  }
6610 
6611  ASSERT(CheckFastAsciiConvert(
6612  saved_dst, saved_src, length, changed, Converter::kIsToLower));
6613 
6614  *changed_out = changed;
6615  return true;
6616 }
6617 
6618 } // namespace
6619 
6620 
6621 template <class Converter>
6622 MUST_USE_RESULT static MaybeObject* ConvertCase(
6623  Arguments args,
6624  Isolate* isolate,
6626  HandleScope handle_scope(isolate);
6627  CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
6628  s = FlattenGetString(s);
6629  int length = s->length();
6630  // Assume that the string is not empty; we need this assumption later
6631  if (length == 0) return *s;
6632 
6633  // Simpler handling of ASCII strings.
6634  //
6635  // NOTE: This assumes that the upper/lower case of an ASCII
6636  // character is also ASCII. This is currently the case, but it
6637  // might break in the future if we implement more context and locale
6638  // dependent upper/lower conversions.
6639  if (s->IsOneByteRepresentationUnderneath()) {
6640  Handle<SeqOneByteString> result =
6641  isolate->factory()->NewRawOneByteString(length);
6642  ASSERT(!result.is_null()); // Same length as input.
6643  DisallowHeapAllocation no_gc;
6644  String::FlatContent flat_content = s->GetFlatContent();
6645  ASSERT(flat_content.IsFlat());
6646  bool has_changed_character = false;
6647  bool is_ascii = FastAsciiConvert<Converter>(
6648  reinterpret_cast<char*>(result->GetChars()),
6649  reinterpret_cast<const char*>(flat_content.ToOneByteVector().start()),
6650  length,
6651  &has_changed_character);
6652  // If not ASCII, we discard the result and take the 2 byte path.
6653  if (is_ascii) return has_changed_character ? *result : *s;
6654  }
6655 
6656  Handle<SeqString> result;
6657  if (s->IsOneByteRepresentation()) {
6658  result = isolate->factory()->NewRawOneByteString(length);
6659  } else {
6660  result = isolate->factory()->NewRawTwoByteString(length);
6661  }
6662  ASSERT(!result.is_null()); // Same length as input.
6663 
6664  MaybeObject* maybe = ConvertCaseHelper(isolate, *s, *result, length, mapping);
6665  Object* answer;
6666  if (!maybe->ToObject(&answer)) return maybe;
6667  if (answer->IsString()) return answer;
6668 
6669  ASSERT(answer->IsSmi());
6670  length = Smi::cast(answer)->value();
6671  if (s->IsOneByteRepresentation() && length > 0) {
6672  result = isolate->factory()->NewRawOneByteString(length);
6673  } else {
6674  if (length < 0) length = -length;
6675  result = isolate->factory()->NewRawTwoByteString(length);
6676  }
6677  RETURN_IF_EMPTY_HANDLE(isolate, result);
6678  return ConvertCaseHelper(isolate, *s, *result, length, mapping);
6679 }
6680 
6681 
6682 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) {
6683  return ConvertCase(
6684  args, isolate, isolate->runtime_state()->to_lower_mapping());
6685 }
6686 
6687 
6688 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToUpperCase) {
6689  return ConvertCase(
6690  args, isolate, isolate->runtime_state()->to_upper_mapping());
6691 }
6692 
6693 
6694 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringTrim) {
6695  HandleScope scope(isolate);
6696  ASSERT(args.length() == 3);
6697 
6698  CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
6699  CONVERT_BOOLEAN_ARG_CHECKED(trimLeft, 1);
6700  CONVERT_BOOLEAN_ARG_CHECKED(trimRight, 2);
6701 
6702  string = FlattenGetString(string);
6703  int length = string->length();
6704 
6705  int left = 0;
6706  UnicodeCache* unicode_cache = isolate->unicode_cache();
6707  if (trimLeft) {
6708  while (left < length &&
6709  unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(left))) {
6710  left++;
6711  }
6712  }
6713 
6714  int right = length;
6715  if (trimRight) {
6716  while (right > left &&
6717  unicode_cache->IsWhiteSpaceOrLineTerminator(
6718  string->Get(right - 1))) {
6719  right--;
6720  }
6721  }
6722 
6723  return *isolate->factory()->NewSubString(string, left, right);
6724 }
6725 
6726 
6727 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
6728  HandleScope handle_scope(isolate);
6729  ASSERT(args.length() == 3);
6730  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
6731  CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
6732  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]);
6733 
6734  int subject_length = subject->length();
6735  int pattern_length = pattern->length();
6736  RUNTIME_ASSERT(pattern_length > 0);
6737 
6738  if (limit == 0xffffffffu) {
6739  Handle<Object> cached_answer(
6740  RegExpResultsCache::Lookup(isolate->heap(),
6741  *subject,
6742  *pattern,
6744  isolate);
6745  if (*cached_answer != Smi::FromInt(0)) {
6746  // The cache FixedArray is a COW-array and can therefore be reused.
6747  Handle<JSArray> result =
6748  isolate->factory()->NewJSArrayWithElements(
6749  Handle<FixedArray>::cast(cached_answer));
6750  return *result;
6751  }
6752  }
6753 
6754  // The limit can be very large (0xffffffffu), but since the pattern
6755  // isn't empty, we can never create more parts than ~half the length
6756  // of the subject.
6757 
6758  if (!subject->IsFlat()) FlattenString(subject);
6759 
6760  static const int kMaxInitialListCapacity = 16;
6761 
6762  ZoneScope zone_scope(isolate->runtime_zone());
6763 
6764  // Find (up to limit) indices of separator and end-of-string in subject
6765  int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit);
6766  ZoneList<int> indices(initial_capacity, zone_scope.zone());
6767  if (!pattern->IsFlat()) FlattenString(pattern);
6768 
6769  FindStringIndicesDispatch(isolate, *subject, *pattern,
6770  &indices, limit, zone_scope.zone());
6771 
6772  if (static_cast<uint32_t>(indices.length()) < limit) {
6773  indices.Add(subject_length, zone_scope.zone());
6774  }
6775 
6776  // The list indices now contains the end of each part to create.
6777 
6778  // Create JSArray of substrings separated by separator.
6779  int part_count = indices.length();
6780 
6781  Handle<JSArray> result = isolate->factory()->NewJSArray(part_count);
6783  result->set_length(Smi::FromInt(part_count));
6784 
6785  ASSERT(result->HasFastObjectElements());
6786 
6787  if (part_count == 1 && indices.at(0) == subject_length) {
6788  FixedArray::cast(result->elements())->set(0, *subject);
6789  return *result;
6790  }
6791 
6792  Handle<FixedArray> elements(FixedArray::cast(result->elements()));
6793  int part_start = 0;
6794  for (int i = 0; i < part_count; i++) {
6795  HandleScope local_loop_handle(isolate);
6796  int part_end = indices.at(i);
6797  Handle<String> substring =
6798  isolate->factory()->NewProperSubString(subject, part_start, part_end);
6799  elements->set(i, *substring);
6800  part_start = part_end + pattern_length;
6801  }
6802 
6803  if (limit == 0xffffffffu) {
6804  if (result->HasFastObjectElements()) {
6805  RegExpResultsCache::Enter(isolate->heap(),
6806  *subject,
6807  *pattern,
6808  *elements,
6810  }
6811  }
6812 
6813  return *result;
6814 }
6815 
6816 
6817 // Copies ASCII characters to the given fixed array looking up
6818 // one-char strings in the cache. Gives up on the first char that is
6819 // not in the cache and fills the remainder with smi zeros. Returns
6820 // the length of the successfully copied prefix.
6821 static int CopyCachedAsciiCharsToArray(Heap* heap,
6822  const uint8_t* chars,
6823  FixedArray* elements,
6824  int length) {
6825  DisallowHeapAllocation no_gc;
6826  FixedArray* ascii_cache = heap->single_character_string_cache();
6827  Object* undefined = heap->undefined_value();
6828  int i;
6829  WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
6830  for (i = 0; i < length; ++i) {
6831  Object* value = ascii_cache->get(chars[i]);
6832  if (value == undefined) break;
6833  elements->set(i, value, mode);
6834  }
6835  if (i < length) {
6836  ASSERT(Smi::FromInt(0) == 0);
6837  memset(elements->data_start() + i, 0, kPointerSize * (length - i));
6838  }
6839 #ifdef DEBUG
6840  for (int j = 0; j < length; ++j) {
6841  Object* element = elements->get(j);
6842  ASSERT(element == Smi::FromInt(0) ||
6843  (element->IsString() && String::cast(element)->LooksValid()));
6844  }
6845 #endif
6846  return i;
6847 }
6848 
6849 
6850 // Converts a String to JSArray.
6851 // For example, "foo" => ["f", "o", "o"].
6852 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToArray) {
6853  HandleScope scope(isolate);
6854  ASSERT(args.length() == 2);
6856  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
6857 
6858  s = FlattenGetString(s);
6859  const int length = static_cast<int>(Min<uint32_t>(s->length(), limit));
6860 
6861  Handle<FixedArray> elements;
6862  int position = 0;
6863  if (s->IsFlat() && s->IsOneByteRepresentation()) {
6864  // Try using cached chars where possible.
6865  Object* obj;
6866  { MaybeObject* maybe_obj =
6867  isolate->heap()->AllocateUninitializedFixedArray(length);
6868  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
6869  }
6870  elements = Handle<FixedArray>(FixedArray::cast(obj), isolate);
6871  DisallowHeapAllocation no_gc;
6872  String::FlatContent content = s->GetFlatContent();
6873  if (content.IsAscii()) {
6874  Vector<const uint8_t> chars = content.ToOneByteVector();
6875  // Note, this will initialize all elements (not only the prefix)
6876  // to prevent GC from seeing partially initialized array.
6877  position = CopyCachedAsciiCharsToArray(isolate->heap(),
6878  chars.start(),
6879  *elements,
6880  length);
6881  } else {
6882  MemsetPointer(elements->data_start(),
6883  isolate->heap()->undefined_value(),
6884  length);
6885  }
6886  } else {
6887  elements = isolate->factory()->NewFixedArray(length);
6888  }
6889  for (int i = position; i < length; ++i) {
6890  Handle<Object> str =
6891  LookupSingleCharacterStringFromCode(isolate, s->Get(i));
6892  elements->set(i, *str);
6893  }
6894 
6895 #ifdef DEBUG
6896  for (int i = 0; i < length; ++i) {
6897  ASSERT(String::cast(elements->get(i))->length() == 1);
6898  }
6899 #endif
6900 
6901  return *isolate->factory()->NewJSArrayWithElements(elements);
6902 }
6903 
6904 
6905 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStringWrapper) {
6906  SealHandleScope shs(isolate);
6907  ASSERT(args.length() == 1);
6908  CONVERT_ARG_CHECKED(String, value, 0);
6909  return value->ToObject(isolate);
6910 }
6911 
6912 
6913 bool Runtime::IsUpperCaseChar(RuntimeState* runtime_state, uint16_t ch) {
6915  int char_length = runtime_state->to_upper_mapping()->get(ch, 0, chars);
6916  return char_length == 0;
6917 }
6918 
6919 
6920 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NumberToString) {
6921  SealHandleScope shs(isolate);
6922  ASSERT(args.length() == 1);
6923 
6924  Object* number = args[0];
6925  RUNTIME_ASSERT(number->IsNumber());
6926 
6927  return isolate->heap()->NumberToString(number);
6928 }
6929 
6930 
6931 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NumberToStringSkipCache) {
6932  SealHandleScope shs(isolate);
6933  ASSERT(args.length() == 1);
6934 
6935  Object* number = args[0];
6936  RUNTIME_ASSERT(number->IsNumber());
6937 
6938  return isolate->heap()->NumberToString(number, false);
6939 }
6940 
6941 
6942 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToInteger) {
6943  SealHandleScope shs(isolate);
6944  ASSERT(args.length() == 1);
6945 
6946  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6947 
6948  // We do not include 0 so that we don't have to treat +0 / -0 cases.
6949  if (number > 0 && number <= Smi::kMaxValue) {
6950  return Smi::FromInt(static_cast<int>(number));
6951  }
6952  return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
6953 }
6954 
6955 
6956 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToIntegerMapMinusZero) {
6957  SealHandleScope shs(isolate);
6958  ASSERT(args.length() == 1);
6959 
6960  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6961 
6962  // We do not include 0 so that we don't have to treat +0 / -0 cases.
6963  if (number > 0 && number <= Smi::kMaxValue) {
6964  return Smi::FromInt(static_cast<int>(number));
6965  }
6966 
6967  double double_value = DoubleToInteger(number);
6968  // Map both -0 and +0 to +0.
6969  if (double_value == 0) double_value = 0;
6970 
6971  return isolate->heap()->NumberFromDouble(double_value);
6972 }
6973 
6974 
6975 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSUint32) {
6976  SealHandleScope shs(isolate);
6977  ASSERT(args.length() == 1);
6978 
6979  CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]);
6980  return isolate->heap()->NumberFromUint32(number);
6981 }
6982 
6983 
6984 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSInt32) {
6985  SealHandleScope shs(isolate);
6986  ASSERT(args.length() == 1);
6987 
6988  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6989 
6990  // We do not include 0 so that we don't have to treat +0 / -0 cases.
6991  if (number > 0 && number <= Smi::kMaxValue) {
6992  return Smi::FromInt(static_cast<int>(number));
6993  }
6994  return isolate->heap()->NumberFromInt32(DoubleToInt32(number));
6995 }
6996 
6997 
6998 // Converts a Number to a Smi, if possible. Returns NaN if the number is not
6999 // a small integer.
7000 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NumberToSmi) {
7001  SealHandleScope shs(isolate);
7002  ASSERT(args.length() == 1);
7003 
7004  Object* obj = args[0];
7005  if (obj->IsSmi()) {
7006  return obj;
7007  }
7008  if (obj->IsHeapNumber()) {
7009  double value = HeapNumber::cast(obj)->value();
7010  int int_value = FastD2I(value);
7011  if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
7012  return Smi::FromInt(int_value);
7013  }
7014  }
7015  return isolate->heap()->nan_value();
7016 }
7017 
7018 
7019 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_AllocateHeapNumber) {
7020  SealHandleScope shs(isolate);
7021  ASSERT(args.length() == 0);
7022  return isolate->heap()->AllocateHeapNumber(0);
7023 }
7024 
7025 
7026 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAdd) {
7027  SealHandleScope shs(isolate);
7028  ASSERT(args.length() == 2);
7029 
7032  return isolate->heap()->NumberFromDouble(x + y);
7033 }
7034 
7035 
7036 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSub) {
7037  SealHandleScope shs(isolate);
7038  ASSERT(args.length() == 2);
7039 
7042  return isolate->heap()->NumberFromDouble(x - y);
7043 }
7044 
7045 
7046 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMul) {
7047  SealHandleScope shs(isolate);
7048  ASSERT(args.length() == 2);
7049 
7052  return isolate->heap()->NumberFromDouble(x * y);
7053 }
7054 
7055 
7056 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberUnaryMinus) {
7057  SealHandleScope shs(isolate);
7058  ASSERT(args.length() == 1);
7059 
7061  return isolate->heap()->NumberFromDouble(-x);
7062 }
7063 
7064 
7065 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAlloc) {
7066  SealHandleScope shs(isolate);
7067  ASSERT(args.length() == 0);
7068 
7069  return isolate->heap()->NumberFromDouble(9876543210.0);
7070 }
7071 
7072 
7073 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberDiv) {
7074  SealHandleScope shs(isolate);
7075  ASSERT(args.length() == 2);
7076 
7079  return isolate->heap()->NumberFromDouble(x / y);
7080 }
7081 
7082 
7083 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMod) {
7084  SealHandleScope shs(isolate);
7085  ASSERT(args.length() == 2);
7086 
7089 
7090  x = modulo(x, y);
7091  // NumberFromDouble may return a Smi instead of a Number object
7092  return isolate->heap()->NumberFromDouble(x);
7093 }
7094 
7095 
7096 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberImul) {
7097  SealHandleScope shs(isolate);
7098  ASSERT(args.length() == 2);
7099 
7100  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7101  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7102  return isolate->heap()->NumberFromInt32(x * y);
7103 }
7104 
7105 
7106 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StringAdd) {
7107  HandleScope scope(isolate);
7108  ASSERT(args.length() == 2);
7111  isolate->counters()->string_add_runtime()->Increment();
7112  Handle<String> result = isolate->factory()->NewConsString(str1, str2);
7113  RETURN_IF_EMPTY_HANDLE(isolate, result);
7114  return *result;
7115 }
7116 
7117 
7118 template <typename sinkchar>
7119 static inline void StringBuilderConcatHelper(String* special,
7120  sinkchar* sink,
7121  FixedArray* fixed_array,
7122  int array_length) {
7123  int position = 0;
7124  for (int i = 0; i < array_length; i++) {
7125  Object* element = fixed_array->get(i);
7126  if (element->IsSmi()) {
7127  // Smi encoding of position and length.
7128  int encoded_slice = Smi::cast(element)->value();
7129  int pos;
7130  int len;
7131  if (encoded_slice > 0) {
7132  // Position and length encoded in one smi.
7133  pos = StringBuilderSubstringPosition::decode(encoded_slice);
7134  len = StringBuilderSubstringLength::decode(encoded_slice);
7135  } else {
7136  // Position and length encoded in two smis.
7137  Object* obj = fixed_array->get(++i);
7138  ASSERT(obj->IsSmi());
7139  pos = Smi::cast(obj)->value();
7140  len = -encoded_slice;
7141  }
7142  String::WriteToFlat(special,
7143  sink + position,
7144  pos,
7145  pos + len);
7146  position += len;
7147  } else {
7148  String* string = String::cast(element);
7149  int element_length = string->length();
7150  String::WriteToFlat(string, sink + position, 0, element_length);
7151  position += element_length;
7152  }
7153  }
7154 }
7155 
7156 
7157 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
7158  HandleScope scope(isolate);
7159  ASSERT(args.length() == 3);
7161  if (!args[1]->IsSmi()) return isolate->ThrowInvalidStringLength();
7162  int array_length = args.smi_at(1);
7163  CONVERT_ARG_HANDLE_CHECKED(String, special, 2);
7164 
7165  // This assumption is used by the slice encoding in one or two smis.
7167 
7169 
7170  int special_length = special->length();
7171  if (!array->HasFastObjectElements()) {
7172  return isolate->Throw(isolate->heap()->illegal_argument_string());
7173  }
7174  FixedArray* fixed_array = FixedArray::cast(array->elements());
7175  if (fixed_array->length() < array_length) {
7176  array_length = fixed_array->length();
7177  }
7178 
7179  if (array_length == 0) {
7180  return isolate->heap()->empty_string();
7181  } else if (array_length == 1) {
7182  Object* first = fixed_array->get(0);
7183  if (first->IsString()) return first;
7184  }
7185 
7186  bool one_byte = special->HasOnlyOneByteChars();
7187  int position = 0;
7188  for (int i = 0; i < array_length; i++) {
7189  int increment = 0;
7190  Object* elt = fixed_array->get(i);
7191  if (elt->IsSmi()) {
7192  // Smi encoding of position and length.
7193  int smi_value = Smi::cast(elt)->value();
7194  int pos;
7195  int len;
7196  if (smi_value > 0) {
7197  // Position and length encoded in one smi.
7198  pos = StringBuilderSubstringPosition::decode(smi_value);
7199  len = StringBuilderSubstringLength::decode(smi_value);
7200  } else {
7201  // Position and length encoded in two smis.
7202  len = -smi_value;
7203  // Get the position and check that it is a positive smi.
7204  i++;
7205  if (i >= array_length) {
7206  return isolate->Throw(isolate->heap()->illegal_argument_string());
7207  }
7208  Object* next_smi = fixed_array->get(i);
7209  if (!next_smi->IsSmi()) {
7210  return isolate->Throw(isolate->heap()->illegal_argument_string());
7211  }
7212  pos = Smi::cast(next_smi)->value();
7213  if (pos < 0) {
7214  return isolate->Throw(isolate->heap()->illegal_argument_string());
7215  }
7216  }
7217  ASSERT(pos >= 0);
7218  ASSERT(len >= 0);
7219  if (pos > special_length || len > special_length - pos) {
7220  return isolate->Throw(isolate->heap()->illegal_argument_string());
7221  }
7222  increment = len;
7223  } else if (elt->IsString()) {
7224  String* element = String::cast(elt);
7225  int element_length = element->length();
7226  increment = element_length;
7227  if (one_byte && !element->HasOnlyOneByteChars()) {
7228  one_byte = false;
7229  }
7230  } else {
7231  ASSERT(!elt->IsTheHole());
7232  return isolate->Throw(isolate->heap()->illegal_argument_string());
7233  }
7234  if (increment > String::kMaxLength - position) {
7235  return isolate->ThrowInvalidStringLength();
7236  }
7237  position += increment;
7238  }
7239 
7240  int length = position;
7241  Object* object;
7242 
7243  if (one_byte) {
7244  { MaybeObject* maybe_object =
7245  isolate->heap()->AllocateRawOneByteString(length);
7246  if (!maybe_object->ToObject(&object)) return maybe_object;
7247  }
7248  SeqOneByteString* answer = SeqOneByteString::cast(object);
7249  StringBuilderConcatHelper(*special,
7250  answer->GetChars(),
7251  fixed_array,
7252  array_length);
7253  return answer;
7254  } else {
7255  { MaybeObject* maybe_object =
7256  isolate->heap()->AllocateRawTwoByteString(length);
7257  if (!maybe_object->ToObject(&object)) return maybe_object;
7258  }
7259  SeqTwoByteString* answer = SeqTwoByteString::cast(object);
7260  StringBuilderConcatHelper(*special,
7261  answer->GetChars(),
7262  fixed_array,
7263  array_length);
7264  return answer;
7265  }
7266 }
7267 
7268 
7269 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
7270  HandleScope scope(isolate);
7271  ASSERT(args.length() == 3);
7273  if (!args[1]->IsSmi()) return isolate->ThrowInvalidStringLength();
7274  int array_length = args.smi_at(1);
7275  CONVERT_ARG_HANDLE_CHECKED(String, separator, 2);
7276  RUNTIME_ASSERT(array->HasFastObjectElements());
7277 
7278  Handle<FixedArray> fixed_array(FixedArray::cast(array->elements()));
7279  if (fixed_array->length() < array_length) {
7280  array_length = fixed_array->length();
7281  }
7282 
7283  if (array_length == 0) {
7284  return isolate->heap()->empty_string();
7285  } else if (array_length == 1) {
7286  Object* first = fixed_array->get(0);
7287  RUNTIME_ASSERT(first->IsString());
7288  return first;
7289  }
7290 
7291  int separator_length = separator->length();
7292  int max_nof_separators =
7293  (String::kMaxLength + separator_length - 1) / separator_length;
7294  if (max_nof_separators < (array_length - 1)) {
7295  return isolate->ThrowInvalidStringLength();
7296  }
7297  int length = (array_length - 1) * separator_length;
7298  for (int i = 0; i < array_length; i++) {
7299  Object* element_obj = fixed_array->get(i);
7300  RUNTIME_ASSERT(element_obj->IsString());
7301  String* element = String::cast(element_obj);
7302  int increment = element->length();
7303  if (increment > String::kMaxLength - length) {
7305  length = kMaxInt; // Provoke exception;
7306  break;
7307  }
7308  length += increment;
7309  }
7310 
7311  Handle<SeqTwoByteString> answer =
7312  isolate->factory()->NewRawTwoByteString(length);
7313  RETURN_IF_EMPTY_HANDLE(isolate, answer);
7314 
7315  DisallowHeapAllocation no_gc;
7316 
7317  uc16* sink = answer->GetChars();
7318 #ifdef DEBUG
7319  uc16* end = sink + length;
7320 #endif
7321 
7322  String* first = String::cast(fixed_array->get(0));
7323  String* seperator_raw = *separator;
7324  int first_length = first->length();
7325  String::WriteToFlat(first, sink, 0, first_length);
7326  sink += first_length;
7327 
7328  for (int i = 1; i < array_length; i++) {
7329  ASSERT(sink + separator_length <= end);
7330  String::WriteToFlat(seperator_raw, sink, 0, separator_length);
7331  sink += separator_length;
7332 
7333  String* element = String::cast(fixed_array->get(i));
7334  int element_length = element->length();
7335  ASSERT(sink + element_length <= end);
7336  String::WriteToFlat(element, sink, 0, element_length);
7337  sink += element_length;
7338  }
7339  ASSERT(sink == end);
7340 
7341  // Use %_FastAsciiArrayJoin instead.
7342  ASSERT(!answer->IsOneByteRepresentation());
7343  return *answer;
7344 }
7345 
7346 template <typename Char>
7347 static void JoinSparseArrayWithSeparator(FixedArray* elements,
7348  int elements_length,
7349  uint32_t array_length,
7350  String* separator,
7351  Vector<Char> buffer) {
7352  int previous_separator_position = 0;
7353  int separator_length = separator->length();
7354  int cursor = 0;
7355  for (int i = 0; i < elements_length; i += 2) {
7356  int position = NumberToInt32(elements->get(i));
7357  String* string = String::cast(elements->get(i + 1));
7358  int string_length = string->length();
7359  if (string->length() > 0) {
7360  while (previous_separator_position < position) {
7361  String::WriteToFlat<Char>(separator, &buffer[cursor],
7362  0, separator_length);
7363  cursor += separator_length;
7364  previous_separator_position++;
7365  }
7366  String::WriteToFlat<Char>(string, &buffer[cursor],
7367  0, string_length);
7368  cursor += string->length();
7369  }
7370  }
7371  if (separator_length > 0) {
7372  // Array length must be representable as a signed 32-bit number,
7373  // otherwise the total string length would have been too large.
7374  ASSERT(array_length <= 0x7fffffff); // Is int32_t.
7375  int last_array_index = static_cast<int>(array_length - 1);
7376  while (previous_separator_position < last_array_index) {
7377  String::WriteToFlat<Char>(separator, &buffer[cursor],
7378  0, separator_length);
7379  cursor += separator_length;
7380  previous_separator_position++;
7381  }
7382  }
7383  ASSERT(cursor <= buffer.length());
7384 }
7385 
7386 
7387 RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) {
7388  HandleScope scope(isolate);
7389  ASSERT(args.length() == 3);
7390  CONVERT_ARG_CHECKED(JSArray, elements_array, 0);
7391  RUNTIME_ASSERT(elements_array->HasFastSmiOrObjectElements());
7392  CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]);
7393  CONVERT_ARG_CHECKED(String, separator, 2);
7394  // elements_array is fast-mode JSarray of alternating positions
7395  // (increasing order) and strings.
7396  // array_length is length of original array (used to add separators);
7397  // separator is string to put between elements. Assumed to be non-empty.
7398 
7399  // Find total length of join result.
7400  int string_length = 0;
7401  bool is_ascii = separator->IsOneByteRepresentation();
7402  bool overflow = false;
7403  CONVERT_NUMBER_CHECKED(int, elements_length,
7404  Int32, elements_array->length());
7405  RUNTIME_ASSERT((elements_length & 1) == 0); // Even length.
7406  FixedArray* elements = FixedArray::cast(elements_array->elements());
7407  for (int i = 0; i < elements_length; i += 2) {
7408  RUNTIME_ASSERT(elements->get(i)->IsNumber());
7409  RUNTIME_ASSERT(elements->get(i + 1)->IsString());
7410  String* string = String::cast(elements->get(i + 1));
7411  int length = string->length();
7412  if (is_ascii && !string->IsOneByteRepresentation()) {
7413  is_ascii = false;
7414  }
7415  if (length > String::kMaxLength ||
7416  String::kMaxLength - length < string_length) {
7417  overflow = true;
7418  break;
7419  }
7420  string_length += length;
7421  }
7422  int separator_length = separator->length();
7423  if (!overflow && separator_length > 0) {
7424  if (array_length <= 0x7fffffffu) {
7425  int separator_count = static_cast<int>(array_length) - 1;
7426  int remaining_length = String::kMaxLength - string_length;
7427  if ((remaining_length / separator_length) >= separator_count) {
7428  string_length += separator_length * (array_length - 1);
7429  } else {
7430  // Not room for the separators within the maximal string length.
7431  overflow = true;
7432  }
7433  } else {
7434  // Nonempty separator and at least 2^31-1 separators necessary
7435  // means that the string is too large to create.
7436  STATIC_ASSERT(String::kMaxLength < 0x7fffffff);
7437  overflow = true;
7438  }
7439  }
7440  if (overflow) {
7441  // Throw an exception if the resulting string is too large. See
7442  // https://code.google.com/p/chromium/issues/detail?id=336820
7443  // for details.
7444  return isolate->ThrowInvalidStringLength();
7445  }
7446 
7447  if (is_ascii) {
7448  MaybeObject* result_allocation =
7449  isolate->heap()->AllocateRawOneByteString(string_length);
7450  if (result_allocation->IsFailure()) return result_allocation;
7451  SeqOneByteString* result_string =
7452  SeqOneByteString::cast(result_allocation->ToObjectUnchecked());
7453  JoinSparseArrayWithSeparator<uint8_t>(elements,
7454  elements_length,
7455  array_length,
7456  separator,
7458  result_string->GetChars(),
7459  string_length));
7460  return result_string;
7461  } else {
7462  MaybeObject* result_allocation =
7463  isolate->heap()->AllocateRawTwoByteString(string_length);
7464  if (result_allocation->IsFailure()) return result_allocation;
7465  SeqTwoByteString* result_string =
7466  SeqTwoByteString::cast(result_allocation->ToObjectUnchecked());
7467  JoinSparseArrayWithSeparator<uc16>(elements,
7468  elements_length,
7469  array_length,
7470  separator,
7471  Vector<uc16>(result_string->GetChars(),
7472  string_length));
7473  return result_string;
7474  }
7475 }
7476 
7477 
7478 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberOr) {
7479  SealHandleScope shs(isolate);
7480  ASSERT(args.length() == 2);
7481 
7482  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7483  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7484  return isolate->heap()->NumberFromInt32(x | y);
7485 }
7486 
7487 
7488 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAnd) {
7489  SealHandleScope shs(isolate);
7490  ASSERT(args.length() == 2);
7491 
7492  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7493  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7494  return isolate->heap()->NumberFromInt32(x & y);
7495 }
7496 
7497 
7498 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberXor) {
7499  SealHandleScope shs(isolate);
7500  ASSERT(args.length() == 2);
7501 
7502  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7503  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7504  return isolate->heap()->NumberFromInt32(x ^ y);
7505 }
7506 
7507 
7508 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShl) {
7509  SealHandleScope shs(isolate);
7510  ASSERT(args.length() == 2);
7511 
7512  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7513  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7514  return isolate->heap()->NumberFromInt32(x << (y & 0x1f));
7515 }
7516 
7517 
7518 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShr) {
7519  SealHandleScope shs(isolate);
7520  ASSERT(args.length() == 2);
7521 
7522  CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
7523  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7524  return isolate->heap()->NumberFromUint32(x >> (y & 0x1f));
7525 }
7526 
7527 
7528 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSar) {
7529  SealHandleScope shs(isolate);
7530  ASSERT(args.length() == 2);
7531 
7532  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7533  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7534  return isolate->heap()->NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f));
7535 }
7536 
7537 
7538 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberEquals) {
7539  SealHandleScope shs(isolate);
7540  ASSERT(args.length() == 2);
7541 
7544  if (std::isnan(x)) return Smi::FromInt(NOT_EQUAL);
7545  if (std::isnan(y)) return Smi::FromInt(NOT_EQUAL);
7546  if (x == y) return Smi::FromInt(EQUAL);
7547  Object* result;
7548  if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
7549  result = Smi::FromInt(EQUAL);
7550  } else {
7551  result = Smi::FromInt(NOT_EQUAL);
7552  }
7553  return result;
7554 }
7555 
7556 
7557 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) {
7558  SealHandleScope shs(isolate);
7559  ASSERT(args.length() == 2);
7560 
7561  CONVERT_ARG_CHECKED(String, x, 0);
7562  CONVERT_ARG_CHECKED(String, y, 1);
7563 
7564  bool not_equal = !x->Equals(y);
7565  // This is slightly convoluted because the value that signifies
7566  // equality is 0 and inequality is 1 so we have to negate the result
7567  // from String::Equals.
7568  ASSERT(not_equal == 0 || not_equal == 1);
7569  STATIC_CHECK(EQUAL == 0);
7570  STATIC_CHECK(NOT_EQUAL == 1);
7571  return Smi::FromInt(not_equal);
7572 }
7573 
7574 
7575 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberCompare) {
7576  SealHandleScope shs(isolate);
7577  ASSERT(args.length() == 3);
7578 
7581  if (std::isnan(x) || std::isnan(y)) return args[2];
7582  if (x == y) return Smi::FromInt(EQUAL);
7583  if (isless(x, y)) return Smi::FromInt(LESS);
7584  return Smi::FromInt(GREATER);
7585 }
7586 
7587 
7588 // Compare two Smis as if they were converted to strings and then
7589 // compared lexicographically.
7590 RUNTIME_FUNCTION(MaybeObject*, Runtime_SmiLexicographicCompare) {
7591  SealHandleScope shs(isolate);
7592  ASSERT(args.length() == 2);
7593  CONVERT_SMI_ARG_CHECKED(x_value, 0);
7594  CONVERT_SMI_ARG_CHECKED(y_value, 1);
7595 
7596  // If the integers are equal so are the string representations.
7597  if (x_value == y_value) return Smi::FromInt(EQUAL);
7598 
7599  // If one of the integers is zero the normal integer order is the
7600  // same as the lexicographic order of the string representations.
7601  if (x_value == 0 || y_value == 0)
7602  return Smi::FromInt(x_value < y_value ? LESS : GREATER);
7603 
7604  // If only one of the integers is negative the negative number is
7605  // smallest because the char code of '-' is less than the char code
7606  // of any digit. Otherwise, we make both values positive.
7607 
7608  // Use unsigned values otherwise the logic is incorrect for -MIN_INT on
7609  // architectures using 32-bit Smis.
7610  uint32_t x_scaled = x_value;
7611  uint32_t y_scaled = y_value;
7612  if (x_value < 0 || y_value < 0) {
7613  if (y_value >= 0) return Smi::FromInt(LESS);
7614  if (x_value >= 0) return Smi::FromInt(GREATER);
7615  x_scaled = -x_value;
7616  y_scaled = -y_value;
7617  }
7618 
7619  static const uint32_t kPowersOf10[] = {
7620  1, 10, 100, 1000, 10*1000, 100*1000,
7621  1000*1000, 10*1000*1000, 100*1000*1000,
7622  1000*1000*1000
7623  };
7624 
7625  // If the integers have the same number of decimal digits they can be
7626  // compared directly as the numeric order is the same as the
7627  // lexicographic order. If one integer has fewer digits, it is scaled
7628  // by some power of 10 to have the same number of digits as the longer
7629  // integer. If the scaled integers are equal it means the shorter
7630  // integer comes first in the lexicographic order.
7631 
7632  // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
7633  int x_log2 = IntegerLog2(x_scaled);
7634  int x_log10 = ((x_log2 + 1) * 1233) >> 12;
7635  x_log10 -= x_scaled < kPowersOf10[x_log10];
7636 
7637  int y_log2 = IntegerLog2(y_scaled);
7638  int y_log10 = ((y_log2 + 1) * 1233) >> 12;
7639  y_log10 -= y_scaled < kPowersOf10[y_log10];
7640 
7641  int tie = EQUAL;
7642 
7643  if (x_log10 < y_log10) {
7644  // X has fewer digits. We would like to simply scale up X but that
7645  // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would
7646  // be scaled up to 9_000_000_000. So we scale up by the next
7647  // smallest power and scale down Y to drop one digit. It is OK to
7648  // drop one digit from the longer integer since the final digit is
7649  // past the length of the shorter integer.
7650  x_scaled *= kPowersOf10[y_log10 - x_log10 - 1];
7651  y_scaled /= 10;
7652  tie = LESS;
7653  } else if (y_log10 < x_log10) {
7654  y_scaled *= kPowersOf10[x_log10 - y_log10 - 1];
7655  x_scaled /= 10;
7656  tie = GREATER;
7657  }
7658 
7659  if (x_scaled < y_scaled) return Smi::FromInt(LESS);
7660  if (x_scaled > y_scaled) return Smi::FromInt(GREATER);
7661  return Smi::FromInt(tie);
7662 }
7663 
7664 
7665 static Object* StringCharacterStreamCompare(RuntimeState* state,
7666  String* x,
7667  String* y) {
7668  StringCharacterStream stream_x(x, state->string_iterator_compare_x());
7669  StringCharacterStream stream_y(y, state->string_iterator_compare_y());
7670  while (stream_x.HasMore() && stream_y.HasMore()) {
7671  int d = stream_x.GetNext() - stream_y.GetNext();
7672  if (d < 0) return Smi::FromInt(LESS);
7673  else if (d > 0) return Smi::FromInt(GREATER);
7674  }
7675 
7676  // x is (non-trivial) prefix of y:
7677  if (stream_y.HasMore()) return Smi::FromInt(LESS);
7678  // y is prefix of x:
7679  return Smi::FromInt(stream_x.HasMore() ? GREATER : EQUAL);
7680 }
7681 
7682 
7683 static Object* FlatStringCompare(String* x, String* y) {
7684  ASSERT(x->IsFlat());
7685  ASSERT(y->IsFlat());
7686  Object* equal_prefix_result = Smi::FromInt(EQUAL);
7687  int prefix_length = x->length();
7688  if (y->length() < prefix_length) {
7689  prefix_length = y->length();
7690  equal_prefix_result = Smi::FromInt(GREATER);
7691  } else if (y->length() > prefix_length) {
7692  equal_prefix_result = Smi::FromInt(LESS);
7693  }
7694  int r;
7695  DisallowHeapAllocation no_gc;
7696  String::FlatContent x_content = x->GetFlatContent();
7697  String::FlatContent y_content = y->GetFlatContent();
7698  if (x_content.IsAscii()) {
7699  Vector<const uint8_t> x_chars = x_content.ToOneByteVector();
7700  if (y_content.IsAscii()) {
7701  Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
7702  r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7703  } else {
7704  Vector<const uc16> y_chars = y_content.ToUC16Vector();
7705  r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7706  }
7707  } else {
7708  Vector<const uc16> x_chars = x_content.ToUC16Vector();
7709  if (y_content.IsAscii()) {
7710  Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
7711  r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7712  } else {
7713  Vector<const uc16> y_chars = y_content.ToUC16Vector();
7714  r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7715  }
7716  }
7717  Object* result;
7718  if (r == 0) {
7719  result = equal_prefix_result;
7720  } else {
7721  result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
7722  }
7723  ASSERT(result ==
7724  StringCharacterStreamCompare(x->GetIsolate()->runtime_state(), x, y));
7725  return result;
7726 }
7727 
7728 
7729 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StringCompare) {
7730  SealHandleScope shs(isolate);
7731  ASSERT(args.length() == 2);
7732 
7733  CONVERT_ARG_CHECKED(String, x, 0);
7734  CONVERT_ARG_CHECKED(String, y, 1);
7735 
7736  isolate->counters()->string_compare_runtime()->Increment();
7737 
7738  // A few fast case tests before we flatten.
7739  if (x == y) return Smi::FromInt(EQUAL);
7740  if (y->length() == 0) {
7741  if (x->length() == 0) return Smi::FromInt(EQUAL);
7742  return Smi::FromInt(GREATER);
7743  } else if (x->length() == 0) {
7744  return Smi::FromInt(LESS);
7745  }
7746 
7747  int d = x->Get(0) - y->Get(0);
7748  if (d < 0) return Smi::FromInt(LESS);
7749  else if (d > 0) return Smi::FromInt(GREATER);
7750 
7751  Object* obj;
7752  { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(x);
7753  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7754  }
7755  { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(y);
7756  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7757  }
7758 
7759  return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
7760  : StringCharacterStreamCompare(isolate->runtime_state(), x, y);
7761 }
7762 
7763 
7764 #define RUNTIME_UNARY_MATH(NAME) \
7765 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_##NAME) { \
7766  SealHandleScope shs(isolate); \
7767  ASSERT(args.length() == 1); \
7768  isolate->counters()->math_##NAME()->Increment(); \
7769  CONVERT_DOUBLE_ARG_CHECKED(x, 0); \
7770  return isolate->heap()->AllocateHeapNumber(std::NAME(x)); \
7771 }
7772 
7773 RUNTIME_UNARY_MATH(acos)
7774 RUNTIME_UNARY_MATH(asin)
7775 RUNTIME_UNARY_MATH(atan)
7777 #undef RUNTIME_UNARY_MATH
7778 
7779 
7780 RUNTIME_FUNCTION(MaybeObject*, Runtime_DoubleHi) {
7781  SealHandleScope shs(isolate);
7782  ASSERT(args.length() == 1);
7784  uint64_t integer = double_to_uint64(x);
7785  integer = (integer >> 32) & 0xFFFFFFFFu;
7786  return isolate->heap()->NumberFromDouble(static_cast<int32_t>(integer));
7787 }
7788 
7789 
7790 RUNTIME_FUNCTION(MaybeObject*, Runtime_DoubleLo) {
7791  SealHandleScope shs(isolate);
7792  ASSERT(args.length() == 1);
7794  return isolate->heap()->NumberFromDouble(
7795  static_cast<int32_t>(double_to_uint64(x) & 0xFFFFFFFFu));
7796 }
7797 
7798 
7799 RUNTIME_FUNCTION(MaybeObject*, Runtime_ConstructDouble) {
7800  SealHandleScope shs(isolate);
7801  ASSERT(args.length() == 2);
7802  CONVERT_NUMBER_CHECKED(uint32_t, hi, Uint32, args[0]);
7803  CONVERT_NUMBER_CHECKED(uint32_t, lo, Uint32, args[1]);
7804  uint64_t result = (static_cast<uint64_t>(hi) << 32) | lo;
7805  return isolate->heap()->AllocateHeapNumber(uint64_to_double(result));
7806 }
7807 
7808 
7809 static const double kPiDividedBy4 = 0.78539816339744830962;
7810 
7811 
7812 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan2) {
7813  SealHandleScope shs(isolate);
7814  ASSERT(args.length() == 2);
7815  isolate->counters()->math_atan2()->Increment();
7816 
7819  double result;
7820  if (std::isinf(x) && std::isinf(y)) {
7821  // Make sure that the result in case of two infinite arguments
7822  // is a multiple of Pi / 4. The sign of the result is determined
7823  // by the first argument (x) and the sign of the second argument
7824  // determines the multiplier: one or three.
7825  int multiplier = (x < 0) ? -1 : 1;
7826  if (y < 0) multiplier *= 3;
7827  result = multiplier * kPiDividedBy4;
7828  } else {
7829  result = std::atan2(x, y);
7830  }
7831  return isolate->heap()->AllocateHeapNumber(result);
7832 }
7833 
7834 
7835 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_exp) {
7836  SealHandleScope shs(isolate);
7837  ASSERT(args.length() == 1);
7838  isolate->counters()->math_exp()->Increment();
7839 
7842  return isolate->heap()->NumberFromDouble(fast_exp(x));
7843 }
7844 
7845 
7846 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_floor) {
7847  SealHandleScope shs(isolate);
7848  ASSERT(args.length() == 1);
7849  isolate->counters()->math_floor()->Increment();
7850 
7852  return isolate->heap()->NumberFromDouble(std::floor(x));
7853 }
7854 
7855 
7856 // Slow version of Math.pow. We check for fast paths for special cases.
7857 // Used if SSE2/VFP3 is not available.
7858 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow) {
7859  SealHandleScope shs(isolate);
7860  ASSERT(args.length() == 2);
7861  isolate->counters()->math_pow()->Increment();
7862 
7864 
7865  // If the second argument is a smi, it is much faster to call the
7866  // custom powi() function than the generic pow().
7867  if (args[1]->IsSmi()) {
7868  int y = args.smi_at(1);
7869  return isolate->heap()->NumberFromDouble(power_double_int(x, y));
7870  }
7871 
7873  double result = power_helper(x, y);
7874  if (std::isnan(result)) return isolate->heap()->nan_value();
7875  return isolate->heap()->AllocateHeapNumber(result);
7876 }
7877 
7878 
7879 // Fast version of Math.pow if we know that y is not an integer and y is not
7880 // -0.5 or 0.5. Used as slow case from full codegen.
7881 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow_cfunction) {
7882  SealHandleScope shs(isolate);
7883  ASSERT(args.length() == 2);
7884  isolate->counters()->math_pow()->Increment();
7885 
7888  if (y == 0) {
7889  return Smi::FromInt(1);
7890  } else {
7891  double result = power_double_double(x, y);
7892  if (std::isnan(result)) return isolate->heap()->nan_value();
7893  return isolate->heap()->AllocateHeapNumber(result);
7894  }
7895 }
7896 
7897 
7898 RUNTIME_FUNCTION(MaybeObject*, Runtime_RoundNumber) {
7899  SealHandleScope shs(isolate);
7900  ASSERT(args.length() == 1);
7901  isolate->counters()->math_round()->Increment();
7902 
7903  if (!args[0]->IsHeapNumber()) {
7904  // Must be smi. Return the argument unchanged for all the other types
7905  // to make fuzz-natives test happy.
7906  return args[0];
7907  }
7908 
7909  HeapNumber* number = reinterpret_cast<HeapNumber*>(args[0]);
7910 
7911  double value = number->value();
7912  int exponent = number->get_exponent();
7913  int sign = number->get_sign();
7914 
7915  if (exponent < -1) {
7916  // Number in range ]-0.5..0.5[. These always round to +/-zero.
7917  if (sign) return isolate->heap()->minus_zero_value();
7918  return Smi::FromInt(0);
7919  }
7920 
7921  // We compare with kSmiValueSize - 2 because (2^30 - 0.1) has exponent 29 and
7922  // should be rounded to 2^30, which is not smi (for 31-bit smis, similar
7923  // argument holds for 32-bit smis).
7924  if (!sign && exponent < kSmiValueSize - 2) {
7925  return Smi::FromInt(static_cast<int>(value + 0.5));
7926  }
7927 
7928  // If the magnitude is big enough, there's no place for fraction part. If we
7929  // try to add 0.5 to this number, 1.0 will be added instead.
7930  if (exponent >= 52) {
7931  return number;
7932  }
7933 
7934  if (sign && value >= -0.5) return isolate->heap()->minus_zero_value();
7935 
7936  // Do not call NumberFromDouble() to avoid extra checks.
7937  return isolate->heap()->AllocateHeapNumber(std::floor(value + 0.5));
7938 }
7939 
7940 
7941 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sqrt) {
7942  SealHandleScope shs(isolate);
7943  ASSERT(args.length() == 1);
7944  isolate->counters()->math_sqrt()->Increment();
7945 
7947  return isolate->heap()->AllocateHeapNumber(fast_sqrt(x));
7948 }
7949 
7950 
7951 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_fround) {
7952  SealHandleScope shs(isolate);
7953  ASSERT(args.length() == 1);
7954 
7956  float xf = static_cast<float>(x);
7957  return isolate->heap()->AllocateHeapNumber(xf);
7958 }
7959 
7960 
7961 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateMakeDay) {
7962  SealHandleScope shs(isolate);
7963  ASSERT(args.length() == 2);
7964 
7965  CONVERT_SMI_ARG_CHECKED(year, 0);
7966  CONVERT_SMI_ARG_CHECKED(month, 1);
7967 
7968  return Smi::FromInt(isolate->date_cache()->DaysFromYearMonth(year, month));
7969 }
7970 
7971 
7972 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateSetValue) {
7973  HandleScope scope(isolate);
7974  ASSERT(args.length() == 3);
7975 
7977  CONVERT_DOUBLE_ARG_CHECKED(time, 1);
7978  CONVERT_SMI_ARG_CHECKED(is_utc, 2);
7979 
7980  DateCache* date_cache = isolate->date_cache();
7981 
7982  Object* value = NULL;
7983  bool is_value_nan = false;
7984  if (std::isnan(time)) {
7985  value = isolate->heap()->nan_value();
7986  is_value_nan = true;
7987  } else if (!is_utc &&
7990  value = isolate->heap()->nan_value();
7991  is_value_nan = true;
7992  } else {
7993  time = is_utc ? time : date_cache->ToUTC(static_cast<int64_t>(time));
7994  if (time < -DateCache::kMaxTimeInMs ||
7995  time > DateCache::kMaxTimeInMs) {
7996  value = isolate->heap()->nan_value();
7997  is_value_nan = true;
7998  } else {
7999  MaybeObject* maybe_result =
8000  isolate->heap()->AllocateHeapNumber(DoubleToInteger(time));
8001  if (!maybe_result->ToObject(&value)) return maybe_result;
8002  }
8003  }
8004  date->SetValue(value, is_value_nan);
8005  return value;
8006 }
8007 
8008 
8009 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewArgumentsFast) {
8010  HandleScope scope(isolate);
8011  ASSERT(args.length() == 3);
8012 
8013  Handle<JSFunction> callee = args.at<JSFunction>(0);
8014  Object** parameters = reinterpret_cast<Object**>(args[1]);
8015  const int argument_count = Smi::cast(args[2])->value();
8016 
8017  Handle<JSObject> result =
8018  isolate->factory()->NewArgumentsObject(callee, argument_count);
8019  // Allocate the elements if needed.
8020  int parameter_count = callee->shared()->formal_parameter_count();
8021  if (argument_count > 0) {
8022  if (parameter_count > 0) {
8023  int mapped_count = Min(argument_count, parameter_count);
8024  Handle<FixedArray> parameter_map =
8025  isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
8026  parameter_map->set_map(
8027  isolate->heap()->sloppy_arguments_elements_map());
8028 
8029  Handle<Map> old_map(result->map());
8030  Handle<Map> new_map = isolate->factory()->CopyMap(old_map);
8031  new_map->set_elements_kind(SLOPPY_ARGUMENTS_ELEMENTS);
8032 
8033  result->set_map(*new_map);
8034  result->set_elements(*parameter_map);
8035 
8036  // Store the context and the arguments array at the beginning of the
8037  // parameter map.
8038  Handle<Context> context(isolate->context());
8039  Handle<FixedArray> arguments =
8040  isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
8041  parameter_map->set(0, *context);
8042  parameter_map->set(1, *arguments);
8043 
8044  // Loop over the actual parameters backwards.
8045  int index = argument_count - 1;
8046  while (index >= mapped_count) {
8047  // These go directly in the arguments array and have no
8048  // corresponding slot in the parameter map.
8049  arguments->set(index, *(parameters - index - 1));
8050  --index;
8051  }
8052 
8053  Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
8054  while (index >= 0) {
8055  // Detect duplicate names to the right in the parameter list.
8056  Handle<String> name(scope_info->ParameterName(index));
8057  int context_local_count = scope_info->ContextLocalCount();
8058  bool duplicate = false;
8059  for (int j = index + 1; j < parameter_count; ++j) {
8060  if (scope_info->ParameterName(j) == *name) {
8061  duplicate = true;
8062  break;
8063  }
8064  }
8065 
8066  if (duplicate) {
8067  // This goes directly in the arguments array with a hole in the
8068  // parameter map.
8069  arguments->set(index, *(parameters - index - 1));
8070  parameter_map->set_the_hole(index + 2);
8071  } else {
8072  // The context index goes in the parameter map with a hole in the
8073  // arguments array.
8074  int context_index = -1;
8075  for (int j = 0; j < context_local_count; ++j) {
8076  if (scope_info->ContextLocalName(j) == *name) {
8077  context_index = j;
8078  break;
8079  }
8080  }
8081  ASSERT(context_index >= 0);
8082  arguments->set_the_hole(index);
8083  parameter_map->set(index + 2, Smi::FromInt(
8084  Context::MIN_CONTEXT_SLOTS + context_index));
8085  }
8086 
8087  --index;
8088  }
8089  } else {
8090  // If there is no aliasing, the arguments object elements are not
8091  // special in any way.
8092  Handle<FixedArray> elements =
8093  isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
8094  result->set_elements(*elements);
8095  for (int i = 0; i < argument_count; ++i) {
8096  elements->set(i, *(parameters - i - 1));
8097  }
8098  }
8099  }
8100  return *result;
8101 }
8102 
8103 
8104 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewStrictArgumentsFast) {
8105  SealHandleScope shs(isolate);
8106  ASSERT(args.length() == 3);
8107 
8108  JSFunction* callee = JSFunction::cast(args[0]);
8109  Object** parameters = reinterpret_cast<Object**>(args[1]);
8110  const int length = args.smi_at(2);
8111 
8112  Object* result;
8113  { MaybeObject* maybe_result =
8114  isolate->heap()->AllocateArgumentsObject(callee, length);
8115  if (!maybe_result->ToObject(&result)) return maybe_result;
8116  }
8117  // Allocate the elements if needed.
8118  if (length > 0) {
8119  // Allocate the fixed array.
8120  FixedArray* array;
8121  { MaybeObject* maybe_obj =
8122  isolate->heap()->AllocateUninitializedFixedArray(length);
8123  if (!maybe_obj->To(&array)) return maybe_obj;
8124  }
8125 
8126  DisallowHeapAllocation no_gc;
8127  WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
8128  for (int i = 0; i < length; i++) {
8129  array->set(i, *--parameters, mode);
8130  }
8131  JSObject::cast(result)->set_elements(array);
8132  }
8133  return result;
8134 }
8135 
8136 
8137 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewClosureFromStubFailure) {
8138  HandleScope scope(isolate);
8139  ASSERT(args.length() == 1);
8141  Handle<Context> context(isolate->context());
8142  PretenureFlag pretenure_flag = NOT_TENURED;
8143  Handle<JSFunction> result =
8144  isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
8145  context,
8146  pretenure_flag);
8147  return *result;
8148 }
8149 
8150 
8151 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewClosure) {
8152  HandleScope scope(isolate);
8153  ASSERT(args.length() == 3);
8154  CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
8156  CONVERT_BOOLEAN_ARG_CHECKED(pretenure, 2);
8157 
8158  // The caller ensures that we pretenure closures that are assigned
8159  // directly to properties.
8160  PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
8161  Handle<JSFunction> result =
8162  isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
8163  context,
8164  pretenure_flag);
8165  return *result;
8166 }
8167 
8168 
8169 // Find the arguments of the JavaScript function invocation that called
8170 // into C++ code. Collect these in a newly allocated array of handles (possibly
8171 // prefixed by a number of empty handles).
8172 static SmartArrayPointer<Handle<Object> > GetCallerArguments(
8173  Isolate* isolate,
8174  int prefix_argc,
8175  int* total_argc) {
8176  // Find frame containing arguments passed to the caller.
8177  JavaScriptFrameIterator it(isolate);
8178  JavaScriptFrame* frame = it.frame();
8179  List<JSFunction*> functions(2);
8180  frame->GetFunctions(&functions);
8181  if (functions.length() > 1) {
8182  int inlined_jsframe_index = functions.length() - 1;
8183  JSFunction* inlined_function = functions[inlined_jsframe_index];
8184  SlotRefValueBuilder slot_refs(
8185  frame,
8186  inlined_jsframe_index,
8187  inlined_function->shared()->formal_parameter_count());
8188 
8189  int args_count = slot_refs.args_length();
8190 
8191  *total_argc = prefix_argc + args_count;
8192  SmartArrayPointer<Handle<Object> > param_data(
8193  NewArray<Handle<Object> >(*total_argc));
8194  slot_refs.Prepare(isolate);
8195  for (int i = 0; i < args_count; i++) {
8196  Handle<Object> val = slot_refs.GetNext(isolate, 0);
8197  param_data[prefix_argc + i] = val;
8198  }
8199  slot_refs.Finish(isolate);
8200 
8201  return param_data;
8202  } else {
8203  it.AdvanceToArgumentsFrame();
8204  frame = it.frame();
8205  int args_count = frame->ComputeParametersCount();
8206 
8207  *total_argc = prefix_argc + args_count;
8208  SmartArrayPointer<Handle<Object> > param_data(
8209  NewArray<Handle<Object> >(*total_argc));
8210  for (int i = 0; i < args_count; i++) {
8211  Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate);
8212  param_data[prefix_argc + i] = val;
8213  }
8214  return param_data;
8215  }
8216 }
8217 
8218 
8219 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionBindArguments) {
8220  HandleScope scope(isolate);
8221  ASSERT(args.length() == 4);
8222  CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0);
8223  RUNTIME_ASSERT(args[3]->IsNumber());
8224  Handle<Object> bindee = args.at<Object>(1);
8225 
8226  // TODO(lrn): Create bound function in C++ code from premade shared info.
8227  bound_function->shared()->set_bound(true);
8228  // Get all arguments of calling function (Function.prototype.bind).
8229  int argc = 0;
8230  SmartArrayPointer<Handle<Object> > arguments =
8231  GetCallerArguments(isolate, 0, &argc);
8232  // Don't count the this-arg.
8233  if (argc > 0) {
8234  ASSERT(*arguments[0] == args[2]);
8235  argc--;
8236  } else {
8237  ASSERT(args[2]->IsUndefined());
8238  }
8239  // Initialize array of bindings (function, this, and any existing arguments
8240  // if the function was already bound).
8241  Handle<FixedArray> new_bindings;
8242  int i;
8243  if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) {
8244  Handle<FixedArray> old_bindings(
8245  JSFunction::cast(*bindee)->function_bindings());
8246  new_bindings =
8247  isolate->factory()->NewFixedArray(old_bindings->length() + argc);
8248  bindee = Handle<Object>(old_bindings->get(JSFunction::kBoundFunctionIndex),
8249  isolate);
8250  i = 0;
8251  for (int n = old_bindings->length(); i < n; i++) {
8252  new_bindings->set(i, old_bindings->get(i));
8253  }
8254  } else {
8255  int array_size = JSFunction::kBoundArgumentsStartIndex + argc;
8256  new_bindings = isolate->factory()->NewFixedArray(array_size);
8257  new_bindings->set(JSFunction::kBoundFunctionIndex, *bindee);
8258  new_bindings->set(JSFunction::kBoundThisIndex, args[2]);
8259  i = 2;
8260  }
8261  // Copy arguments, skipping the first which is "this_arg".
8262  for (int j = 0; j < argc; j++, i++) {
8263  new_bindings->set(i, *arguments[j + 1]);
8264  }
8265  new_bindings->set_map_no_write_barrier(
8266  isolate->heap()->fixed_cow_array_map());
8267  bound_function->set_function_bindings(*new_bindings);
8268 
8269  // Update length.
8270  Handle<String> length_string = isolate->factory()->length_string();
8271  Handle<Object> new_length(args.at<Object>(3));
8272  PropertyAttributes attr =
8273  static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY);
8274  ForceSetProperty(bound_function, length_string, new_length, attr);
8275  return *bound_function;
8276 }
8277 
8278 
8279 RUNTIME_FUNCTION(MaybeObject*, Runtime_BoundFunctionGetBindings) {
8280  HandleScope handles(isolate);
8281  ASSERT(args.length() == 1);
8282  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0);
8283  if (callable->IsJSFunction()) {
8284  Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
8285  if (function->shared()->bound()) {
8286  Handle<FixedArray> bindings(function->function_bindings());
8287  ASSERT(bindings->map() == isolate->heap()->fixed_cow_array_map());
8288  return *isolate->factory()->NewJSArrayWithElements(bindings);
8289  }
8290  }
8291  return isolate->heap()->undefined_value();
8292 }
8293 
8294 
8295 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObjectFromBound) {
8296  HandleScope scope(isolate);
8297  ASSERT(args.length() == 1);
8298  // First argument is a function to use as a constructor.
8299  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8300  RUNTIME_ASSERT(function->shared()->bound());
8301 
8302  // The argument is a bound function. Extract its bound arguments
8303  // and callable.
8304  Handle<FixedArray> bound_args =
8305  Handle<FixedArray>(FixedArray::cast(function->function_bindings()));
8306  int bound_argc = bound_args->length() - JSFunction::kBoundArgumentsStartIndex;
8307  Handle<Object> bound_function(
8309  isolate);
8310  ASSERT(!bound_function->IsJSFunction() ||
8311  !Handle<JSFunction>::cast(bound_function)->shared()->bound());
8312 
8313  int total_argc = 0;
8314  SmartArrayPointer<Handle<Object> > param_data =
8315  GetCallerArguments(isolate, bound_argc, &total_argc);
8316  for (int i = 0; i < bound_argc; i++) {
8317  param_data[i] = Handle<Object>(bound_args->get(
8319  }
8320 
8321  if (!bound_function->IsJSFunction()) {
8322  bool exception_thrown;
8323  bound_function = Execution::TryGetConstructorDelegate(isolate,
8324  bound_function,
8325  &exception_thrown);
8326  if (exception_thrown) return Failure::Exception();
8327  }
8328  ASSERT(bound_function->IsJSFunction());
8329 
8330  bool exception = false;
8331  Handle<Object> result =
8332  Execution::New(Handle<JSFunction>::cast(bound_function),
8333  total_argc, param_data.get(), &exception);
8334  if (exception) {
8335  return Failure::Exception();
8336  }
8337  ASSERT(!result.is_null());
8338  return *result;
8339 }
8340 
8341 
8342 static MaybeObject* Runtime_NewObjectHelper(Isolate* isolate,
8343  Handle<Object> constructor,
8344  Handle<AllocationSite> site) {
8345  // If the constructor isn't a proper function we throw a type error.
8346  if (!constructor->IsJSFunction()) {
8347  Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
8348  Handle<Object> type_error =
8349  isolate->factory()->NewTypeError("not_constructor", arguments);
8350  return isolate->Throw(*type_error);
8351  }
8352 
8353  Handle<JSFunction> function = Handle<JSFunction>::cast(constructor);
8354 
8355  // If function should not have prototype, construction is not allowed. In this
8356  // case generated code bailouts here, since function has no initial_map.
8357  if (!function->should_have_prototype() && !function->shared()->bound()) {
8358  Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
8359  Handle<Object> type_error =
8360  isolate->factory()->NewTypeError("not_constructor", arguments);
8361  return isolate->Throw(*type_error);
8362  }
8363 
8364 #ifdef ENABLE_DEBUGGER_SUPPORT
8365  Debug* debug = isolate->debug();
8366  // Handle stepping into constructors if step into is active.
8367  if (debug->StepInActive()) {
8368  debug->HandleStepIn(function, Handle<Object>::null(), 0, true);
8369  }
8370 #endif
8371 
8372  if (function->has_initial_map()) {
8373  if (function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
8374  // The 'Function' function ignores the receiver object when
8375  // called using 'new' and creates a new JSFunction object that
8376  // is returned. The receiver object is only used for error
8377  // reporting if an error occurs when constructing the new
8378  // JSFunction. Factory::NewJSObject() should not be used to
8379  // allocate JSFunctions since it does not properly initialize
8380  // the shared part of the function. Since the receiver is
8381  // ignored anyway, we use the global object as the receiver
8382  // instead of a new JSFunction object. This way, errors are
8383  // reported the same way whether or not 'Function' is called
8384  // using 'new'.
8385  return isolate->context()->global_object();
8386  }
8387  }
8388 
8389  // The function should be compiled for the optimization hints to be
8390  // available.
8392 
8393  Handle<SharedFunctionInfo> shared(function->shared(), isolate);
8394  if (!function->has_initial_map() &&
8395  shared->IsInobjectSlackTrackingInProgress()) {
8396  // The tracking is already in progress for another function. We can only
8397  // track one initial_map at a time, so we force the completion before the
8398  // function is called as a constructor for the first time.
8399  shared->CompleteInobjectSlackTracking();
8400  }
8401 
8402  Handle<JSObject> result;
8403  if (site.is_null()) {
8404  result = isolate->factory()->NewJSObject(function);
8405  } else {
8406  result = isolate->factory()->NewJSObjectWithMemento(function, site);
8407  }
8408  RETURN_IF_EMPTY_HANDLE(isolate, result);
8409 
8410  isolate->counters()->constructed_objects()->Increment();
8411  isolate->counters()->constructed_objects_runtime()->Increment();
8412 
8413  return *result;
8414 }
8415 
8416 
8417 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewObject) {
8418  HandleScope scope(isolate);
8419  ASSERT(args.length() == 1);
8420 
8421  Handle<Object> constructor = args.at<Object>(0);
8422  return Runtime_NewObjectHelper(isolate,
8423  constructor,
8425 }
8426 
8427 
8428 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewObjectWithAllocationSite) {
8429  HandleScope scope(isolate);
8430  ASSERT(args.length() == 2);
8431 
8432  Handle<Object> constructor = args.at<Object>(1);
8433  Handle<Object> feedback = args.at<Object>(0);
8435  if (feedback->IsAllocationSite()) {
8436  // The feedback can be an AllocationSite or undefined.
8437  site = Handle<AllocationSite>::cast(feedback);
8438  }
8439  return Runtime_NewObjectHelper(isolate,
8440  constructor,
8441  site);
8442 }
8443 
8444 
8445 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_FinalizeInstanceSize) {
8446  HandleScope scope(isolate);
8447  ASSERT(args.length() == 1);
8448 
8449  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8450  function->shared()->CompleteInobjectSlackTracking();
8451 
8452  return isolate->heap()->undefined_value();
8453 }
8454 
8455 
8456 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_CompileUnoptimized) {
8457  HandleScope scope(isolate);
8458  ASSERT(args.length() == 1);
8459 
8460  Handle<JSFunction> function = args.at<JSFunction>(0);
8461 #ifdef DEBUG
8462  if (FLAG_trace_lazy && !function->shared()->is_compiled()) {
8463  PrintF("[unoptimized: ");
8464  function->PrintName();
8465  PrintF("]\n");
8466  }
8467 #endif
8468 
8469  // Compile the target function.
8470  ASSERT(function->shared()->allows_lazy_compilation());
8471 
8473  RETURN_IF_EMPTY_HANDLE(isolate, code);
8474  function->ReplaceCode(*code);
8475 
8476  // All done. Return the compiled code.
8477  ASSERT(function->is_compiled());
8478  ASSERT(function->code()->kind() == Code::FUNCTION ||
8479  (FLAG_always_opt &&
8480  function->code()->kind() == Code::OPTIMIZED_FUNCTION));
8481  return *code;
8482 }
8483 
8484 
8485 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_CompileOptimized) {
8486  HandleScope scope(isolate);
8487  ASSERT(args.length() == 2);
8488  Handle<JSFunction> function = args.at<JSFunction>(0);
8489  CONVERT_BOOLEAN_ARG_CHECKED(concurrent, 1);
8490 
8491  Handle<Code> unoptimized(function->shared()->code());
8492  if (!function->shared()->is_compiled()) {
8493  // If the function is not compiled, do not optimize.
8494  // This can happen if the debugger is activated and
8495  // the function is returned to the not compiled state.
8496  // TODO(yangguo): reconsider this.
8497  function->ReplaceCode(function->shared()->code());
8498  } else if (!isolate->use_crankshaft() ||
8499  function->shared()->optimization_disabled() ||
8500  isolate->DebuggerHasBreakPoints()) {
8501  // If the function is not optimizable or debugger is active continue
8502  // using the code from the full compiler.
8503  if (FLAG_trace_opt) {
8504  PrintF("[failed to optimize ");
8505  function->PrintName();
8506  PrintF(": is code optimizable: %s, is debugger enabled: %s]\n",
8507  function->shared()->optimization_disabled() ? "F" : "T",
8508  isolate->DebuggerHasBreakPoints() ? "T" : "F");
8509  }
8510  function->ReplaceCode(*unoptimized);
8511  } else {
8514  Handle<Code> code = Compiler::GetOptimizedCode(function, unoptimized, mode);
8515  function->ReplaceCode(code.is_null() ? *unoptimized : *code);
8516  }
8517 
8518  ASSERT(function->code()->kind() == Code::FUNCTION ||
8519  function->code()->kind() == Code::OPTIMIZED_FUNCTION ||
8520  function->IsInOptimizationQueue());
8521  return function->code();
8522 }
8523 
8524 
8526  public:
8529 
8531  : code_(code),
8533 
8534  void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
8535  JavaScriptFrameIterator it(isolate, top);
8536  VisitFrames(&it);
8537  }
8538 
8539  void VisitFrames(JavaScriptFrameIterator* it) {
8540  for (; !it->done(); it->Advance()) {
8541  JavaScriptFrame* frame = it->frame();
8542  if (code_->contains(frame->pc())) has_code_activations_ = true;
8543  }
8544  }
8545 };
8546 
8547 
8548 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NotifyStubFailure) {
8549  HandleScope scope(isolate);
8550  ASSERT(args.length() == 0);
8551  Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8552  ASSERT(AllowHeapAllocation::IsAllowed());
8553  delete deoptimizer;
8554  return isolate->heap()->undefined_value();
8555 }
8556 
8557 
8558 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NotifyDeoptimized) {
8559  HandleScope scope(isolate);
8560  ASSERT(args.length() == 1);
8561  RUNTIME_ASSERT(args[0]->IsSmi());
8563  static_cast<Deoptimizer::BailoutType>(args.smi_at(0));
8564  Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8565  ASSERT(AllowHeapAllocation::IsAllowed());
8566 
8567  Handle<JSFunction> function = deoptimizer->function();
8568  Handle<Code> optimized_code = deoptimizer->compiled_code();
8569 
8570  ASSERT(optimized_code->kind() == Code::OPTIMIZED_FUNCTION);
8571  ASSERT(type == deoptimizer->bailout_type());
8572 
8573  // Make sure to materialize objects before causing any allocation.
8574  JavaScriptFrameIterator it(isolate);
8575  deoptimizer->MaterializeHeapObjects(&it);
8576  delete deoptimizer;
8577 
8578  JavaScriptFrame* frame = it.frame();
8579  RUNTIME_ASSERT(frame->function()->IsJSFunction());
8580  ASSERT(frame->function() == *function);
8581 
8582  // Avoid doing too much work when running with --always-opt and keep
8583  // the optimized code around.
8584  if (FLAG_always_opt || type == Deoptimizer::LAZY) {
8585  return isolate->heap()->undefined_value();
8586  }
8587 
8588  // Search for other activations of the same function and code.
8589  ActivationsFinder activations_finder(*optimized_code);
8590  activations_finder.VisitFrames(&it);
8591  isolate->thread_manager()->IterateArchivedThreads(&activations_finder);
8592 
8593  if (!activations_finder.has_code_activations_) {
8594  if (function->code() == *optimized_code) {
8595  if (FLAG_trace_deopt) {
8596  PrintF("[removing optimized code for: ");
8597  function->PrintName();
8598  PrintF("]\n");
8599  }
8600  function->ReplaceCode(function->shared()->code());
8601  // Evict optimized code for this function from the cache so that it
8602  // doesn't get used for new closures.
8603  function->shared()->EvictFromOptimizedCodeMap(*optimized_code,
8604  "notify deoptimized");
8605  }
8606  } else {
8607  // TODO(titzer): we should probably do DeoptimizeCodeList(code)
8608  // unconditionally if the code is not already marked for deoptimization.
8609  // If there is an index by shared function info, all the better.
8611  }
8612 
8613  return isolate->heap()->undefined_value();
8614 }
8615 
8616 
8617 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeoptimizeFunction) {
8618  HandleScope scope(isolate);
8619  ASSERT(args.length() == 1);
8620  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8621  if (!function->IsOptimized()) return isolate->heap()->undefined_value();
8622 
8624 
8625  return isolate->heap()->undefined_value();
8626 }
8627 
8628 
8629 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearFunctionTypeFeedback) {
8630  HandleScope scope(isolate);
8631  ASSERT(args.length() == 1);
8632  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8633  Code* unoptimized = function->shared()->code();
8634  if (unoptimized->kind() == Code::FUNCTION) {
8635  unoptimized->ClearInlineCaches();
8636  unoptimized->ClearTypeFeedbackInfo(isolate->heap());
8637  }
8638  return isolate->heap()->undefined_value();
8639 }
8640 
8641 
8642 RUNTIME_FUNCTION(MaybeObject*, Runtime_RunningInSimulator) {
8643  SealHandleScope shs(isolate);
8644 #if defined(USE_SIMULATOR)
8645  return isolate->heap()->true_value();
8646 #else
8647  return isolate->heap()->false_value();
8648 #endif
8649 }
8650 
8651 
8652 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsConcurrentRecompilationSupported) {
8653  HandleScope scope(isolate);
8654  return isolate->concurrent_recompilation_enabled()
8655  ? isolate->heap()->true_value() : isolate->heap()->false_value();
8656 }
8657 
8658 
8659 RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) {
8660  HandleScope scope(isolate);
8661  RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
8662  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8663 
8664  if (!function->IsOptimizable() &&
8665  !function->IsMarkedForConcurrentOptimization() &&
8666  !function->IsInOptimizationQueue()) {
8667  return isolate->heap()->undefined_value();
8668  }
8669 
8670  function->MarkForOptimization();
8671 
8672  Code* unoptimized = function->shared()->code();
8673  if (args.length() == 2 &&
8674  unoptimized->kind() == Code::FUNCTION) {
8676  if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("osr"))) {
8677  // Start patching from the currently patched loop nesting level.
8678  int current_level = unoptimized->allow_osr_at_loop_nesting_level();
8679  ASSERT(BackEdgeTable::Verify(isolate, unoptimized, current_level));
8680  for (int i = current_level + 1; i <= Code::kMaxLoopNestingMarker; i++) {
8681  unoptimized->set_allow_osr_at_loop_nesting_level(i);
8682  isolate->runtime_profiler()->AttemptOnStackReplacement(*function);
8683  }
8684  } else if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("concurrent")) &&
8685  isolate->concurrent_recompilation_enabled()) {
8686  function->MarkForConcurrentOptimization();
8687  }
8688  }
8689 
8690  return isolate->heap()->undefined_value();
8691 }
8692 
8693 
8694 RUNTIME_FUNCTION(MaybeObject*, Runtime_NeverOptimizeFunction) {
8695  HandleScope scope(isolate);
8696  ASSERT(args.length() == 1);
8697  CONVERT_ARG_CHECKED(JSFunction, function, 0);
8698  function->shared()->set_optimization_disabled(true);
8699  return isolate->heap()->undefined_value();
8700 }
8701 
8702 
8703 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) {
8704  HandleScope scope(isolate);
8705  RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
8706  if (!isolate->use_crankshaft()) {
8707  return Smi::FromInt(4); // 4 == "never".
8708  }
8709  bool sync_with_compiler_thread = true;
8710  if (args.length() == 2) {
8712  if (sync->IsOneByteEqualTo(STATIC_ASCII_VECTOR("no sync"))) {
8713  sync_with_compiler_thread = false;
8714  }
8715  }
8716  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8717  if (isolate->concurrent_recompilation_enabled() &&
8718  sync_with_compiler_thread) {
8719  while (function->IsInOptimizationQueue()) {
8720  isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
8721  OS::Sleep(50);
8722  }
8723  }
8724  if (FLAG_always_opt) {
8725  // We may have always opt, but that is more best-effort than a real
8726  // promise, so we still say "no" if it is not optimized.
8727  return function->IsOptimized() ? Smi::FromInt(3) // 3 == "always".
8728  : Smi::FromInt(2); // 2 == "no".
8729  }
8730  if (FLAG_deopt_every_n_times) {
8731  return Smi::FromInt(6); // 6 == "maybe deopted".
8732  }
8733  return function->IsOptimized() ? Smi::FromInt(1) // 1 == "yes".
8734  : Smi::FromInt(2); // 2 == "no".
8735 }
8736 
8737 
8738 RUNTIME_FUNCTION(MaybeObject*, Runtime_UnblockConcurrentRecompilation) {
8739  RUNTIME_ASSERT(FLAG_block_concurrent_recompilation);
8740  RUNTIME_ASSERT(isolate->concurrent_recompilation_enabled());
8741  isolate->optimizing_compiler_thread()->Unblock();
8742  return isolate->heap()->undefined_value();
8743 }
8744 
8745 
8746 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationCount) {
8747  HandleScope scope(isolate);
8748  ASSERT(args.length() == 1);
8749  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8750  return Smi::FromInt(function->shared()->opt_count());
8751 }
8752 
8753 
8754 static bool IsSuitableForOnStackReplacement(Isolate* isolate,
8755  Handle<JSFunction> function,
8756  Handle<Code> current_code) {
8757  // Keep track of whether we've succeeded in optimizing.
8758  if (!isolate->use_crankshaft() || !current_code->optimizable()) return false;
8759  // If we are trying to do OSR when there are already optimized
8760  // activations of the function, it means (a) the function is directly or
8761  // indirectly recursive and (b) an optimized invocation has been
8762  // deoptimized so that we are currently in an unoptimized activation.
8763  // Check for optimized activations of this function.
8764  for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
8765  JavaScriptFrame* frame = it.frame();
8766  if (frame->is_optimized() && frame->function() == *function) return false;
8767  }
8768 
8769  return true;
8770 }
8771 
8772 
8773 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
8774  HandleScope scope(isolate);
8775  ASSERT(args.length() == 1);
8776  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8777  Handle<Code> caller_code(function->shared()->code());
8778 
8779  // We're not prepared to handle a function with arguments object.
8780  ASSERT(!function->shared()->uses_arguments());
8781 
8782  // Passing the PC in the javascript frame from the caller directly is
8783  // not GC safe, so we walk the stack to get it.
8784  JavaScriptFrameIterator it(isolate);
8785  JavaScriptFrame* frame = it.frame();
8786  if (!caller_code->contains(frame->pc())) {
8787  // Code on the stack may not be the code object referenced by the shared
8788  // function info. It may have been replaced to include deoptimization data.
8789  caller_code = Handle<Code>(frame->LookupCode());
8790  }
8791 
8792  uint32_t pc_offset = static_cast<uint32_t>(
8793  frame->pc() - caller_code->instruction_start());
8794 
8795 #ifdef DEBUG
8796  ASSERT_EQ(frame->function(), *function);
8797  ASSERT_EQ(frame->LookupCode(), *caller_code);
8798  ASSERT(caller_code->contains(frame->pc()));
8799 #endif // DEBUG
8800 
8801 
8802  BailoutId ast_id = caller_code->TranslatePcOffsetToAstId(pc_offset);
8803  ASSERT(!ast_id.IsNone());
8804 
8805  Compiler::ConcurrencyMode mode = isolate->concurrent_osr_enabled()
8807  Handle<Code> result = Handle<Code>::null();
8808 
8809  OptimizedCompileJob* job = NULL;
8810  if (mode == Compiler::CONCURRENT) {
8811  // Gate the OSR entry with a stack check.
8812  BackEdgeTable::AddStackCheck(caller_code, pc_offset);
8813  // Poll already queued compilation jobs.
8814  OptimizingCompilerThread* thread = isolate->optimizing_compiler_thread();
8815  if (thread->IsQueuedForOSR(function, ast_id)) {
8816  if (FLAG_trace_osr) {
8817  PrintF("[OSR - Still waiting for queued: ");
8818  function->PrintName();
8819  PrintF(" at AST id %d]\n", ast_id.ToInt());
8820  }
8821  return NULL;
8822  }
8823 
8824  job = thread->FindReadyOSRCandidate(function, ast_id);
8825  }
8826 
8827  if (job != NULL) {
8828  if (FLAG_trace_osr) {
8829  PrintF("[OSR - Found ready: ");
8830  function->PrintName();
8831  PrintF(" at AST id %d]\n", ast_id.ToInt());
8832  }
8834  } else if (result.is_null() &&
8835  IsSuitableForOnStackReplacement(isolate, function, caller_code)) {
8836  if (FLAG_trace_osr) {
8837  PrintF("[OSR - Compiling: ");
8838  function->PrintName();
8839  PrintF(" at AST id %d]\n", ast_id.ToInt());
8840  }
8841  result = Compiler::GetOptimizedCode(function, caller_code, mode, ast_id);
8842  if (result.is_identical_to(isolate->builtins()->InOptimizationQueue())) {
8843  // Optimization is queued. Return to check later.
8844  return NULL;
8845  }
8846  }
8847 
8848  // Revert the patched back edge table, regardless of whether OSR succeeds.
8849  BackEdgeTable::Revert(isolate, *caller_code);
8850 
8851  // Check whether we ended up with usable optimized code.
8852  if (!result.is_null() && result->kind() == Code::OPTIMIZED_FUNCTION) {
8853  DeoptimizationInputData* data =
8854  DeoptimizationInputData::cast(result->deoptimization_data());
8855 
8856  if (data->OsrPcOffset()->value() >= 0) {
8857  ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id);
8858  if (FLAG_trace_osr) {
8859  PrintF("[OSR - Entry at AST id %d, offset %d in optimized code]\n",
8860  ast_id.ToInt(), data->OsrPcOffset()->value());
8861  }
8862  // TODO(titzer): this is a massive hack to make the deopt counts
8863  // match. Fix heuristics for reenabling optimizations!
8864  function->shared()->increment_deopt_count();
8865 
8866  // TODO(titzer): Do not install code into the function.
8867  function->ReplaceCode(*result);
8868  return *result;
8869  }
8870  }
8871 
8872  // Failed.
8873  if (FLAG_trace_osr) {
8874  PrintF("[OSR - Failed: ");
8875  function->PrintName();
8876  PrintF(" at AST id %d]\n", ast_id.ToInt());
8877  }
8878 
8879  if (!function->IsOptimized()) {
8880  function->ReplaceCode(function->shared()->code());
8881  }
8882  return NULL;
8883 }
8884 
8885 
8886 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAllocationTimeout) {
8887  SealHandleScope shs(isolate);
8888  ASSERT(args.length() == 2 || args.length() == 3);
8889 #ifdef DEBUG
8890  CONVERT_SMI_ARG_CHECKED(interval, 0);
8891  CONVERT_SMI_ARG_CHECKED(timeout, 1);
8892  isolate->heap()->set_allocation_timeout(timeout);
8893  FLAG_gc_interval = interval;
8894  if (args.length() == 3) {
8895  // Enable/disable inline allocation if requested.
8896  CONVERT_BOOLEAN_ARG_CHECKED(inline_allocation, 2);
8897  if (inline_allocation) {
8898  isolate->heap()->EnableInlineAllocation();
8899  } else {
8900  isolate->heap()->DisableInlineAllocation();
8901  }
8902  }
8903 #endif
8904  return isolate->heap()->undefined_value();
8905 }
8906 
8907 
8908 RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckIsBootstrapping) {
8909  SealHandleScope shs(isolate);
8910  RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8911  return isolate->heap()->undefined_value();
8912 }
8913 
8914 
8915 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetRootNaN) {
8916  SealHandleScope shs(isolate);
8917  RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8918  return isolate->heap()->nan_value();
8919 }
8920 
8921 
8922 RUNTIME_FUNCTION(MaybeObject*, Runtime_Call) {
8923  HandleScope scope(isolate);
8924  ASSERT(args.length() >= 2);
8925  int argc = args.length() - 2;
8926  CONVERT_ARG_CHECKED(JSReceiver, fun, argc + 1);
8927  Object* receiver = args[0];
8928 
8929  // If there are too many arguments, allocate argv via malloc.
8930  const int argv_small_size = 10;
8931  Handle<Object> argv_small_buffer[argv_small_size];
8932  SmartArrayPointer<Handle<Object> > argv_large_buffer;
8933  Handle<Object>* argv = argv_small_buffer;
8934  if (argc > argv_small_size) {
8935  argv = new Handle<Object>[argc];
8936  if (argv == NULL) return isolate->StackOverflow();
8937  argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8938  }
8939 
8940  for (int i = 0; i < argc; ++i) {
8941  MaybeObject* maybe = args[1 + i];
8942  Object* object;
8943  if (!maybe->To<Object>(&object)) return maybe;
8944  argv[i] = Handle<Object>(object, isolate);
8945  }
8946 
8947  bool threw;
8948  Handle<JSReceiver> hfun(fun);
8949  Handle<Object> hreceiver(receiver, isolate);
8951  isolate, hfun, hreceiver, argc, argv, &threw, true);
8952 
8953  if (threw) return Failure::Exception();
8954  return *result;
8955 }
8956 
8957 
8958 RUNTIME_FUNCTION(MaybeObject*, Runtime_Apply) {
8959  HandleScope scope(isolate);
8960  ASSERT(args.length() == 5);
8962  Handle<Object> receiver = args.at<Object>(1);
8963  CONVERT_ARG_HANDLE_CHECKED(JSObject, arguments, 2);
8964  CONVERT_SMI_ARG_CHECKED(offset, 3);
8965  CONVERT_SMI_ARG_CHECKED(argc, 4);
8966  RUNTIME_ASSERT(offset >= 0);
8967  RUNTIME_ASSERT(argc >= 0);
8968 
8969  // If there are too many arguments, allocate argv via malloc.
8970  const int argv_small_size = 10;
8971  Handle<Object> argv_small_buffer[argv_small_size];
8972  SmartArrayPointer<Handle<Object> > argv_large_buffer;
8973  Handle<Object>* argv = argv_small_buffer;
8974  if (argc > argv_small_size) {
8975  argv = new Handle<Object>[argc];
8976  if (argv == NULL) return isolate->StackOverflow();
8977  argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8978  }
8979 
8980  for (int i = 0; i < argc; ++i) {
8981  argv[i] = Object::GetElement(isolate, arguments, offset + i);
8982  RETURN_IF_EMPTY_HANDLE(isolate, argv[i]);
8983  }
8984 
8985  bool threw;
8987  isolate, fun, receiver, argc, argv, &threw, true);
8988 
8989  if (threw) return Failure::Exception();
8990  return *result;
8991 }
8992 
8993 
8994 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionDelegate) {
8995  HandleScope scope(isolate);
8996  ASSERT(args.length() == 1);
8997  RUNTIME_ASSERT(!args[0]->IsJSFunction());
8998  return *Execution::GetFunctionDelegate(isolate, args.at<Object>(0));
8999 }
9000 
9001 
9002 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) {
9003  HandleScope scope(isolate);
9004  ASSERT(args.length() == 1);
9005  RUNTIME_ASSERT(!args[0]->IsJSFunction());
9006  return *Execution::GetConstructorDelegate(isolate, args.at<Object>(0));
9007 }
9008 
9009 
9010 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewGlobalContext) {
9011  SealHandleScope shs(isolate);
9012  ASSERT(args.length() == 2);
9013 
9014  CONVERT_ARG_CHECKED(JSFunction, function, 0);
9015  CONVERT_ARG_CHECKED(ScopeInfo, scope_info, 1);
9016  Context* result;
9017  MaybeObject* maybe_result =
9018  isolate->heap()->AllocateGlobalContext(function, scope_info);
9019  if (!maybe_result->To(&result)) return maybe_result;
9020 
9021  ASSERT(function->context() == isolate->context());
9022  ASSERT(function->context()->global_object() == result->global_object());
9023  result->global_object()->set_global_context(result);
9024 
9025  return result; // non-failure
9026 }
9027 
9028 
9029 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_NewFunctionContext) {
9030  SealHandleScope shs(isolate);
9031  ASSERT(args.length() == 1);
9032 
9033  CONVERT_ARG_CHECKED(JSFunction, function, 0);
9034  int length = function->shared()->scope_info()->ContextLength();
9035  return isolate->heap()->AllocateFunctionContext(length, function);
9036 }
9037 
9038 
9039 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_PushWithContext) {
9040  SealHandleScope shs(isolate);
9041  ASSERT(args.length() == 2);
9042  JSReceiver* extension_object;
9043  if (args[0]->IsJSReceiver()) {
9044  extension_object = JSReceiver::cast(args[0]);
9045  } else {
9046  // Convert the object to a proper JavaScript object.
9047  MaybeObject* maybe_js_object = args[0]->ToObject(isolate);
9048  if (!maybe_js_object->To(&extension_object)) {
9049  if (Failure::cast(maybe_js_object)->IsInternalError()) {
9050  HandleScope scope(isolate);
9051  Handle<Object> handle = args.at<Object>(0);
9052  Handle<Object> result =
9053  isolate->factory()->NewTypeError("with_expression",
9054  HandleVector(&handle, 1));
9055  return isolate->Throw(*result);
9056  } else {
9057  return maybe_js_object;
9058  }
9059  }
9060  }
9061 
9062  JSFunction* function;
9063  if (args[1]->IsSmi()) {
9064  // A smi sentinel indicates a context nested inside global code rather
9065  // than some function. There is a canonical empty function that can be
9066  // gotten from the native context.
9067  function = isolate->context()->native_context()->closure();
9068  } else {
9069  function = JSFunction::cast(args[1]);
9070  }
9071 
9072  Context* context;
9073  MaybeObject* maybe_context =
9074  isolate->heap()->AllocateWithContext(function,
9075  isolate->context(),
9076  extension_object);
9077  if (!maybe_context->To(&context)) return maybe_context;
9078  isolate->set_context(context);
9079  return context;
9080 }
9081 
9082 
9083 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_PushCatchContext) {
9084  SealHandleScope shs(isolate);
9085  ASSERT(args.length() == 3);
9086  String* name = String::cast(args[0]);
9087  Object* thrown_object = args[1];
9088  JSFunction* function;
9089  if (args[2]->IsSmi()) {
9090  // A smi sentinel indicates a context nested inside global code rather
9091  // than some function. There is a canonical empty function that can be
9092  // gotten from the native context.
9093  function = isolate->context()->native_context()->closure();
9094  } else {
9095  function = JSFunction::cast(args[2]);
9096  }
9097  Context* context;
9098  MaybeObject* maybe_context =
9099  isolate->heap()->AllocateCatchContext(function,
9100  isolate->context(),
9101  name,
9102  thrown_object);
9103  if (!maybe_context->To(&context)) return maybe_context;
9104  isolate->set_context(context);
9105  return context;
9106 }
9107 
9108 
9109 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_PushBlockContext) {
9110  SealHandleScope shs(isolate);
9111  ASSERT(args.length() == 2);
9112  ScopeInfo* scope_info = ScopeInfo::cast(args[0]);
9113  JSFunction* function;
9114  if (args[1]->IsSmi()) {
9115  // A smi sentinel indicates a context nested inside global code rather
9116  // than some function. There is a canonical empty function that can be
9117  // gotten from the native context.
9118  function = isolate->context()->native_context()->closure();
9119  } else {
9120  function = JSFunction::cast(args[1]);
9121  }
9122  Context* context;
9123  MaybeObject* maybe_context =
9124  isolate->heap()->AllocateBlockContext(function,
9125  isolate->context(),
9126  scope_info);
9127  if (!maybe_context->To(&context)) return maybe_context;
9128  isolate->set_context(context);
9129  return context;
9130 }
9131 
9132 
9133 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSModule) {
9134  SealHandleScope shs(isolate);
9135  ASSERT(args.length() == 1);
9136  Object* obj = args[0];
9137  return isolate->heap()->ToBoolean(obj->IsJSModule());
9138 }
9139 
9140 
9141 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_PushModuleContext) {
9142  SealHandleScope shs(isolate);
9143  ASSERT(args.length() == 2);
9144  CONVERT_SMI_ARG_CHECKED(index, 0);
9145 
9146  if (!args[1]->IsScopeInfo()) {
9147  // Module already initialized. Find hosting context and retrieve context.
9148  Context* host = Context::cast(isolate->context())->global_context();
9149  Context* context = Context::cast(host->get(index));
9150  ASSERT(context->previous() == isolate->context());
9151  isolate->set_context(context);
9152  return context;
9153  }
9154 
9155  CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
9156 
9157  // Allocate module context.
9158  HandleScope scope(isolate);
9159  Factory* factory = isolate->factory();
9160  Handle<Context> context = factory->NewModuleContext(scope_info);
9161  Handle<JSModule> module = factory->NewJSModule(context, scope_info);
9162  context->set_module(*module);
9163  Context* previous = isolate->context();
9164  context->set_previous(previous);
9165  context->set_closure(previous->closure());
9166  context->set_global_object(previous->global_object());
9167  isolate->set_context(*context);
9168 
9169  // Find hosting scope and initialize internal variable holding module there.
9170  previous->global_context()->set(index, *context);
9171 
9172  return *context;
9173 }
9174 
9175 
9176 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_DeclareModules) {
9177  HandleScope scope(isolate);
9178  ASSERT(args.length() == 1);
9179  CONVERT_ARG_HANDLE_CHECKED(FixedArray, descriptions, 0);
9180  Context* host_context = isolate->context();
9181 
9182  for (int i = 0; i < descriptions->length(); ++i) {
9183  Handle<ModuleInfo> description(ModuleInfo::cast(descriptions->get(i)));
9184  int host_index = description->host_index();
9185  Handle<Context> context(Context::cast(host_context->get(host_index)));
9186  Handle<JSModule> module(context->module());
9187 
9188  for (int j = 0; j < description->length(); ++j) {
9189  Handle<String> name(description->name(j));
9190  VariableMode mode = description->mode(j);
9191  int index = description->index(j);
9192  switch (mode) {
9193  case VAR:
9194  case LET:
9195  case CONST:
9196  case CONST_LEGACY: {
9197  PropertyAttributes attr =
9199  Handle<AccessorInfo> info =
9200  Accessors::MakeModuleExport(name, index, attr);
9201  Handle<Object> result = JSObject::SetAccessor(module, info);
9202  ASSERT(!(result.is_null() || result->IsUndefined()));
9203  USE(result);
9204  break;
9205  }
9206  case MODULE: {
9207  Object* referenced_context = Context::cast(host_context)->get(index);
9208  Handle<JSModule> value(Context::cast(referenced_context)->module());
9209  JSReceiver::SetProperty(module, name, value, FROZEN, STRICT);
9210  break;
9211  }
9212  case INTERNAL:
9213  case TEMPORARY:
9214  case DYNAMIC:
9215  case DYNAMIC_GLOBAL:
9216  case DYNAMIC_LOCAL:
9217  UNREACHABLE();
9218  }
9219  }
9220 
9222  }
9223 
9224  ASSERT(!isolate->has_pending_exception());
9225  return isolate->heap()->undefined_value();
9226 }
9227 
9228 
9229 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_DeleteContextSlot) {
9230  HandleScope scope(isolate);
9231  ASSERT(args.length() == 2);
9232 
9233  CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
9235 
9236  int index;
9237  PropertyAttributes attributes;
9239  BindingFlags binding_flags;
9240  Handle<Object> holder = context->Lookup(name,
9241  flags,
9242  &index,
9243  &attributes,
9244  &binding_flags);
9245 
9246  // If the slot was not found the result is true.
9247  if (holder.is_null()) {
9248  return isolate->heap()->true_value();
9249  }
9250 
9251  // If the slot was found in a context, it should be DONT_DELETE.
9252  if (holder->IsContext()) {
9253  return isolate->heap()->false_value();
9254  }
9255 
9256  // The slot was found in a JSObject, either a context extension object,
9257  // the global object, or the subject of a with. Try to delete it
9258  // (respecting DONT_DELETE).
9259  Handle<JSObject> object = Handle<JSObject>::cast(holder);
9260  Handle<Object> result = JSReceiver::DeleteProperty(object, name);
9261  RETURN_IF_EMPTY_HANDLE(isolate, result);
9262  return *result;
9263 }
9264 
9265 
9266 // A mechanism to return a pair of Object pointers in registers (if possible).
9267 // How this is achieved is calling convention-dependent.
9268 // All currently supported x86 compiles uses calling conventions that are cdecl
9269 // variants where a 64-bit value is returned in two 32-bit registers
9270 // (edx:eax on ia32, r1:r0 on ARM).
9271 // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax.
9272 // In Win64 calling convention, a struct of two pointers is returned in memory,
9273 // allocated by the caller, and passed as a pointer in a hidden first parameter.
9274 #ifdef V8_HOST_ARCH_64_BIT
9275 struct ObjectPair {
9276  MaybeObject* x;
9277  MaybeObject* y;
9278 };
9279 
9280 
9281 static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
9282  ObjectPair result = {x, y};
9283  // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
9284  // In Win64 they are assigned to a hidden first argument.
9285  return result;
9286 }
9287 #else
9288 typedef uint64_t ObjectPair;
9289 static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
9290  return reinterpret_cast<uint32_t>(x) |
9291  (reinterpret_cast<ObjectPair>(y) << 32);
9292 }
9293 #endif
9294 
9295 
9296 static inline MaybeObject* Unhole(Heap* heap,
9297  MaybeObject* x,
9298  PropertyAttributes attributes) {
9299  ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
9300  USE(attributes);
9301  return x->IsTheHole() ? heap->undefined_value() : x;
9302 }
9303 
9304 
9305 static Object* ComputeReceiverForNonGlobal(Isolate* isolate,
9306  JSObject* holder) {
9307  ASSERT(!holder->IsGlobalObject());
9308  Context* top = isolate->context();
9309  // Get the context extension function.
9310  JSFunction* context_extension_function =
9311  top->native_context()->context_extension_function();
9312  // If the holder isn't a context extension object, we just return it
9313  // as the receiver. This allows arguments objects to be used as
9314  // receivers, but only if they are put in the context scope chain
9315  // explicitly via a with-statement.
9316  Object* constructor = holder->map()->constructor();
9317  if (constructor != context_extension_function) return holder;
9318  // Fall back to using the global object as the implicit receiver if
9319  // the property turns out to be a local variable allocated in a
9320  // context extension object - introduced via eval.
9321  return isolate->heap()->undefined_value();
9322 }
9323 
9324 
9325 static ObjectPair LoadContextSlotHelper(Arguments args,
9326  Isolate* isolate,
9327  bool throw_error) {
9328  HandleScope scope(isolate);
9329  ASSERT_EQ(2, args.length());
9330 
9331  if (!args[0]->IsContext() || !args[1]->IsString()) {
9332  return MakePair(isolate->ThrowIllegalOperation(), NULL);
9333  }
9334  Handle<Context> context = args.at<Context>(0);
9335  Handle<String> name = args.at<String>(1);
9336 
9337  int index;
9338  PropertyAttributes attributes;
9340  BindingFlags binding_flags;
9341  Handle<Object> holder = context->Lookup(name,
9342  flags,
9343  &index,
9344  &attributes,
9345  &binding_flags);
9346  if (isolate->has_pending_exception()) {
9347  return MakePair(Failure::Exception(), NULL);
9348  }
9349 
9350  // If the index is non-negative, the slot has been found in a context.
9351  if (index >= 0) {
9352  ASSERT(holder->IsContext());
9353  // If the "property" we were looking for is a local variable, the
9354  // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
9355  Handle<Object> receiver = isolate->factory()->undefined_value();
9356  Object* value = Context::cast(*holder)->get(index);
9357  // Check for uninitialized bindings.
9358  switch (binding_flags) {
9361  if (value->IsTheHole()) {
9362  Handle<Object> reference_error =
9363  isolate->factory()->NewReferenceError("not_defined",
9364  HandleVector(&name, 1));
9365  return MakePair(isolate->Throw(*reference_error), NULL);
9366  }
9367  // FALLTHROUGH
9371  ASSERT(!value->IsTheHole());
9372  return MakePair(value, *receiver);
9374  return MakePair(Unhole(isolate->heap(), value, attributes), *receiver);
9375  case MISSING_BINDING:
9376  UNREACHABLE();
9377  return MakePair(NULL, NULL);
9378  }
9379  }
9380 
9381  // Otherwise, if the slot was found the holder is a context extension
9382  // object, subject of a with, or a global object. We read the named
9383  // property from it.
9384  if (!holder.is_null()) {
9385  Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
9386  ASSERT(object->IsJSProxy() || JSReceiver::HasProperty(object, name));
9387  // GetProperty below can cause GC.
9388  Handle<Object> receiver_handle(
9389  object->IsGlobalObject()
9390  ? Object::cast(isolate->heap()->undefined_value())
9391  : object->IsJSProxy() ? static_cast<Object*>(*object)
9392  : ComputeReceiverForNonGlobal(isolate, JSObject::cast(*object)),
9393  isolate);
9394 
9395  // No need to unhole the value here. This is taken care of by the
9396  // GetProperty function.
9397  MaybeObject* value = object->GetProperty(*name);
9398  return MakePair(value, *receiver_handle);
9399  }
9400 
9401  if (throw_error) {
9402  // The property doesn't exist - throw exception.
9403  Handle<Object> reference_error =
9404  isolate->factory()->NewReferenceError("not_defined",
9405  HandleVector(&name, 1));
9406  return MakePair(isolate->Throw(*reference_error), NULL);
9407  } else {
9408  // The property doesn't exist - return undefined.
9409  return MakePair(isolate->heap()->undefined_value(),
9410  isolate->heap()->undefined_value());
9411  }
9412 }
9413 
9414 
9415 RUNTIME_FUNCTION(ObjectPair, RuntimeHidden_LoadContextSlot) {
9416  return LoadContextSlotHelper(args, isolate, true);
9417 }
9418 
9419 
9420 RUNTIME_FUNCTION(ObjectPair, RuntimeHidden_LoadContextSlotNoReferenceError) {
9421  return LoadContextSlotHelper(args, isolate, false);
9422 }
9423 
9424 
9425 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StoreContextSlot) {
9426  HandleScope scope(isolate);
9427  ASSERT(args.length() == 4);
9428 
9429  Handle<Object> value(args[0], isolate);
9430  CONVERT_ARG_HANDLE_CHECKED(Context, context, 1);
9432  CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 3);
9433 
9434  int index;
9435  PropertyAttributes attributes;
9437  BindingFlags binding_flags;
9438  Handle<Object> holder = context->Lookup(name,
9439  flags,
9440  &index,
9441  &attributes,
9442  &binding_flags);
9443  if (isolate->has_pending_exception()) return Failure::Exception();
9444 
9445  if (index >= 0) {
9446  // The property was found in a context slot.
9447  Handle<Context> context = Handle<Context>::cast(holder);
9448  if (binding_flags == MUTABLE_CHECK_INITIALIZED &&
9449  context->get(index)->IsTheHole()) {
9450  Handle<Object> error =
9451  isolate->factory()->NewReferenceError("not_defined",
9452  HandleVector(&name, 1));
9453  return isolate->Throw(*error);
9454  }
9455  // Ignore if read_only variable.
9456  if ((attributes & READ_ONLY) == 0) {
9457  // Context is a fixed array and set cannot fail.
9458  context->set(index, *value);
9459  } else if (strict_mode == STRICT) {
9460  // Setting read only property in strict mode.
9461  Handle<Object> error =
9462  isolate->factory()->NewTypeError("strict_cannot_assign",
9463  HandleVector(&name, 1));
9464  return isolate->Throw(*error);
9465  }
9466  return *value;
9467  }
9468 
9469  // Slow case: The property is not in a context slot. It is either in a
9470  // context extension object, a property of the subject of a with, or a
9471  // property of the global object.
9472  Handle<JSReceiver> object;
9473 
9474  if (!holder.is_null()) {
9475  // The property exists on the holder.
9476  object = Handle<JSReceiver>::cast(holder);
9477  } else {
9478  // The property was not found.
9479  ASSERT(attributes == ABSENT);
9480 
9481  if (strict_mode == STRICT) {
9482  // Throw in strict mode (assignment to undefined variable).
9483  Handle<Object> error =
9484  isolate->factory()->NewReferenceError(
9485  "not_defined", HandleVector(&name, 1));
9486  return isolate->Throw(*error);
9487  }
9488  // In sloppy mode, the property is added to the global object.
9489  attributes = NONE;
9490  object = Handle<JSReceiver>(isolate->context()->global_object());
9491  }
9492 
9493  // Set the property if it's not read only or doesn't yet exist.
9494  if ((attributes & READ_ONLY) == 0 ||
9495  (JSReceiver::GetLocalPropertyAttribute(object, name) == ABSENT)) {
9497  isolate,
9498  JSReceiver::SetProperty(object, name, value, NONE, strict_mode));
9499  } else if (strict_mode == STRICT && (attributes & READ_ONLY) != 0) {
9500  // Setting read only property in strict mode.
9501  Handle<Object> error =
9502  isolate->factory()->NewTypeError(
9503  "strict_cannot_assign", HandleVector(&name, 1));
9504  return isolate->Throw(*error);
9505  }
9506  return *value;
9507 }
9508 
9509 
9510 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_Throw) {
9511  HandleScope scope(isolate);
9512  ASSERT(args.length() == 1);
9513 
9514  return isolate->Throw(args[0]);
9515 }
9516 
9517 
9518 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_ReThrow) {
9519  HandleScope scope(isolate);
9520  ASSERT(args.length() == 1);
9521 
9522  return isolate->ReThrow(args[0]);
9523 }
9524 
9525 
9526 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_PromoteScheduledException) {
9527  SealHandleScope shs(isolate);
9528  ASSERT_EQ(0, args.length());
9529  return isolate->PromoteScheduledException();
9530 }
9531 
9532 
9533 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_ThrowReferenceError) {
9534  HandleScope scope(isolate);
9535  ASSERT(args.length() == 1);
9536 
9537  Handle<Object> name(args[0], isolate);
9538  Handle<Object> reference_error =
9539  isolate->factory()->NewReferenceError("not_defined",
9540  HandleVector(&name, 1));
9541  return isolate->Throw(*reference_error);
9542 }
9543 
9544 
9545 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_ThrowNotDateError) {
9546  HandleScope scope(isolate);
9547  ASSERT(args.length() == 0);
9548  return isolate->Throw(*isolate->factory()->NewTypeError(
9549  "not_date_object", HandleVector<Object>(NULL, 0)));
9550 }
9551 
9552 
9553 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_ThrowMessage) {
9554  HandleScope scope(isolate);
9555  ASSERT(args.length() == 1);
9556  CONVERT_SMI_ARG_CHECKED(message_id, 0);
9557  const char* message = GetBailoutReason(
9558  static_cast<BailoutReason>(message_id));
9559  Handle<String> message_handle =
9560  isolate->factory()->NewStringFromAscii(CStrVector(message));
9561  RETURN_IF_EMPTY_HANDLE(isolate, message_handle);
9562  return isolate->Throw(*message_handle);
9563 }
9564 
9565 
9566 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StackGuard) {
9567  SealHandleScope shs(isolate);
9568  ASSERT(args.length() == 0);
9569 
9570  // First check if this is a real stack overflow.
9571  if (isolate->stack_guard()->IsStackOverflow()) {
9572  return isolate->StackOverflow();
9573  }
9574 
9575  return Execution::HandleStackGuardInterrupt(isolate);
9576 }
9577 
9578 
9579 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_TryInstallOptimizedCode) {
9580  HandleScope scope(isolate);
9581  ASSERT(args.length() == 1);
9582  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
9583 
9584  // First check if this is a real stack overflow.
9585  if (isolate->stack_guard()->IsStackOverflow()) {
9586  SealHandleScope shs(isolate);
9587  return isolate->StackOverflow();
9588  }
9589 
9590  isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
9591  return (function->IsOptimized()) ? function->code()
9592  : function->shared()->code();
9593 }
9594 
9595 
9596 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_Interrupt) {
9597  SealHandleScope shs(isolate);
9598  ASSERT(args.length() == 0);
9599  return Execution::HandleStackGuardInterrupt(isolate);
9600 }
9601 
9602 
9603 static int StackSize(Isolate* isolate) {
9604  int n = 0;
9605  for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) n++;
9606  return n;
9607 }
9608 
9609 
9610 static void PrintTransition(Isolate* isolate, Object* result) {
9611  // indentation
9612  { const int nmax = 80;
9613  int n = StackSize(isolate);
9614  if (n <= nmax)
9615  PrintF("%4d:%*s", n, n, "");
9616  else
9617  PrintF("%4d:%*s", n, nmax, "...");
9618  }
9619 
9620  if (result == NULL) {
9621  JavaScriptFrame::PrintTop(isolate, stdout, true, false);
9622  PrintF(" {\n");
9623  } else {
9624  // function result
9625  PrintF("} -> ");
9626  result->ShortPrint();
9627  PrintF("\n");
9628  }
9629 }
9630 
9631 
9632 RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceEnter) {
9633  SealHandleScope shs(isolate);
9634  ASSERT(args.length() == 0);
9635  PrintTransition(isolate, NULL);
9636  return isolate->heap()->undefined_value();
9637 }
9638 
9639 
9640 RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceExit) {
9641  SealHandleScope shs(isolate);
9642  PrintTransition(isolate, args[0]);
9643  return args[0]; // return TOS
9644 }
9645 
9646 
9647 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrint) {
9648  SealHandleScope shs(isolate);
9649  ASSERT(args.length() == 1);
9650 
9651 #ifdef DEBUG
9652  if (args[0]->IsString()) {
9653  // If we have a string, assume it's a code "marker"
9654  // and print some interesting cpu debugging info.
9655  JavaScriptFrameIterator it(isolate);
9656  JavaScriptFrame* frame = it.frame();
9657  PrintF("fp = %p, sp = %p, caller_sp = %p: ",
9658  frame->fp(), frame->sp(), frame->caller_sp());
9659  } else {
9660  PrintF("DebugPrint: ");
9661  }
9662  args[0]->Print();
9663  if (args[0]->IsHeapObject()) {
9664  PrintF("\n");
9665  HeapObject::cast(args[0])->map()->Print();
9666  }
9667 #else
9668  // ShortPrint is available in release mode. Print is not.
9669  args[0]->ShortPrint();
9670 #endif
9671  PrintF("\n");
9672  Flush();
9673 
9674  return args[0]; // return TOS
9675 }
9676 
9677 
9678 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugTrace) {
9679  SealHandleScope shs(isolate);
9680  ASSERT(args.length() == 0);
9681  isolate->PrintStack(stdout);
9682  return isolate->heap()->undefined_value();
9683 }
9684 
9685 
9686 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateCurrentTime) {
9687  SealHandleScope shs(isolate);
9688  ASSERT(args.length() == 0);
9689 
9690  // According to ECMA-262, section 15.9.1, page 117, the precision of
9691  // the number in a Date object representing a particular instant in
9692  // time is milliseconds. Therefore, we floor the result of getting
9693  // the OS time.
9694  double millis = std::floor(OS::TimeCurrentMillis());
9695  return isolate->heap()->NumberFromDouble(millis);
9696 }
9697 
9698 
9699 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateParseString) {
9700  HandleScope scope(isolate);
9701  ASSERT(args.length() == 2);
9702 
9704  FlattenString(str);
9705 
9706  CONVERT_ARG_HANDLE_CHECKED(JSArray, output, 1);
9707 
9709  RUNTIME_ASSERT(output->HasFastObjectElements());
9710 
9711  DisallowHeapAllocation no_gc;
9712 
9713  FixedArray* output_array = FixedArray::cast(output->elements());
9714  RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
9715  bool result;
9716  String::FlatContent str_content = str->GetFlatContent();
9717  if (str_content.IsAscii()) {
9718  result = DateParser::Parse(str_content.ToOneByteVector(),
9719  output_array,
9720  isolate->unicode_cache());
9721  } else {
9722  ASSERT(str_content.IsTwoByte());
9723  result = DateParser::Parse(str_content.ToUC16Vector(),
9724  output_array,
9725  isolate->unicode_cache());
9726  }
9727 
9728  if (result) {
9729  return *output;
9730  } else {
9731  return isolate->heap()->null_value();
9732  }
9733 }
9734 
9735 
9736 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateLocalTimezone) {
9737  SealHandleScope shs(isolate);
9738  ASSERT(args.length() == 1);
9739 
9741  const char* zone =
9742  isolate->date_cache()->LocalTimezone(static_cast<int64_t>(x));
9743  return isolate->heap()->AllocateStringFromUtf8(CStrVector(zone));
9744 }
9745 
9746 
9747 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateToUTC) {
9748  SealHandleScope shs(isolate);
9749  ASSERT(args.length() == 1);
9750 
9752  int64_t time = isolate->date_cache()->ToUTC(static_cast<int64_t>(x));
9753 
9754  return isolate->heap()->NumberFromDouble(static_cast<double>(time));
9755 }
9756 
9757 
9758 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateCacheVersion) {
9759  HandleScope hs(isolate);
9760  ASSERT(args.length() == 0);
9761  if (!isolate->eternal_handles()->Exists(EternalHandles::DATE_CACHE_VERSION)) {
9762  Handle<FixedArray> date_cache_version =
9763  isolate->factory()->NewFixedArray(1, TENURED);
9764  date_cache_version->set(0, Smi::FromInt(0));
9765  isolate->eternal_handles()->CreateSingleton(
9766  isolate, *date_cache_version, EternalHandles::DATE_CACHE_VERSION);
9767  }
9768  Handle<FixedArray> date_cache_version =
9769  Handle<FixedArray>::cast(isolate->eternal_handles()->GetSingleton(
9771  // Return result as a JS array.
9772  Handle<JSObject> result =
9773  isolate->factory()->NewJSObject(isolate->array_function());
9774  JSArray::SetContent(Handle<JSArray>::cast(result), date_cache_version);
9775  return *result;
9776 }
9777 
9778 
9779 RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalReceiver) {
9780  SealHandleScope shs(isolate);
9781  ASSERT(args.length() == 1);
9782  Object* global = args[0];
9783  if (!global->IsJSGlobalObject()) return isolate->heap()->null_value();
9784  return JSGlobalObject::cast(global)->global_receiver();
9785 }
9786 
9787 
9788 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAttachedGlobal) {
9789  SealHandleScope shs(isolate);
9790  ASSERT(args.length() == 1);
9791  Object* global = args[0];
9792  if (!global->IsJSGlobalObject()) return isolate->heap()->false_value();
9793  return isolate->heap()->ToBoolean(
9794  !JSGlobalObject::cast(global)->IsDetached());
9795 }
9796 
9797 
9798 RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) {
9799  HandleScope scope(isolate);
9800  ASSERT_EQ(1, args.length());
9801  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9802 
9803  source = Handle<String>(FlattenGetString(source));
9804  // Optimized fast case where we only have ASCII characters.
9805  Handle<Object> result;
9806  if (source->IsSeqOneByteString()) {
9807  result = JsonParser<true>::Parse(source);
9808  } else {
9809  result = JsonParser<false>::Parse(source);
9810  }
9811  if (result.is_null()) {
9812  // Syntax error or stack overflow in scanner.
9813  ASSERT(isolate->has_pending_exception());
9814  return Failure::Exception();
9815  }
9816  return *result;
9817 }
9818 
9819 
9821  Handle<Context> context) {
9822  ASSERT(context->allow_code_gen_from_strings()->IsFalse());
9823  // Check with callback if set.
9825  isolate->allow_code_gen_callback();
9826  if (callback == NULL) {
9827  // No callback set and code generation disallowed.
9828  return false;
9829  } else {
9830  // Callback set. Let it decide if code generation is allowed.
9831  VMState<EXTERNAL> state(isolate);
9832  return callback(v8::Utils::ToLocal(context));
9833  }
9834 }
9835 
9836 
9837 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
9838  HandleScope scope(isolate);
9839  ASSERT_EQ(2, args.length());
9840  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9841  CONVERT_BOOLEAN_ARG_CHECKED(function_literal_only, 1);
9842 
9843  // Extract native context.
9844  Handle<Context> context(isolate->context()->native_context());
9845 
9846  // Check if native context allows code generation from
9847  // strings. Throw an exception if it doesn't.
9848  if (context->allow_code_gen_from_strings()->IsFalse() &&
9849  !CodeGenerationFromStringsAllowed(isolate, context)) {
9850  Handle<Object> error_message =
9851  context->ErrorMessageForCodeGenerationFromStrings();
9852  return isolate->Throw(*isolate->factory()->NewEvalError(
9853  "code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
9854  }
9855 
9856  // Compile source string in the native context.
9857  ParseRestriction restriction = function_literal_only
9860  source, context, SLOPPY, restriction, RelocInfo::kNoPosition);
9861  RETURN_IF_EMPTY_HANDLE(isolate, fun);
9862  return *fun;
9863 }
9864 
9865 
9866 static ObjectPair CompileGlobalEval(Isolate* isolate,
9867  Handle<String> source,
9868  Handle<Object> receiver,
9869  StrictMode strict_mode,
9870  int scope_position) {
9871  Handle<Context> context = Handle<Context>(isolate->context());
9872  Handle<Context> native_context = Handle<Context>(context->native_context());
9873 
9874  // Check if native context allows code generation from
9875  // strings. Throw an exception if it doesn't.
9876  if (native_context->allow_code_gen_from_strings()->IsFalse() &&
9877  !CodeGenerationFromStringsAllowed(isolate, native_context)) {
9878  Handle<Object> error_message =
9879  native_context->ErrorMessageForCodeGenerationFromStrings();
9880  isolate->Throw(*isolate->factory()->NewEvalError(
9881  "code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
9882  return MakePair(Failure::Exception(), NULL);
9883  }
9884 
9885  // Deal with a normal eval call with a string argument. Compile it
9886  // and return the compiled function bound in the local context.
9887  static const ParseRestriction restriction = NO_PARSE_RESTRICTION;
9888  Handle<JSFunction> compiled = Compiler::GetFunctionFromEval(
9889  source, context, strict_mode, restriction, scope_position);
9890  RETURN_IF_EMPTY_HANDLE_VALUE(isolate, compiled,
9891  MakePair(Failure::Exception(), NULL));
9892  return MakePair(*compiled, *receiver);
9893 }
9894 
9895 
9896 RUNTIME_FUNCTION(ObjectPair, RuntimeHidden_ResolvePossiblyDirectEval) {
9897  HandleScope scope(isolate);
9898  ASSERT(args.length() == 5);
9899 
9900  Handle<Object> callee = args.at<Object>(0);
9901 
9902  // If "eval" didn't refer to the original GlobalEval, it's not a
9903  // direct call to eval.
9904  // (And even if it is, but the first argument isn't a string, just let
9905  // execution default to an indirect call to eval, which will also return
9906  // the first argument without doing anything).
9907  if (*callee != isolate->native_context()->global_eval_fun() ||
9908  !args[1]->IsString()) {
9909  return MakePair(*callee, isolate->heap()->undefined_value());
9910  }
9911 
9912  ASSERT(args[3]->IsSmi());
9913  ASSERT(args.smi_at(3) == SLOPPY || args.smi_at(3) == STRICT);
9914  StrictMode strict_mode = static_cast<StrictMode>(args.smi_at(3));
9915  ASSERT(args[4]->IsSmi());
9916  return CompileGlobalEval(isolate,
9917  args.at<String>(1),
9918  args.at<Object>(2),
9919  strict_mode,
9920  args.smi_at(4));
9921 }
9922 
9923 
9924 // Allocate a block of memory in the given space (filled with a filler).
9925 // Used as a fall-back for generated code when the space is full.
9926 static MaybeObject* Allocate(Isolate* isolate,
9927  int size,
9928  bool double_align,
9929  AllocationSpace space) {
9930  Heap* heap = isolate->heap();
9932  RUNTIME_ASSERT(size > 0);
9934  HeapObject* allocation;
9935  { MaybeObject* maybe_allocation = heap->AllocateRaw(size, space, space);
9936  if (!maybe_allocation->To(&allocation)) return maybe_allocation;
9937  }
9938 #ifdef DEBUG
9939  MemoryChunk* chunk = MemoryChunk::FromAddress(allocation->address());
9940  ASSERT(chunk->owner()->identity() == space);
9941 #endif
9942  heap->CreateFillerObjectAt(allocation->address(), size);
9943  return allocation;
9944 }
9945 
9946 
9947 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_AllocateInNewSpace) {
9948  SealHandleScope shs(isolate);
9949  ASSERT(args.length() == 1);
9950  CONVERT_SMI_ARG_CHECKED(size, 0);
9951  return Allocate(isolate, size, false, NEW_SPACE);
9952 }
9953 
9954 
9955 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_AllocateInTargetSpace) {
9956  SealHandleScope shs(isolate);
9957  ASSERT(args.length() == 2);
9958  CONVERT_SMI_ARG_CHECKED(size, 0);
9959  CONVERT_SMI_ARG_CHECKED(flags, 1);
9960  bool double_align = AllocateDoubleAlignFlag::decode(flags);
9962  return Allocate(isolate, size, double_align, space);
9963 }
9964 
9965 
9966 // Push an object unto an array of objects if it is not already in the
9967 // array. Returns true if the element was pushed on the stack and
9968 // false otherwise.
9969 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) {
9970  HandleScope scope(isolate);
9971  ASSERT(args.length() == 2);
9974  RUNTIME_ASSERT(array->HasFastSmiOrObjectElements());
9975  int length = Smi::cast(array->length())->value();
9976  FixedArray* elements = FixedArray::cast(array->elements());
9977  for (int i = 0; i < length; i++) {
9978  if (elements->get(i) == *element) return isolate->heap()->false_value();
9979  }
9980 
9981  // Strict not needed. Used for cycle detection in Array join implementation.
9982  RETURN_IF_EMPTY_HANDLE(isolate, JSObject::SetFastElement(array, length,
9983  element,
9984  SLOPPY,
9985  true));
9986  return isolate->heap()->true_value();
9987 }
9988 
9989 
10002  public:
10004  Handle<FixedArray> storage,
10005  bool fast_elements) :
10006  isolate_(isolate),
10007  storage_(Handle<FixedArray>::cast(
10008  isolate->global_handles()->Create(*storage))),
10009  index_offset_(0u),
10010  fast_elements_(fast_elements),
10011  exceeds_array_limit_(false) { }
10012 
10014  clear_storage();
10015  }
10016 
10017  void visit(uint32_t i, Handle<Object> elm) {
10018  if (i > JSObject::kMaxElementCount - index_offset_) {
10019  exceeds_array_limit_ = true;
10020  return;
10021  }
10022  uint32_t index = index_offset_ + i;
10023 
10024  if (fast_elements_) {
10025  if (index < static_cast<uint32_t>(storage_->length())) {
10026  storage_->set(index, *elm);
10027  return;
10028  }
10029  // Our initial estimate of length was foiled, possibly by
10030  // getters on the arrays increasing the length of later arrays
10031  // during iteration.
10032  // This shouldn't happen in anything but pathological cases.
10033  SetDictionaryMode(index);
10034  // Fall-through to dictionary mode.
10035  }
10036  ASSERT(!fast_elements_);
10038  SeededNumberDictionary::cast(*storage_));
10040  isolate_->factory()->DictionaryAtNumberPut(dict, index, elm);
10041  if (!result.is_identical_to(dict)) {
10042  // Dictionary needed to grow.
10043  clear_storage();
10044  set_storage(*result);
10045  }
10046  }
10047 
10048  void increase_index_offset(uint32_t delta) {
10049  if (JSObject::kMaxElementCount - index_offset_ < delta) {
10050  index_offset_ = JSObject::kMaxElementCount;
10051  } else {
10052  index_offset_ += delta;
10053  }
10054  }
10055 
10057  return exceeds_array_limit_;
10058  }
10059 
10061  Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
10062  Handle<Object> length =
10063  isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
10064  Handle<Map> map;
10065  if (fast_elements_) {
10067  } else {
10069  }
10070  array->set_map(*map);
10071  array->set_length(*length);
10072  array->set_elements(*storage_);
10073  return array;
10074  }
10075 
10076  private:
10077  // Convert storage to dictionary mode.
10078  void SetDictionaryMode(uint32_t index) {
10079  ASSERT(fast_elements_);
10080  Handle<FixedArray> current_storage(*storage_);
10081  Handle<SeededNumberDictionary> slow_storage(
10082  isolate_->factory()->NewSeededNumberDictionary(
10083  current_storage->length()));
10084  uint32_t current_length = static_cast<uint32_t>(current_storage->length());
10085  for (uint32_t i = 0; i < current_length; i++) {
10086  HandleScope loop_scope(isolate_);
10087  Handle<Object> element(current_storage->get(i), isolate_);
10088  if (!element->IsTheHole()) {
10089  Handle<SeededNumberDictionary> new_storage =
10090  isolate_->factory()->DictionaryAtNumberPut(slow_storage, i, element);
10091  if (!new_storage.is_identical_to(slow_storage)) {
10092  slow_storage = loop_scope.CloseAndEscape(new_storage);
10093  }
10094  }
10095  }
10096  clear_storage();
10097  set_storage(*slow_storage);
10098  fast_elements_ = false;
10099  }
10100 
10101  inline void clear_storage() {
10102  GlobalHandles::Destroy(Handle<Object>::cast(storage_).location());
10103  }
10104 
10105  inline void set_storage(FixedArray* storage) {
10106  storage_ = Handle<FixedArray>::cast(
10107  isolate_->global_handles()->Create(storage));
10108  }
10109 
10110  Isolate* isolate_;
10111  Handle<FixedArray> storage_; // Always a global handle.
10112  // Index after last seen index. Always less than or equal to
10113  // JSObject::kMaxElementCount.
10114  uint32_t index_offset_;
10115  bool fast_elements_ : 1;
10116  bool exceeds_array_limit_ : 1;
10117 };
10118 
10119 
10120 static uint32_t EstimateElementCount(Handle<JSArray> array) {
10121  uint32_t length = static_cast<uint32_t>(array->length()->Number());
10122  int element_count = 0;
10123  switch (array->GetElementsKind()) {
10124  case FAST_SMI_ELEMENTS:
10126  case FAST_ELEMENTS:
10127  case FAST_HOLEY_ELEMENTS: {
10128  // Fast elements can't have lengths that are not representable by
10129  // a 32-bit signed integer.
10130  ASSERT(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
10131  int fast_length = static_cast<int>(length);
10132  Handle<FixedArray> elements(FixedArray::cast(array->elements()));
10133  for (int i = 0; i < fast_length; i++) {
10134  if (!elements->get(i)->IsTheHole()) element_count++;
10135  }
10136  break;
10137  }
10138  case FAST_DOUBLE_ELEMENTS:
10140  // Fast elements can't have lengths that are not representable by
10141  // a 32-bit signed integer.
10142  ASSERT(static_cast<int32_t>(FixedDoubleArray::kMaxLength) >= 0);
10143  int fast_length = static_cast<int>(length);
10144  if (array->elements()->IsFixedArray()) {
10145  ASSERT(FixedArray::cast(array->elements())->length() == 0);
10146  break;
10147  }
10148  Handle<FixedDoubleArray> elements(
10149  FixedDoubleArray::cast(array->elements()));
10150  for (int i = 0; i < fast_length; i++) {
10151  if (!elements->is_the_hole(i)) element_count++;
10152  }
10153  break;
10154  }
10155  case DICTIONARY_ELEMENTS: {
10156  Handle<SeededNumberDictionary> dictionary(
10157  SeededNumberDictionary::cast(array->elements()));
10158  int capacity = dictionary->Capacity();
10159  for (int i = 0; i < capacity; i++) {
10160  Handle<Object> key(dictionary->KeyAt(i), array->GetIsolate());
10161  if (dictionary->IsKey(*key)) {
10162  element_count++;
10163  }
10164  }
10165  break;
10166  }
10168 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
10169  case EXTERNAL_##TYPE##_ELEMENTS: \
10170  case TYPE##_ELEMENTS: \
10171 
10173 #undef TYPED_ARRAY_CASE
10174  // External arrays are always dense.
10175  return length;
10176  }
10177  // As an estimate, we assume that the prototype doesn't contain any
10178  // inherited elements.
10179  return element_count;
10180 }
10181 
10182 
10183 
10184 template<class ExternalArrayClass, class ElementType>
10185 static void IterateExternalArrayElements(Isolate* isolate,
10186  Handle<JSObject> receiver,
10187  bool elements_are_ints,
10188  bool elements_are_guaranteed_smis,
10189  ArrayConcatVisitor* visitor) {
10190  Handle<ExternalArrayClass> array(
10191  ExternalArrayClass::cast(receiver->elements()));
10192  uint32_t len = static_cast<uint32_t>(array->length());
10193 
10194  ASSERT(visitor != NULL);
10195  if (elements_are_ints) {
10196  if (elements_are_guaranteed_smis) {
10197  for (uint32_t j = 0; j < len; j++) {
10198  HandleScope loop_scope(isolate);
10199  Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get_scalar(j))),
10200  isolate);
10201  visitor->visit(j, e);
10202  }
10203  } else {
10204  for (uint32_t j = 0; j < len; j++) {
10205  HandleScope loop_scope(isolate);
10206  int64_t val = static_cast<int64_t>(array->get_scalar(j));
10207  if (Smi::IsValid(static_cast<intptr_t>(val))) {
10208  Handle<Smi> e(Smi::FromInt(static_cast<int>(val)), isolate);
10209  visitor->visit(j, e);
10210  } else {
10211  Handle<Object> e =
10212  isolate->factory()->NewNumber(static_cast<ElementType>(val));
10213  visitor->visit(j, e);
10214  }
10215  }
10216  }
10217  } else {
10218  for (uint32_t j = 0; j < len; j++) {
10219  HandleScope loop_scope(isolate);
10220  Handle<Object> e = isolate->factory()->NewNumber(array->get_scalar(j));
10221  visitor->visit(j, e);
10222  }
10223  }
10224 }
10225 
10226 
10227 // Used for sorting indices in a List<uint32_t>.
10228 static int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
10229  uint32_t a = *ap;
10230  uint32_t b = *bp;
10231  return (a == b) ? 0 : (a < b) ? -1 : 1;
10232 }
10233 
10234 
10235 static void CollectElementIndices(Handle<JSObject> object,
10236  uint32_t range,
10237  List<uint32_t>* indices) {
10238  Isolate* isolate = object->GetIsolate();
10239  ElementsKind kind = object->GetElementsKind();
10240  switch (kind) {
10241  case FAST_SMI_ELEMENTS:
10242  case FAST_ELEMENTS:
10244  case FAST_HOLEY_ELEMENTS: {
10245  Handle<FixedArray> elements(FixedArray::cast(object->elements()));
10246  uint32_t length = static_cast<uint32_t>(elements->length());
10247  if (range < length) length = range;
10248  for (uint32_t i = 0; i < length; i++) {
10249  if (!elements->get(i)->IsTheHole()) {
10250  indices->Add(i);
10251  }
10252  }
10253  break;
10254  }
10256  case FAST_DOUBLE_ELEMENTS: {
10257  // TODO(1810): Decide if it's worthwhile to implement this.
10258  UNREACHABLE();
10259  break;
10260  }
10261  case DICTIONARY_ELEMENTS: {
10262  Handle<SeededNumberDictionary> dict(
10263  SeededNumberDictionary::cast(object->elements()));
10264  uint32_t capacity = dict->Capacity();
10265  for (uint32_t j = 0; j < capacity; j++) {
10266  HandleScope loop_scope(isolate);
10267  Handle<Object> k(dict->KeyAt(j), isolate);
10268  if (dict->IsKey(*k)) {
10269  ASSERT(k->IsNumber());
10270  uint32_t index = static_cast<uint32_t>(k->Number());
10271  if (index < range) {
10272  indices->Add(index);
10273  }
10274  }
10275  }
10276  break;
10277  }
10278  default: {
10279  int dense_elements_length;
10280  switch (kind) {
10281 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
10282  case EXTERNAL_##TYPE##_ELEMENTS: { \
10283  dense_elements_length = \
10284  External##Type##Array::cast(object->elements())->length(); \
10285  break; \
10286  }
10287 
10289 #undef TYPED_ARRAY_CASE
10290 
10291  default:
10292  UNREACHABLE();
10293  dense_elements_length = 0;
10294  break;
10295  }
10296  uint32_t length = static_cast<uint32_t>(dense_elements_length);
10297  if (range <= length) {
10298  length = range;
10299  // We will add all indices, so we might as well clear it first
10300  // and avoid duplicates.
10301  indices->Clear();
10302  }
10303  for (uint32_t i = 0; i < length; i++) {
10304  indices->Add(i);
10305  }
10306  if (length == range) return; // All indices accounted for already.
10307  break;
10308  }
10309  }
10310 
10311  Handle<Object> prototype(object->GetPrototype(), isolate);
10312  if (prototype->IsJSObject()) {
10313  // The prototype will usually have no inherited element indices,
10314  // but we have to check.
10315  CollectElementIndices(Handle<JSObject>::cast(prototype), range, indices);
10316  }
10317 }
10318 
10319 
10330 static bool IterateElements(Isolate* isolate,
10331  Handle<JSArray> receiver,
10332  ArrayConcatVisitor* visitor) {
10333  uint32_t length = static_cast<uint32_t>(receiver->length()->Number());
10334  switch (receiver->GetElementsKind()) {
10335  case FAST_SMI_ELEMENTS:
10336  case FAST_ELEMENTS:
10338  case FAST_HOLEY_ELEMENTS: {
10339  // Run through the elements FixedArray and use HasElement and GetElement
10340  // to check the prototype for missing elements.
10341  Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
10342  int fast_length = static_cast<int>(length);
10343  ASSERT(fast_length <= elements->length());
10344  for (int j = 0; j < fast_length; j++) {
10345  HandleScope loop_scope(isolate);
10346  Handle<Object> element_value(elements->get(j), isolate);
10347  if (!element_value->IsTheHole()) {
10348  visitor->visit(j, element_value);
10349  } else if (JSReceiver::HasElement(receiver, j)) {
10350  // Call GetElement on receiver, not its prototype, or getters won't
10351  // have the correct receiver.
10352  element_value = Object::GetElement(isolate, receiver, j);
10353  RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
10354  visitor->visit(j, element_value);
10355  }
10356  }
10357  break;
10358  }
10360  case FAST_DOUBLE_ELEMENTS: {
10361  // Run through the elements FixedArray and use HasElement and GetElement
10362  // to check the prototype for missing elements.
10363  Handle<FixedDoubleArray> elements(
10364  FixedDoubleArray::cast(receiver->elements()));
10365  int fast_length = static_cast<int>(length);
10366  ASSERT(fast_length <= elements->length());
10367  for (int j = 0; j < fast_length; j++) {
10368  HandleScope loop_scope(isolate);
10369  if (!elements->is_the_hole(j)) {
10370  double double_value = elements->get_scalar(j);
10371  Handle<Object> element_value =
10372  isolate->factory()->NewNumber(double_value);
10373  visitor->visit(j, element_value);
10374  } else if (JSReceiver::HasElement(receiver, j)) {
10375  // Call GetElement on receiver, not its prototype, or getters won't
10376  // have the correct receiver.
10377  Handle<Object> element_value =
10378  Object::GetElement(isolate, receiver, j);
10379  RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
10380  visitor->visit(j, element_value);
10381  }
10382  }
10383  break;
10384  }
10385  case DICTIONARY_ELEMENTS: {
10386  Handle<SeededNumberDictionary> dict(receiver->element_dictionary());
10387  List<uint32_t> indices(dict->Capacity() / 2);
10388  // Collect all indices in the object and the prototypes less
10389  // than length. This might introduce duplicates in the indices list.
10390  CollectElementIndices(receiver, length, &indices);
10391  indices.Sort(&compareUInt32);
10392  int j = 0;
10393  int n = indices.length();
10394  while (j < n) {
10395  HandleScope loop_scope(isolate);
10396  uint32_t index = indices[j];
10397  Handle<Object> element = Object::GetElement(isolate, receiver, index);
10398  RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element, false);
10399  visitor->visit(index, element);
10400  // Skip to next different index (i.e., omit duplicates).
10401  do {
10402  j++;
10403  } while (j < n && indices[j] == index);
10404  }
10405  break;
10406  }
10408  Handle<ExternalUint8ClampedArray> pixels(ExternalUint8ClampedArray::cast(
10409  receiver->elements()));
10410  for (uint32_t j = 0; j < length; j++) {
10411  Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate);
10412  visitor->visit(j, e);
10413  }
10414  break;
10415  }
10416  case EXTERNAL_INT8_ELEMENTS: {
10417  IterateExternalArrayElements<ExternalInt8Array, int8_t>(
10418  isolate, receiver, true, true, visitor);
10419  break;
10420  }
10421  case EXTERNAL_UINT8_ELEMENTS: {
10422  IterateExternalArrayElements<ExternalUint8Array, uint8_t>(
10423  isolate, receiver, true, true, visitor);
10424  break;
10425  }
10426  case EXTERNAL_INT16_ELEMENTS: {
10427  IterateExternalArrayElements<ExternalInt16Array, int16_t>(
10428  isolate, receiver, true, true, visitor);
10429  break;
10430  }
10431  case EXTERNAL_UINT16_ELEMENTS: {
10432  IterateExternalArrayElements<ExternalUint16Array, uint16_t>(
10433  isolate, receiver, true, true, visitor);
10434  break;
10435  }
10436  case EXTERNAL_INT32_ELEMENTS: {
10437  IterateExternalArrayElements<ExternalInt32Array, int32_t>(
10438  isolate, receiver, true, false, visitor);
10439  break;
10440  }
10441  case EXTERNAL_UINT32_ELEMENTS: {
10442  IterateExternalArrayElements<ExternalUint32Array, uint32_t>(
10443  isolate, receiver, true, false, visitor);
10444  break;
10445  }
10447  IterateExternalArrayElements<ExternalFloat32Array, float>(
10448  isolate, receiver, false, false, visitor);
10449  break;
10450  }
10452  IterateExternalArrayElements<ExternalFloat64Array, double>(
10453  isolate, receiver, false, false, visitor);
10454  break;
10455  }
10456  default:
10457  UNREACHABLE();
10458  break;
10459  }
10460  visitor->increase_index_offset(length);
10461  return true;
10462 }
10463 
10464 
10471 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) {
10472  HandleScope handle_scope(isolate);
10473  ASSERT(args.length() == 1);
10474 
10475  CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 0);
10476  int argument_count = static_cast<int>(arguments->length()->Number());
10477  RUNTIME_ASSERT(arguments->HasFastObjectElements());
10478  Handle<FixedArray> elements(FixedArray::cast(arguments->elements()));
10479 
10480  // Pass 1: estimate the length and number of elements of the result.
10481  // The actual length can be larger if any of the arguments have getters
10482  // that mutate other arguments (but will otherwise be precise).
10483  // The number of elements is precise if there are no inherited elements.
10484 
10486 
10487  uint32_t estimate_result_length = 0;
10488  uint32_t estimate_nof_elements = 0;
10489  for (int i = 0; i < argument_count; i++) {
10490  HandleScope loop_scope(isolate);
10491  Handle<Object> obj(elements->get(i), isolate);
10492  uint32_t length_estimate;
10493  uint32_t element_estimate;
10494  if (obj->IsJSArray()) {
10496  length_estimate = static_cast<uint32_t>(array->length()->Number());
10497  if (length_estimate != 0) {
10498  ElementsKind array_kind =
10499  GetPackedElementsKind(array->map()->elements_kind());
10500  if (IsMoreGeneralElementsKindTransition(kind, array_kind)) {
10501  kind = array_kind;
10502  }
10503  }
10504  element_estimate = EstimateElementCount(array);
10505  } else {
10506  if (obj->IsHeapObject()) {
10507  if (obj->IsNumber()) {
10509  kind = FAST_DOUBLE_ELEMENTS;
10510  }
10512  kind = FAST_ELEMENTS;
10513  }
10514  }
10515  length_estimate = 1;
10516  element_estimate = 1;
10517  }
10518  // Avoid overflows by capping at kMaxElementCount.
10519  if (JSObject::kMaxElementCount - estimate_result_length <
10520  length_estimate) {
10521  estimate_result_length = JSObject::kMaxElementCount;
10522  } else {
10523  estimate_result_length += length_estimate;
10524  }
10525  if (JSObject::kMaxElementCount - estimate_nof_elements <
10526  element_estimate) {
10527  estimate_nof_elements = JSObject::kMaxElementCount;
10528  } else {
10529  estimate_nof_elements += element_estimate;
10530  }
10531  }
10532 
10533  // If estimated number of elements is more than half of length, a
10534  // fixed array (fast case) is more time and space-efficient than a
10535  // dictionary.
10536  bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length;
10537 
10538  Handle<FixedArray> storage;
10539  if (fast_case) {
10540  if (kind == FAST_DOUBLE_ELEMENTS) {
10541  Handle<FixedDoubleArray> double_storage =
10542  isolate->factory()->NewFixedDoubleArray(estimate_result_length);
10543  int j = 0;
10544  bool failure = false;
10545  for (int i = 0; i < argument_count; i++) {
10546  Handle<Object> obj(elements->get(i), isolate);
10547  if (obj->IsSmi()) {
10548  double_storage->set(j, Smi::cast(*obj)->value());
10549  j++;
10550  } else if (obj->IsNumber()) {
10551  double_storage->set(j, obj->Number());
10552  j++;
10553  } else {
10554  JSArray* array = JSArray::cast(*obj);
10555  uint32_t length = static_cast<uint32_t>(array->length()->Number());
10556  switch (array->map()->elements_kind()) {
10558  case FAST_DOUBLE_ELEMENTS: {
10559  // Empty fixed array indicates that there are no elements.
10560  if (array->elements()->IsFixedArray()) break;
10561  FixedDoubleArray* elements =
10562  FixedDoubleArray::cast(array->elements());
10563  for (uint32_t i = 0; i < length; i++) {
10564  if (elements->is_the_hole(i)) {
10565  failure = true;
10566  break;
10567  }
10568  double double_value = elements->get_scalar(i);
10569  double_storage->set(j, double_value);
10570  j++;
10571  }
10572  break;
10573  }
10575  case FAST_SMI_ELEMENTS: {
10576  FixedArray* elements(
10577  FixedArray::cast(array->elements()));
10578  for (uint32_t i = 0; i < length; i++) {
10579  Object* element = elements->get(i);
10580  if (element->IsTheHole()) {
10581  failure = true;
10582  break;
10583  }
10584  int32_t int_value = Smi::cast(element)->value();
10585  double_storage->set(j, int_value);
10586  j++;
10587  }
10588  break;
10589  }
10590  case FAST_HOLEY_ELEMENTS:
10591  ASSERT_EQ(0, length);
10592  break;
10593  default:
10594  UNREACHABLE();
10595  }
10596  }
10597  if (failure) break;
10598  }
10599  Handle<JSArray> array = isolate->factory()->NewJSArray(0);
10600  Smi* length = Smi::FromInt(j);
10601  Handle<Map> map;
10602  map = JSObject::GetElementsTransitionMap(array, kind);
10603  array->set_map(*map);
10604  array->set_length(length);
10605  array->set_elements(*double_storage);
10606  return *array;
10607  }
10608  // The backing storage array must have non-existing elements to preserve
10609  // holes across concat operations.
10610  storage = isolate->factory()->NewFixedArrayWithHoles(
10611  estimate_result_length);
10612  } else {
10613  // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
10614  uint32_t at_least_space_for = estimate_nof_elements +
10615  (estimate_nof_elements >> 2);
10616  storage = Handle<FixedArray>::cast(
10617  isolate->factory()->NewSeededNumberDictionary(at_least_space_for));
10618  }
10619 
10620  ArrayConcatVisitor visitor(isolate, storage, fast_case);
10621 
10622  for (int i = 0; i < argument_count; i++) {
10623  Handle<Object> obj(elements->get(i), isolate);
10624  if (obj->IsJSArray()) {
10626  if (!IterateElements(isolate, array, &visitor)) {
10627  return Failure::Exception();
10628  }
10629  } else {
10630  visitor.visit(0, obj);
10631  visitor.increase_index_offset(1);
10632  }
10633  }
10634 
10635  if (visitor.exceeds_array_limit()) {
10636  return isolate->Throw(
10637  *isolate->factory()->NewRangeError("invalid_array_length",
10638  HandleVector<Object>(NULL, 0)));
10639  }
10640  return *visitor.ToArray();
10641 }
10642 
10643 
10644 // This will not allocate (flatten the string), but it may run
10645 // very slowly for very deeply nested ConsStrings. For debugging use only.
10646 RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalPrint) {
10647  SealHandleScope shs(isolate);
10648  ASSERT(args.length() == 1);
10649 
10650  CONVERT_ARG_CHECKED(String, string, 0);
10652  StringCharacterStream stream(string, &op);
10653  while (stream.HasMore()) {
10654  uint16_t character = stream.GetNext();
10655  PrintF("%c", character);
10656  }
10657  return string;
10658 }
10659 
10660 
10661 // Moves all own elements of an object, that are below a limit, to positions
10662 // starting at zero. All undefined values are placed after non-undefined values,
10663 // and are followed by non-existing element. Does not change the length
10664 // property.
10665 // Returns the number of non-undefined elements collected.
10666 // Returns -1 if hole removal is not supported by this method.
10667 RUNTIME_FUNCTION(MaybeObject*, Runtime_RemoveArrayHoles) {
10668  HandleScope scope(isolate);
10669  ASSERT(args.length() == 2);
10671  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
10672  return *JSObject::PrepareElementsForSort(object, limit);
10673 }
10674 
10675 
10676 // Move contents of argument 0 (an array) to argument 1 (an array)
10677 RUNTIME_FUNCTION(MaybeObject*, Runtime_MoveArrayContents) {
10678  SealHandleScope shs(isolate);
10679  ASSERT(args.length() == 2);
10680  CONVERT_ARG_CHECKED(JSArray, from, 0);
10681  CONVERT_ARG_CHECKED(JSArray, to, 1);
10682  from->ValidateElements();
10683  to->ValidateElements();
10684  FixedArrayBase* new_elements = from->elements();
10685  ElementsKind from_kind = from->GetElementsKind();
10686  MaybeObject* maybe_new_map;
10687  maybe_new_map = to->GetElementsTransitionMap(isolate, from_kind);
10688  Object* new_map;
10689  if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
10690  to->set_map_and_elements(Map::cast(new_map), new_elements);
10691  to->set_length(from->length());
10692  Object* obj;
10693  { MaybeObject* maybe_obj = from->ResetElements();
10694  if (!maybe_obj->ToObject(&obj)) return maybe_obj;
10695  }
10696  from->set_length(Smi::FromInt(0));
10697  to->ValidateElements();
10698  return to;
10699 }
10700 
10701 
10702 // How many elements does this object/array have?
10703 RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) {
10704  SealHandleScope shs(isolate);
10705  ASSERT(args.length() == 1);
10706  CONVERT_ARG_CHECKED(JSObject, object, 0);
10707  HeapObject* elements = object->elements();
10708  if (elements->IsDictionary()) {
10709  int result = SeededNumberDictionary::cast(elements)->NumberOfElements();
10710  return Smi::FromInt(result);
10711  } else if (object->IsJSArray()) {
10712  return JSArray::cast(object)->length();
10713  } else {
10714  return Smi::FromInt(FixedArray::cast(elements)->length());
10715  }
10716 }
10717 
10718 
10719 // Returns an array that tells you where in the [0, length) interval an array
10720 // might have elements. Can either return an array of keys (positive integers
10721 // or undefined) or a number representing the positive length of an interval
10722 // starting at index 0.
10723 // Intervals can span over some keys that are not in the object.
10724 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
10725  HandleScope scope(isolate);
10726  ASSERT(args.length() == 2);
10728  CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
10729  if (array->elements()->IsDictionary()) {
10730  Handle<FixedArray> keys = isolate->factory()->empty_fixed_array();
10731  for (Handle<Object> p = array;
10732  !p->IsNull();
10733  p = Handle<Object>(p->GetPrototype(isolate), isolate)) {
10734  if (p->IsJSProxy() || JSObject::cast(*p)->HasIndexedInterceptor()) {
10735  // Bail out if we find a proxy or interceptor, likely not worth
10736  // collecting keys in that case.
10737  return *isolate->factory()->NewNumberFromUint(length);
10738  }
10740  Handle<FixedArray> current_keys =
10741  isolate->factory()->NewFixedArray(
10742  current->NumberOfLocalElements(NONE));
10743  current->GetLocalElementKeys(*current_keys, NONE);
10744  keys = UnionOfKeys(keys, current_keys);
10745  }
10746  // Erase any keys >= length.
10747  // TODO(adamk): Remove this step when the contract of %GetArrayKeys
10748  // is changed to let this happen on the JS side.
10749  for (int i = 0; i < keys->length(); i++) {
10750  if (NumberToUint32(keys->get(i)) >= length) keys->set_undefined(i);
10751  }
10752  return *isolate->factory()->NewJSArrayWithElements(keys);
10753  } else {
10754  ASSERT(array->HasFastSmiOrObjectElements() ||
10755  array->HasFastDoubleElements());
10756  uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
10757  return *isolate->factory()->NewNumberFromUint(Min(actual_length, length));
10758  }
10759 }
10760 
10761 
10762 RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) {
10763  HandleScope scope(isolate);
10764  ASSERT(args.length() == 3);
10765  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
10766  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10769  if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
10770  Handle<Object> result =
10771  JSObject::GetAccessor(Handle<JSObject>::cast(receiver), name, component);
10772  RETURN_IF_EMPTY_HANDLE(isolate, result);
10773  return *result;
10774 }
10775 
10776 
10777 #ifdef ENABLE_DEBUGGER_SUPPORT
10778 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugBreak) {
10779  SealHandleScope shs(isolate);
10780  ASSERT(args.length() == 0);
10781  return Execution::DebugBreakHelper(isolate);
10782 }
10783 
10784 
10785 // Helper functions for wrapping and unwrapping stack frame ids.
10786 static Smi* WrapFrameId(StackFrame::Id id) {
10787  ASSERT(IsAligned(OffsetFrom(id), static_cast<intptr_t>(4)));
10788  return Smi::FromInt(id >> 2);
10789 }
10790 
10791 
10792 static StackFrame::Id UnwrapFrameId(int wrapped) {
10793  return static_cast<StackFrame::Id>(wrapped << 2);
10794 }
10795 
10796 
10797 // Adds a JavaScript function as a debug event listener.
10798 // args[0]: debug event listener function to set or null or undefined for
10799 // clearing the event listener function
10800 // args[1]: object supplied during callback
10801 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDebugEventListener) {
10802  SealHandleScope shs(isolate);
10803  ASSERT(args.length() == 2);
10804  RUNTIME_ASSERT(args[0]->IsJSFunction() ||
10805  args[0]->IsUndefined() ||
10806  args[0]->IsNull());
10807  Handle<Object> callback = args.at<Object>(0);
10808  Handle<Object> data = args.at<Object>(1);
10809  isolate->debugger()->SetEventListener(callback, data);
10810 
10811  return isolate->heap()->undefined_value();
10812 }
10813 
10814 
10815 RUNTIME_FUNCTION(MaybeObject*, Runtime_Break) {
10816  SealHandleScope shs(isolate);
10817  ASSERT(args.length() == 0);
10818  isolate->stack_guard()->DebugBreak();
10819  return isolate->heap()->undefined_value();
10820 }
10821 
10822 
10823 static MaybeObject* DebugLookupResultValue(Heap* heap,
10824  Object* receiver,
10825  Name* name,
10826  LookupResult* result,
10827  bool* caught_exception) {
10828  Object* value;
10829  switch (result->type()) {
10830  case NORMAL:
10831  value = result->holder()->GetNormalizedProperty(result);
10832  if (value->IsTheHole()) {
10833  return heap->undefined_value();
10834  }
10835  return value;
10836  case FIELD: {
10837  Object* value;
10838  MaybeObject* maybe_value =
10839  JSObject::cast(result->holder())->FastPropertyAt(
10840  result->representation(),
10841  result->GetFieldIndex().field_index());
10842  if (!maybe_value->To(&value)) return maybe_value;
10843  if (value->IsTheHole()) {
10844  return heap->undefined_value();
10845  }
10846  return value;
10847  }
10848  case CONSTANT:
10849  return result->GetConstant();
10850  case CALLBACKS: {
10851  Object* structure = result->GetCallbackObject();
10852  if (structure->IsForeign() || structure->IsAccessorInfo()) {
10853  Isolate* isolate = heap->isolate();
10854  HandleScope scope(isolate);
10855  Handle<Object> value = JSObject::GetPropertyWithCallback(
10856  handle(result->holder(), isolate),
10857  handle(receiver, isolate),
10858  handle(structure, isolate),
10859  handle(name, isolate));
10860  if (value.is_null()) {
10861  MaybeObject* exception = heap->isolate()->pending_exception();
10862  heap->isolate()->clear_pending_exception();
10863  if (caught_exception != NULL) *caught_exception = true;
10864  return exception;
10865  }
10866  return *value;
10867  } else {
10868  return heap->undefined_value();
10869  }
10870  }
10871  case INTERCEPTOR:
10872  case TRANSITION:
10873  return heap->undefined_value();
10874  case HANDLER:
10875  case NONEXISTENT:
10876  UNREACHABLE();
10877  return heap->undefined_value();
10878  }
10879  UNREACHABLE(); // keep the compiler happy
10880  return heap->undefined_value();
10881 }
10882 
10883 
10884 // Get debugger related details for an object property.
10885 // args[0]: object holding property
10886 // args[1]: name of the property
10887 //
10888 // The array returned contains the following information:
10889 // 0: Property value
10890 // 1: Property details
10891 // 2: Property value is exception
10892 // 3: Getter function if defined
10893 // 4: Setter function if defined
10894 // Items 2-4 are only filled if the property has either a getter or a setter
10895 // defined through __defineGetter__ and/or __defineSetter__.
10896 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) {
10897  HandleScope scope(isolate);
10898 
10899  ASSERT(args.length() == 2);
10900 
10901  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10902  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10903 
10904  // Make sure to set the current context to the context before the debugger was
10905  // entered (if the debugger is entered). The reason for switching context here
10906  // is that for some property lookups (accessors and interceptors) callbacks
10907  // into the embedding application can occour, and the embedding application
10908  // could have the assumption that its own native context is the current
10909  // context and not some internal debugger context.
10910  SaveContext save(isolate);
10911  if (isolate->debug()->InDebugger()) {
10912  isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
10913  }
10914 
10915  // Skip the global proxy as it has no properties and always delegates to the
10916  // real global object.
10917  if (obj->IsJSGlobalProxy()) {
10918  obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
10919  }
10920 
10921 
10922  // Check if the name is trivially convertible to an index and get the element
10923  // if so.
10924  uint32_t index;
10925  if (name->AsArrayIndex(&index)) {
10926  Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
10927  Handle<Object> element_or_char =
10928  Runtime::GetElementOrCharAt(isolate, obj, index);
10929  RETURN_IF_EMPTY_HANDLE(isolate, element_or_char);
10930  details->set(0, *element_or_char);
10931  details->set(
10932  1, PropertyDetails(NONE, NORMAL, Representation::None()).AsSmi());
10933  return *isolate->factory()->NewJSArrayWithElements(details);
10934  }
10935 
10936  // Find the number of objects making up this.
10937  int length = LocalPrototypeChainLength(*obj);
10938 
10939  // Try local lookup on each of the objects.
10940  Handle<JSObject> jsproto = obj;
10941  for (int i = 0; i < length; i++) {
10942  LookupResult result(isolate);
10943  jsproto->LocalLookup(*name, &result);
10944  if (result.IsFound()) {
10945  // LookupResult is not GC safe as it holds raw object pointers.
10946  // GC can happen later in this code so put the required fields into
10947  // local variables using handles when required for later use.
10948  Handle<Object> result_callback_obj;
10949  if (result.IsPropertyCallbacks()) {
10950  result_callback_obj = Handle<Object>(result.GetCallbackObject(),
10951  isolate);
10952  }
10953  Smi* property_details = result.GetPropertyDetails().AsSmi();
10954  // DebugLookupResultValue can cause GC so details from LookupResult needs
10955  // to be copied to handles before this.
10956  bool caught_exception = false;
10957  Object* raw_value;
10958  { MaybeObject* maybe_raw_value =
10959  DebugLookupResultValue(isolate->heap(), *obj, *name,
10960  &result, &caught_exception);
10961  if (!maybe_raw_value->ToObject(&raw_value)) return maybe_raw_value;
10962  }
10963  Handle<Object> value(raw_value, isolate);
10964 
10965  // If the callback object is a fixed array then it contains JavaScript
10966  // getter and/or setter.
10967  bool hasJavaScriptAccessors = result.IsPropertyCallbacks() &&
10968  result_callback_obj->IsAccessorPair();
10969  Handle<FixedArray> details =
10970  isolate->factory()->NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
10971  details->set(0, *value);
10972  details->set(1, property_details);
10973  if (hasJavaScriptAccessors) {
10974  AccessorPair* accessors = AccessorPair::cast(*result_callback_obj);
10975  details->set(2, isolate->heap()->ToBoolean(caught_exception));
10976  details->set(3, accessors->GetComponent(ACCESSOR_GETTER));
10977  details->set(4, accessors->GetComponent(ACCESSOR_SETTER));
10978  }
10979 
10980  return *isolate->factory()->NewJSArrayWithElements(details);
10981  }
10982  if (i < length - 1) {
10983  jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
10984  }
10985  }
10986 
10987  return isolate->heap()->undefined_value();
10988 }
10989 
10990 
10991 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetProperty) {
10992  HandleScope scope(isolate);
10993 
10994  ASSERT(args.length() == 2);
10995 
10996  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10997  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10998 
10999  LookupResult result(isolate);
11000  obj->Lookup(*name, &result);
11001  if (result.IsFound()) {
11002  return DebugLookupResultValue(isolate->heap(), *obj, *name, &result, NULL);
11003  }
11004  return isolate->heap()->undefined_value();
11005 }
11006 
11007 
11008 // Return the property type calculated from the property details.
11009 // args[0]: smi with property details.
11010 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyTypeFromDetails) {
11011  SealHandleScope shs(isolate);
11012  ASSERT(args.length() == 1);
11014  return Smi::FromInt(static_cast<int>(details.type()));
11015 }
11016 
11017 
11018 // Return the property attribute calculated from the property details.
11019 // args[0]: smi with property details.
11020 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyAttributesFromDetails) {
11021  SealHandleScope shs(isolate);
11022  ASSERT(args.length() == 1);
11024  return Smi::FromInt(static_cast<int>(details.attributes()));
11025 }
11026 
11027 
11028 // Return the property insertion index calculated from the property details.
11029 // args[0]: smi with property details.
11030 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyIndexFromDetails) {
11031  SealHandleScope shs(isolate);
11032  ASSERT(args.length() == 1);
11034  // TODO(verwaest): Depends on the type of details.
11035  return Smi::FromInt(details.dictionary_index());
11036 }
11037 
11038 
11039 // Return property value from named interceptor.
11040 // args[0]: object
11041 // args[1]: property name
11042 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugNamedInterceptorPropertyValue) {
11043  HandleScope scope(isolate);
11044  ASSERT(args.length() == 2);
11045  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
11046  RUNTIME_ASSERT(obj->HasNamedInterceptor());
11047  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
11048 
11049  PropertyAttributes attributes;
11050  Handle<Object> result =
11051  JSObject::GetPropertyWithInterceptor(obj, obj, name, &attributes);
11052  RETURN_IF_EMPTY_HANDLE(isolate, result);
11053  return *result;
11054 }
11055 
11056 
11057 // Return element value from indexed interceptor.
11058 // args[0]: object
11059 // args[1]: index
11060 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugIndexedInterceptorElementValue) {
11061  HandleScope scope(isolate);
11062  ASSERT(args.length() == 2);
11063  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
11064  RUNTIME_ASSERT(obj->HasIndexedInterceptor());
11065  CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
11066  Handle<Object> result = JSObject::GetElementWithInterceptor(obj, obj, index);
11067  RETURN_IF_EMPTY_HANDLE(isolate, result);
11068  return *result;
11069 }
11070 
11071 
11072 RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckExecutionState) {
11073  SealHandleScope shs(isolate);
11074  ASSERT(args.length() >= 1);
11075  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
11076  // Check that the break id is valid.
11077  if (isolate->debug()->break_id() == 0 ||
11078  break_id != isolate->debug()->break_id()) {
11079  return isolate->Throw(
11080  isolate->heap()->illegal_execution_state_string());
11081  }
11082 
11083  return isolate->heap()->true_value();
11084 }
11085 
11086 
11087 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) {
11088  HandleScope scope(isolate);
11089  ASSERT(args.length() == 1);
11090 
11091  // Check arguments.
11092  Object* result;
11093  { MaybeObject* maybe_result = Runtime_CheckExecutionState(
11094  RUNTIME_ARGUMENTS(isolate, args));
11095  if (!maybe_result->ToObject(&result)) return maybe_result;
11096  }
11097 
11098  // Count all frames which are relevant to debugging stack trace.
11099  int n = 0;
11100  StackFrame::Id id = isolate->debug()->break_frame_id();
11101  if (id == StackFrame::NO_ID) {
11102  // If there is no JavaScript stack frame count is 0.
11103  return Smi::FromInt(0);
11104  }
11105 
11106  for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) {
11107  n += it.frame()->GetInlineCount();
11108  }
11109  return Smi::FromInt(n);
11110 }
11111 
11112 
11113 class FrameInspector {
11114  public:
11115  FrameInspector(JavaScriptFrame* frame,
11116  int inlined_jsframe_index,
11117  Isolate* isolate)
11118  : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
11119  // Calculate the deoptimized frame.
11120  if (frame->is_optimized()) {
11121  deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
11122  frame, inlined_jsframe_index, isolate);
11123  }
11124  has_adapted_arguments_ = frame_->has_adapted_arguments();
11125  is_bottommost_ = inlined_jsframe_index == 0;
11126  is_optimized_ = frame_->is_optimized();
11127  }
11128 
11129  ~FrameInspector() {
11130  // Get rid of the calculated deoptimized frame if any.
11131  if (deoptimized_frame_ != NULL) {
11132  Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_,
11133  isolate_);
11134  }
11135  }
11136 
11137  int GetParametersCount() {
11138  return is_optimized_
11139  ? deoptimized_frame_->parameters_count()
11140  : frame_->ComputeParametersCount();
11141  }
11142  int expression_count() { return deoptimized_frame_->expression_count(); }
11143  Object* GetFunction() {
11144  return is_optimized_
11145  ? deoptimized_frame_->GetFunction()
11146  : frame_->function();
11147  }
11148  Object* GetParameter(int index) {
11149  return is_optimized_
11150  ? deoptimized_frame_->GetParameter(index)
11151  : frame_->GetParameter(index);
11152  }
11153  Object* GetExpression(int index) {
11154  return is_optimized_
11155  ? deoptimized_frame_->GetExpression(index)
11156  : frame_->GetExpression(index);
11157  }
11158  int GetSourcePosition() {
11159  return is_optimized_
11160  ? deoptimized_frame_->GetSourcePosition()
11161  : frame_->LookupCode()->SourcePosition(frame_->pc());
11162  }
11163  bool IsConstructor() {
11164  return is_optimized_ && !is_bottommost_
11165  ? deoptimized_frame_->HasConstructStub()
11166  : frame_->IsConstructor();
11167  }
11168 
11169  // To inspect all the provided arguments the frame might need to be
11170  // replaced with the arguments frame.
11171  void SetArgumentsFrame(JavaScriptFrame* frame) {
11172  ASSERT(has_adapted_arguments_);
11173  frame_ = frame;
11174  is_optimized_ = frame_->is_optimized();
11175  ASSERT(!is_optimized_);
11176  }
11177 
11178  private:
11179  JavaScriptFrame* frame_;
11180  DeoptimizedFrameInfo* deoptimized_frame_;
11181  Isolate* isolate_;
11182  bool is_optimized_;
11183  bool is_bottommost_;
11184  bool has_adapted_arguments_;
11185 
11186  DISALLOW_COPY_AND_ASSIGN(FrameInspector);
11187 };
11188 
11189 
11190 static const int kFrameDetailsFrameIdIndex = 0;
11191 static const int kFrameDetailsReceiverIndex = 1;
11192 static const int kFrameDetailsFunctionIndex = 2;
11193 static const int kFrameDetailsArgumentCountIndex = 3;
11194 static const int kFrameDetailsLocalCountIndex = 4;
11195 static const int kFrameDetailsSourcePositionIndex = 5;
11196 static const int kFrameDetailsConstructCallIndex = 6;
11197 static const int kFrameDetailsAtReturnIndex = 7;
11198 static const int kFrameDetailsFlagsIndex = 8;
11199 static const int kFrameDetailsFirstDynamicIndex = 9;
11200 
11201 
11202 static SaveContext* FindSavedContextForFrame(Isolate* isolate,
11203  JavaScriptFrame* frame) {
11204  SaveContext* save = isolate->save_context();
11205  while (save != NULL && !save->IsBelowFrame(frame)) {
11206  save = save->prev();
11207  }
11208  ASSERT(save != NULL);
11209  return save;
11210 }
11211 
11212 
11213 // Return an array with frame details
11214 // args[0]: number: break id
11215 // args[1]: number: frame index
11216 //
11217 // The array returned contains the following information:
11218 // 0: Frame id
11219 // 1: Receiver
11220 // 2: Function
11221 // 3: Argument count
11222 // 4: Local count
11223 // 5: Source position
11224 // 6: Constructor call
11225 // 7: Is at return
11226 // 8: Flags
11227 // Arguments name, value
11228 // Locals name, value
11229 // Return value if any
11230 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
11231  HandleScope scope(isolate);
11232  ASSERT(args.length() == 2);
11233 
11234  // Check arguments.
11235  Object* check;
11236  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11237  RUNTIME_ARGUMENTS(isolate, args));
11238  if (!maybe_check->ToObject(&check)) return maybe_check;
11239  }
11240  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
11241  Heap* heap = isolate->heap();
11242 
11243  // Find the relevant frame with the requested index.
11244  StackFrame::Id id = isolate->debug()->break_frame_id();
11245  if (id == StackFrame::NO_ID) {
11246  // If there are no JavaScript stack frames return undefined.
11247  return heap->undefined_value();
11248  }
11249 
11250  int count = 0;
11251  JavaScriptFrameIterator it(isolate, id);
11252  for (; !it.done(); it.Advance()) {
11253  if (index < count + it.frame()->GetInlineCount()) break;
11254  count += it.frame()->GetInlineCount();
11255  }
11256  if (it.done()) return heap->undefined_value();
11257 
11258  bool is_optimized = it.frame()->is_optimized();
11259 
11260  int inlined_jsframe_index = 0; // Inlined frame index in optimized frame.
11261  if (is_optimized) {
11262  inlined_jsframe_index =
11263  it.frame()->GetInlineCount() - (index - count) - 1;
11264  }
11265  FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate);
11266 
11267  // Traverse the saved contexts chain to find the active context for the
11268  // selected frame.
11269  SaveContext* save = FindSavedContextForFrame(isolate, it.frame());
11270 
11271  // Get the frame id.
11272  Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate);
11273 
11274  // Find source position in unoptimized code.
11275  int position = frame_inspector.GetSourcePosition();
11276 
11277  // Check for constructor frame.
11278  bool constructor = frame_inspector.IsConstructor();
11279 
11280  // Get scope info and read from it for local variable information.
11281  Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
11282  Handle<SharedFunctionInfo> shared(function->shared());
11283  Handle<ScopeInfo> scope_info(shared->scope_info());
11284  ASSERT(*scope_info != ScopeInfo::Empty(isolate));
11285 
11286  // Get the locals names and values into a temporary array.
11287  //
11288  // TODO(1240907): Hide compiler-introduced stack variables
11289  // (e.g. .result)? For users of the debugger, they will probably be
11290  // confusing.
11291  Handle<FixedArray> locals =
11292  isolate->factory()->NewFixedArray(scope_info->LocalCount() * 2);
11293 
11294  // Fill in the values of the locals.
11295  int i = 0;
11296  for (; i < scope_info->StackLocalCount(); ++i) {
11297  // Use the value from the stack.
11298  locals->set(i * 2, scope_info->LocalName(i));
11299  locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
11300  }
11301  if (i < scope_info->LocalCount()) {
11302  // Get the context containing declarations.
11303  Handle<Context> context(
11304  Context::cast(it.frame()->context())->declaration_context());
11305  for (; i < scope_info->LocalCount(); ++i) {
11306  Handle<String> name(scope_info->LocalName(i));
11308  InitializationFlag init_flag;
11309  locals->set(i * 2, *name);
11310  int context_slot_index =
11311  scope_info->ContextSlotIndex(*name, &mode, &init_flag);
11312  Object* value = context->get(context_slot_index);
11313  locals->set(i * 2 + 1, value);
11314  }
11315  }
11316 
11317  // Check whether this frame is positioned at return. If not top
11318  // frame or if the frame is optimized it cannot be at a return.
11319  bool at_return = false;
11320  if (!is_optimized && index == 0) {
11321  at_return = isolate->debug()->IsBreakAtReturn(it.frame());
11322  }
11323 
11324  // If positioned just before return find the value to be returned and add it
11325  // to the frame information.
11326  Handle<Object> return_value = isolate->factory()->undefined_value();
11327  if (at_return) {
11328  StackFrameIterator it2(isolate);
11329  Address internal_frame_sp = NULL;
11330  while (!it2.done()) {
11331  if (it2.frame()->is_internal()) {
11332  internal_frame_sp = it2.frame()->sp();
11333  } else {
11334  if (it2.frame()->is_java_script()) {
11335  if (it2.frame()->id() == it.frame()->id()) {
11336  // The internal frame just before the JavaScript frame contains the
11337  // value to return on top. A debug break at return will create an
11338  // internal frame to store the return value (eax/rax/r0) before
11339  // entering the debug break exit frame.
11340  if (internal_frame_sp != NULL) {
11341  return_value =
11342  Handle<Object>(Memory::Object_at(internal_frame_sp),
11343  isolate);
11344  break;
11345  }
11346  }
11347  }
11348 
11349  // Indicate that the previous frame was not an internal frame.
11350  internal_frame_sp = NULL;
11351  }
11352  it2.Advance();
11353  }
11354  }
11355 
11356  // Now advance to the arguments adapter frame (if any). It contains all
11357  // the provided parameters whereas the function frame always have the number
11358  // of arguments matching the functions parameters. The rest of the
11359  // information (except for what is collected above) is the same.
11360  if ((inlined_jsframe_index == 0) && it.frame()->has_adapted_arguments()) {
11361  it.AdvanceToArgumentsFrame();
11362  frame_inspector.SetArgumentsFrame(it.frame());
11363  }
11364 
11365  // Find the number of arguments to fill. At least fill the number of
11366  // parameters for the function and fill more if more parameters are provided.
11367  int argument_count = scope_info->ParameterCount();
11368  if (argument_count < frame_inspector.GetParametersCount()) {
11369  argument_count = frame_inspector.GetParametersCount();
11370  }
11371 
11372  // Calculate the size of the result.
11373  int details_size = kFrameDetailsFirstDynamicIndex +
11374  2 * (argument_count + scope_info->LocalCount()) +
11375  (at_return ? 1 : 0);
11376  Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
11377 
11378  // Add the frame id.
11379  details->set(kFrameDetailsFrameIdIndex, *frame_id);
11380 
11381  // Add the function (same as in function frame).
11382  details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
11383 
11384  // Add the arguments count.
11385  details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
11386 
11387  // Add the locals count
11388  details->set(kFrameDetailsLocalCountIndex,
11389  Smi::FromInt(scope_info->LocalCount()));
11390 
11391  // Add the source position.
11392  if (position != RelocInfo::kNoPosition) {
11393  details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
11394  } else {
11395  details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
11396  }
11397 
11398  // Add the constructor information.
11399  details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
11400 
11401  // Add the at return information.
11402  details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
11403 
11404  // Add flags to indicate information on whether this frame is
11405  // bit 0: invoked in the debugger context.
11406  // bit 1: optimized frame.
11407  // bit 2: inlined in optimized frame
11408  int flags = 0;
11409  if (*save->context() == *isolate->debug()->debug_context()) {
11410  flags |= 1 << 0;
11411  }
11412  if (is_optimized) {
11413  flags |= 1 << 1;
11414  flags |= inlined_jsframe_index << 2;
11415  }
11416  details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
11417 
11418  // Fill the dynamic part.
11419  int details_index = kFrameDetailsFirstDynamicIndex;
11420 
11421  // Add arguments name and value.
11422  for (int i = 0; i < argument_count; i++) {
11423  // Name of the argument.
11424  if (i < scope_info->ParameterCount()) {
11425  details->set(details_index++, scope_info->ParameterName(i));
11426  } else {
11427  details->set(details_index++, heap->undefined_value());
11428  }
11429 
11430  // Parameter value.
11431  if (i < frame_inspector.GetParametersCount()) {
11432  // Get the value from the stack.
11433  details->set(details_index++, frame_inspector.GetParameter(i));
11434  } else {
11435  details->set(details_index++, heap->undefined_value());
11436  }
11437  }
11438 
11439  // Add locals name and value from the temporary copy from the function frame.
11440  for (int i = 0; i < scope_info->LocalCount() * 2; i++) {
11441  details->set(details_index++, locals->get(i));
11442  }
11443 
11444  // Add the value being returned.
11445  if (at_return) {
11446  details->set(details_index++, *return_value);
11447  }
11448 
11449  // Add the receiver (same as in function frame).
11450  // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
11451  // THE FRAME ITERATOR TO WRAP THE RECEIVER.
11452  Handle<Object> receiver(it.frame()->receiver(), isolate);
11453  if (!receiver->IsJSObject() &&
11454  shared->strict_mode() == SLOPPY &&
11455  !function->IsBuiltin()) {
11456  // If the receiver is not a JSObject and the function is not a
11457  // builtin or strict-mode we have hit an optimization where a
11458  // value object is not converted into a wrapped JS objects. To
11459  // hide this optimization from the debugger, we wrap the receiver
11460  // by creating correct wrapper object based on the calling frame's
11461  // native context.
11462  it.Advance();
11463  if (receiver->IsUndefined()) {
11464  Context* context = function->context();
11465  receiver = handle(context->global_object()->global_receiver());
11466  } else {
11467  ASSERT(!receiver->IsNull());
11468  Context* context = Context::cast(it.frame()->context());
11469  Handle<Context> native_context(Context::cast(context->native_context()));
11470  receiver = isolate->factory()->ToObject(receiver, native_context);
11471  }
11472  }
11473  details->set(kFrameDetailsReceiverIndex, *receiver);
11474 
11475  ASSERT_EQ(details_size, details_index);
11476  return *isolate->factory()->NewJSArrayWithElements(details);
11477 }
11478 
11479 
11480 static bool ParameterIsShadowedByContextLocal(Handle<ScopeInfo> info,
11481  int index) {
11484  return info->ContextSlotIndex(info->ParameterName(index), &mode, &flag) != -1;
11485 }
11486 
11487 
11488 // Create a plain JSObject which materializes the local scope for the specified
11489 // frame.
11490 static Handle<JSObject> MaterializeStackLocalsWithFrameInspector(
11491  Isolate* isolate,
11492  Handle<JSObject> target,
11493  Handle<JSFunction> function,
11494  FrameInspector* frame_inspector) {
11495  Handle<SharedFunctionInfo> shared(function->shared());
11496  Handle<ScopeInfo> scope_info(shared->scope_info());
11497 
11498  // First fill all parameters.
11499  for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11500  // Do not materialize the parameter if it is shadowed by a context local.
11501  if (ParameterIsShadowedByContextLocal(scope_info, i)) continue;
11502 
11503  HandleScope scope(isolate);
11504  Handle<Object> value(i < frame_inspector->GetParametersCount()
11505  ? frame_inspector->GetParameter(i)
11506  : isolate->heap()->undefined_value(),
11507  isolate);
11508  ASSERT(!value->IsTheHole());
11509  Handle<String> name(scope_info->ParameterName(i));
11510 
11512  isolate,
11513  Runtime::SetObjectProperty(isolate, target, name, value, NONE, SLOPPY),
11514  Handle<JSObject>());
11515  }
11516 
11517  // Second fill all stack locals.
11518  for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11519  Handle<String> name(scope_info->StackLocalName(i));
11520  Handle<Object> value(frame_inspector->GetExpression(i), isolate);
11521  if (value->IsTheHole()) continue;
11522 
11524  isolate,
11525  Runtime::SetObjectProperty(isolate, target, name, value, NONE, SLOPPY),
11526  Handle<JSObject>());
11527  }
11528 
11529  return target;
11530 }
11531 
11532 
11533 static void UpdateStackLocalsFromMaterializedObject(Isolate* isolate,
11534  Handle<JSObject> target,
11535  Handle<JSFunction> function,
11536  JavaScriptFrame* frame,
11537  int inlined_jsframe_index) {
11538  if (inlined_jsframe_index != 0 || frame->is_optimized()) {
11539  // Optimized frames are not supported.
11540  // TODO(yangguo): make sure all code deoptimized when debugger is active
11541  // and assert that this cannot happen.
11542  return;
11543  }
11544 
11545  Handle<SharedFunctionInfo> shared(function->shared());
11546  Handle<ScopeInfo> scope_info(shared->scope_info());
11547 
11548  // Parameters.
11549  for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11550  // Shadowed parameters were not materialized.
11551  if (ParameterIsShadowedByContextLocal(scope_info, i)) continue;
11552 
11553  ASSERT(!frame->GetParameter(i)->IsTheHole());
11554  HandleScope scope(isolate);
11555  Handle<String> name(scope_info->ParameterName(i));
11556  Handle<Object> value = GetProperty(isolate, target, name);
11557  frame->SetParameterValue(i, *value);
11558  }
11559 
11560  // Stack locals.
11561  for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11562  if (frame->GetExpression(i)->IsTheHole()) continue;
11563  HandleScope scope(isolate);
11564  Handle<Object> value = GetProperty(
11565  isolate, target, Handle<String>(scope_info->StackLocalName(i)));
11566  frame->SetExpression(i, *value);
11567  }
11568 }
11569 
11570 
11571 static Handle<JSObject> MaterializeLocalContext(Isolate* isolate,
11572  Handle<JSObject> target,
11573  Handle<JSFunction> function,
11574  JavaScriptFrame* frame) {
11575  HandleScope scope(isolate);
11576  Handle<SharedFunctionInfo> shared(function->shared());
11577  Handle<ScopeInfo> scope_info(shared->scope_info());
11578 
11579  if (!scope_info->HasContext()) return target;
11580 
11581  // Third fill all context locals.
11582  Handle<Context> frame_context(Context::cast(frame->context()));
11583  Handle<Context> function_context(frame_context->declaration_context());
11585  scope_info, function_context, target)) {
11586  return Handle<JSObject>();
11587  }
11588 
11589  // Finally copy any properties from the function context extension.
11590  // These will be variables introduced by eval.
11591  if (function_context->closure() == *function) {
11592  if (function_context->has_extension() &&
11593  !function_context->IsNativeContext()) {
11594  Handle<JSObject> ext(JSObject::cast(function_context->extension()));
11595  bool threw = false;
11596  Handle<FixedArray> keys =
11597  GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
11598  if (threw) return Handle<JSObject>();
11599 
11600  for (int i = 0; i < keys->length(); i++) {
11601  // Names of variables introduced by eval are strings.
11602  ASSERT(keys->get(i)->IsString());
11603  Handle<String> key(String::cast(keys->get(i)));
11605  isolate,
11607  target,
11608  key,
11609  GetProperty(isolate, ext, key),
11610  NONE,
11611  SLOPPY),
11612  Handle<JSObject>());
11613  }
11614  }
11615  }
11616 
11617  return target;
11618 }
11619 
11620 
11621 static Handle<JSObject> MaterializeLocalScope(
11622  Isolate* isolate,
11623  JavaScriptFrame* frame,
11624  int inlined_jsframe_index) {
11625  FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
11626  Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
11627 
11628  Handle<JSObject> local_scope =
11629  isolate->factory()->NewJSObject(isolate->object_function());
11630  local_scope = MaterializeStackLocalsWithFrameInspector(
11631  isolate, local_scope, function, &frame_inspector);
11632  RETURN_IF_EMPTY_HANDLE_VALUE(isolate, local_scope, Handle<JSObject>());
11633 
11634  return MaterializeLocalContext(isolate, local_scope, function, frame);
11635 }
11636 
11637 
11638 // Set the context local variable value.
11639 static bool SetContextLocalValue(Isolate* isolate,
11640  Handle<ScopeInfo> scope_info,
11641  Handle<Context> context,
11642  Handle<String> variable_name,
11643  Handle<Object> new_value) {
11644  for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
11645  Handle<String> next_name(scope_info->ContextLocalName(i));
11646  if (variable_name->Equals(*next_name)) {
11648  InitializationFlag init_flag;
11649  int context_index =
11650  scope_info->ContextSlotIndex(*next_name, &mode, &init_flag);
11651  context->set(context_index, *new_value);
11652  return true;
11653  }
11654  }
11655 
11656  return false;
11657 }
11658 
11659 
11660 static bool SetLocalVariableValue(Isolate* isolate,
11661  JavaScriptFrame* frame,
11662  int inlined_jsframe_index,
11663  Handle<String> variable_name,
11664  Handle<Object> new_value) {
11665  if (inlined_jsframe_index != 0 || frame->is_optimized()) {
11666  // Optimized frames are not supported.
11667  return false;
11668  }
11669 
11670  Handle<JSFunction> function(frame->function());
11671  Handle<SharedFunctionInfo> shared(function->shared());
11672  Handle<ScopeInfo> scope_info(shared->scope_info());
11673 
11674  bool default_result = false;
11675 
11676  // Parameters.
11677  for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11678  if (scope_info->ParameterName(i)->Equals(*variable_name)) {
11679  frame->SetParameterValue(i, *new_value);
11680  // Argument might be shadowed in heap context, don't stop here.
11681  default_result = true;
11682  }
11683  }
11684 
11685  // Stack locals.
11686  for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11687  if (scope_info->StackLocalName(i)->Equals(*variable_name)) {
11688  frame->SetExpression(i, *new_value);
11689  return true;
11690  }
11691  }
11692 
11693  if (scope_info->HasContext()) {
11694  // Context locals.
11695  Handle<Context> frame_context(Context::cast(frame->context()));
11696  Handle<Context> function_context(frame_context->declaration_context());
11697  if (SetContextLocalValue(
11698  isolate, scope_info, function_context, variable_name, new_value)) {
11699  return true;
11700  }
11701 
11702  // Function context extension. These are variables introduced by eval.
11703  if (function_context->closure() == *function) {
11704  if (function_context->has_extension() &&
11705  !function_context->IsNativeContext()) {
11706  Handle<JSObject> ext(JSObject::cast(function_context->extension()));
11707 
11708  if (JSReceiver::HasProperty(ext, variable_name)) {
11709  // We don't expect this to do anything except replacing
11710  // property value.
11711  Runtime::SetObjectProperty(isolate, ext, variable_name, new_value,
11712  NONE, SLOPPY);
11713  return true;
11714  }
11715  }
11716  }
11717  }
11718 
11719  return default_result;
11720 }
11721 
11722 
11723 // Create a plain JSObject which materializes the closure content for the
11724 // context.
11725 static Handle<JSObject> MaterializeClosure(Isolate* isolate,
11726  Handle<Context> context) {
11727  ASSERT(context->IsFunctionContext());
11728 
11729  Handle<SharedFunctionInfo> shared(context->closure()->shared());
11730  Handle<ScopeInfo> scope_info(shared->scope_info());
11731 
11732  // Allocate and initialize a JSObject with all the content of this function
11733  // closure.
11734  Handle<JSObject> closure_scope =
11735  isolate->factory()->NewJSObject(isolate->object_function());
11736 
11737  // Fill all context locals to the context extension.
11739  scope_info, context, closure_scope)) {
11740  return Handle<JSObject>();
11741  }
11742 
11743  // Finally copy any properties from the function context extension. This will
11744  // be variables introduced by eval.
11745  if (context->has_extension()) {
11746  Handle<JSObject> ext(JSObject::cast(context->extension()));
11747  bool threw = false;
11748  Handle<FixedArray> keys =
11749  GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
11750  if (threw) return Handle<JSObject>();
11751 
11752  for (int i = 0; i < keys->length(); i++) {
11753  // Names of variables introduced by eval are strings.
11754  ASSERT(keys->get(i)->IsString());
11755  Handle<String> key(String::cast(keys->get(i)));
11757  isolate,
11758  Runtime::SetObjectProperty(isolate, closure_scope, key,
11759  GetProperty(isolate, ext, key),
11760  NONE, SLOPPY),
11761  Handle<JSObject>());
11762  }
11763  }
11764 
11765  return closure_scope;
11766 }
11767 
11768 
11769 // This method copies structure of MaterializeClosure method above.
11770 static bool SetClosureVariableValue(Isolate* isolate,
11771  Handle<Context> context,
11772  Handle<String> variable_name,
11773  Handle<Object> new_value) {
11774  ASSERT(context->IsFunctionContext());
11775 
11776  Handle<SharedFunctionInfo> shared(context->closure()->shared());
11777  Handle<ScopeInfo> scope_info(shared->scope_info());
11778 
11779  // Context locals to the context extension.
11780  if (SetContextLocalValue(
11781  isolate, scope_info, context, variable_name, new_value)) {
11782  return true;
11783  }
11784 
11785  // Properties from the function context extension. This will
11786  // be variables introduced by eval.
11787  if (context->has_extension()) {
11788  Handle<JSObject> ext(JSObject::cast(context->extension()));
11789  if (JSReceiver::HasProperty(ext, variable_name)) {
11790  // We don't expect this to do anything except replacing property value.
11791  Runtime::SetObjectProperty(isolate, ext, variable_name, new_value,
11792  NONE, SLOPPY);
11793  return true;
11794  }
11795  }
11796 
11797  return false;
11798 }
11799 
11800 
11801 // Create a plain JSObject which materializes the scope for the specified
11802 // catch context.
11803 static Handle<JSObject> MaterializeCatchScope(Isolate* isolate,
11804  Handle<Context> context) {
11805  ASSERT(context->IsCatchContext());
11806  Handle<String> name(String::cast(context->extension()));
11807  Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX),
11808  isolate);
11809  Handle<JSObject> catch_scope =
11810  isolate->factory()->NewJSObject(isolate->object_function());
11812  isolate,
11813  Runtime::SetObjectProperty(isolate, catch_scope, name, thrown_object,
11814  NONE, SLOPPY),
11815  Handle<JSObject>());
11816  return catch_scope;
11817 }
11818 
11819 
11820 static bool SetCatchVariableValue(Isolate* isolate,
11821  Handle<Context> context,
11822  Handle<String> variable_name,
11823  Handle<Object> new_value) {
11824  ASSERT(context->IsCatchContext());
11825  Handle<String> name(String::cast(context->extension()));
11826  if (!name->Equals(*variable_name)) {
11827  return false;
11828  }
11829  context->set(Context::THROWN_OBJECT_INDEX, *new_value);
11830  return true;
11831 }
11832 
11833 
11834 // Create a plain JSObject which materializes the block scope for the specified
11835 // block context.
11836 static Handle<JSObject> MaterializeBlockScope(
11837  Isolate* isolate,
11838  Handle<Context> context) {
11839  ASSERT(context->IsBlockContext());
11840  Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
11841 
11842  // Allocate and initialize a JSObject with all the arguments, stack locals
11843  // heap locals and extension properties of the debugged function.
11844  Handle<JSObject> block_scope =
11845  isolate->factory()->NewJSObject(isolate->object_function());
11846 
11847  // Fill all context locals.
11849  scope_info, context, block_scope)) {
11850  return Handle<JSObject>();
11851  }
11852 
11853  return block_scope;
11854 }
11855 
11856 
11857 // Create a plain JSObject which materializes the module scope for the specified
11858 // module context.
11859 static Handle<JSObject> MaterializeModuleScope(
11860  Isolate* isolate,
11861  Handle<Context> context) {
11862  ASSERT(context->IsModuleContext());
11863  Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
11864 
11865  // Allocate and initialize a JSObject with all the members of the debugged
11866  // module.
11867  Handle<JSObject> module_scope =
11868  isolate->factory()->NewJSObject(isolate->object_function());
11869 
11870  // Fill all context locals.
11872  scope_info, context, module_scope)) {
11873  return Handle<JSObject>();
11874  }
11875 
11876  return module_scope;
11877 }
11878 
11879 
11880 // Iterate over the actual scopes visible from a stack frame or from a closure.
11881 // The iteration proceeds from the innermost visible nested scope outwards.
11882 // All scopes are backed by an actual context except the local scope,
11883 // which is inserted "artificially" in the context chain.
11884 class ScopeIterator {
11885  public:
11886  enum ScopeType {
11887  ScopeTypeGlobal = 0,
11888  ScopeTypeLocal,
11889  ScopeTypeWith,
11890  ScopeTypeClosure,
11891  ScopeTypeCatch,
11892  ScopeTypeBlock,
11893  ScopeTypeModule
11894  };
11895 
11896  ScopeIterator(Isolate* isolate,
11897  JavaScriptFrame* frame,
11898  int inlined_jsframe_index,
11899  bool ignore_nested_scopes = false)
11900  : isolate_(isolate),
11901  frame_(frame),
11902  inlined_jsframe_index_(inlined_jsframe_index),
11903  function_(frame->function()),
11904  context_(Context::cast(frame->context())),
11905  nested_scope_chain_(4),
11906  failed_(false) {
11907 
11908  // Catch the case when the debugger stops in an internal function.
11909  Handle<SharedFunctionInfo> shared_info(function_->shared());
11910  Handle<ScopeInfo> scope_info(shared_info->scope_info());
11911  if (shared_info->script() == isolate->heap()->undefined_value()) {
11912  while (context_->closure() == *function_) {
11913  context_ = Handle<Context>(context_->previous(), isolate_);
11914  }
11915  return;
11916  }
11917 
11918  // Get the debug info (create it if it does not exist).
11919  if (!isolate->debug()->EnsureDebugInfo(shared_info, function_)) {
11920  // Return if ensuring debug info failed.
11921  return;
11922  }
11923 
11924  // Currently it takes too much time to find nested scopes due to script
11925  // parsing. Sometimes we want to run the ScopeIterator as fast as possible
11926  // (for example, while collecting async call stacks on every
11927  // addEventListener call), even if we drop some nested scopes.
11928  // Later we may optimize getting the nested scopes (cache the result?)
11929  // and include nested scopes into the "fast" iteration case as well.
11930  if (!ignore_nested_scopes) {
11931  Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared_info);
11932 
11933  // Find the break point where execution has stopped.
11934  BreakLocationIterator break_location_iterator(debug_info,
11935  ALL_BREAK_LOCATIONS);
11936  // pc points to the instruction after the current one, possibly a break
11937  // location as well. So the "- 1" to exclude it from the search.
11938  break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
11939 
11940  // Within the return sequence at the moment it is not possible to
11941  // get a source position which is consistent with the current scope chain.
11942  // Thus all nested with, catch and block contexts are skipped and we only
11943  // provide the function scope.
11944  ignore_nested_scopes = break_location_iterator.IsExit();
11945  }
11946 
11947  if (ignore_nested_scopes) {
11948  if (scope_info->HasContext()) {
11949  context_ = Handle<Context>(context_->declaration_context(), isolate_);
11950  } else {
11951  while (context_->closure() == *function_) {
11952  context_ = Handle<Context>(context_->previous(), isolate_);
11953  }
11954  }
11955  if (scope_info->scope_type() == FUNCTION_SCOPE) {
11956  nested_scope_chain_.Add(scope_info);
11957  }
11958  } else {
11959  // Reparse the code and analyze the scopes.
11960  Handle<Script> script(Script::cast(shared_info->script()));
11961  Scope* scope = NULL;
11962 
11963  // Check whether we are in global, eval or function code.
11964  Handle<ScopeInfo> scope_info(shared_info->scope_info());
11965  if (scope_info->scope_type() != FUNCTION_SCOPE) {
11966  // Global or eval code.
11967  CompilationInfoWithZone info(script);
11968  if (scope_info->scope_type() == GLOBAL_SCOPE) {
11969  info.MarkAsGlobal();
11970  } else {
11971  ASSERT(scope_info->scope_type() == EVAL_SCOPE);
11972  info.MarkAsEval();
11973  info.SetContext(Handle<Context>(function_->context()));
11974  }
11975  if (Parser::Parse(&info) && Scope::Analyze(&info)) {
11976  scope = info.function()->scope();
11977  }
11978  RetrieveScopeChain(scope, shared_info);
11979  } else {
11980  // Function code
11981  CompilationInfoWithZone info(shared_info);
11982  if (Parser::Parse(&info) && Scope::Analyze(&info)) {
11983  scope = info.function()->scope();
11984  }
11985  RetrieveScopeChain(scope, shared_info);
11986  }
11987  }
11988  }
11989 
11990  ScopeIterator(Isolate* isolate,
11991  Handle<JSFunction> function)
11992  : isolate_(isolate),
11993  frame_(NULL),
11994  inlined_jsframe_index_(0),
11995  function_(function),
11996  context_(function->context()),
11997  failed_(false) {
11998  if (function->IsBuiltin()) {
11999  context_ = Handle<Context>();
12000  }
12001  }
12002 
12003  // More scopes?
12004  bool Done() {
12005  ASSERT(!failed_);
12006  return context_.is_null();
12007  }
12008 
12009  bool Failed() { return failed_; }
12010 
12011  // Move to the next scope.
12012  void Next() {
12013  ASSERT(!failed_);
12014  ScopeType scope_type = Type();
12015  if (scope_type == ScopeTypeGlobal) {
12016  // The global scope is always the last in the chain.
12017  ASSERT(context_->IsNativeContext());
12018  context_ = Handle<Context>();
12019  return;
12020  }
12021  if (nested_scope_chain_.is_empty()) {
12022  context_ = Handle<Context>(context_->previous(), isolate_);
12023  } else {
12024  if (nested_scope_chain_.last()->HasContext()) {
12025  ASSERT(context_->previous() != NULL);
12026  context_ = Handle<Context>(context_->previous(), isolate_);
12027  }
12028  nested_scope_chain_.RemoveLast();
12029  }
12030  }
12031 
12032  // Return the type of the current scope.
12033  ScopeType Type() {
12034  ASSERT(!failed_);
12035  if (!nested_scope_chain_.is_empty()) {
12036  Handle<ScopeInfo> scope_info = nested_scope_chain_.last();
12037  switch (scope_info->scope_type()) {
12038  case FUNCTION_SCOPE:
12039  ASSERT(context_->IsFunctionContext() ||
12040  !scope_info->HasContext());
12041  return ScopeTypeLocal;
12042  case MODULE_SCOPE:
12043  ASSERT(context_->IsModuleContext());
12044  return ScopeTypeModule;
12045  case GLOBAL_SCOPE:
12046  ASSERT(context_->IsNativeContext());
12047  return ScopeTypeGlobal;
12048  case WITH_SCOPE:
12049  ASSERT(context_->IsWithContext());
12050  return ScopeTypeWith;
12051  case CATCH_SCOPE:
12052  ASSERT(context_->IsCatchContext());
12053  return ScopeTypeCatch;
12054  case BLOCK_SCOPE:
12055  ASSERT(!scope_info->HasContext() ||
12056  context_->IsBlockContext());
12057  return ScopeTypeBlock;
12058  case EVAL_SCOPE:
12059  UNREACHABLE();
12060  }
12061  }
12062  if (context_->IsNativeContext()) {
12063  ASSERT(context_->global_object()->IsGlobalObject());
12064  return ScopeTypeGlobal;
12065  }
12066  if (context_->IsFunctionContext()) {
12067  return ScopeTypeClosure;
12068  }
12069  if (context_->IsCatchContext()) {
12070  return ScopeTypeCatch;
12071  }
12072  if (context_->IsBlockContext()) {
12073  return ScopeTypeBlock;
12074  }
12075  if (context_->IsModuleContext()) {
12076  return ScopeTypeModule;
12077  }
12078  ASSERT(context_->IsWithContext());
12079  return ScopeTypeWith;
12080  }
12081 
12082  // Return the JavaScript object with the content of the current scope.
12083  Handle<JSObject> ScopeObject() {
12084  ASSERT(!failed_);
12085  switch (Type()) {
12086  case ScopeIterator::ScopeTypeGlobal:
12087  return Handle<JSObject>(CurrentContext()->global_object());
12088  case ScopeIterator::ScopeTypeLocal:
12089  // Materialize the content of the local scope into a JSObject.
12090  ASSERT(nested_scope_chain_.length() == 1);
12091  return MaterializeLocalScope(isolate_, frame_, inlined_jsframe_index_);
12092  case ScopeIterator::ScopeTypeWith:
12093  // Return the with object.
12094  return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
12095  case ScopeIterator::ScopeTypeCatch:
12096  return MaterializeCatchScope(isolate_, CurrentContext());
12097  case ScopeIterator::ScopeTypeClosure:
12098  // Materialize the content of the closure scope into a JSObject.
12099  return MaterializeClosure(isolate_, CurrentContext());
12100  case ScopeIterator::ScopeTypeBlock:
12101  return MaterializeBlockScope(isolate_, CurrentContext());
12102  case ScopeIterator::ScopeTypeModule:
12103  return MaterializeModuleScope(isolate_, CurrentContext());
12104  }
12105  UNREACHABLE();
12106  return Handle<JSObject>();
12107  }
12108 
12109  bool SetVariableValue(Handle<String> variable_name,
12110  Handle<Object> new_value) {
12111  ASSERT(!failed_);
12112  switch (Type()) {
12113  case ScopeIterator::ScopeTypeGlobal:
12114  break;
12115  case ScopeIterator::ScopeTypeLocal:
12116  return SetLocalVariableValue(isolate_, frame_, inlined_jsframe_index_,
12117  variable_name, new_value);
12118  case ScopeIterator::ScopeTypeWith:
12119  break;
12120  case ScopeIterator::ScopeTypeCatch:
12121  return SetCatchVariableValue(isolate_, CurrentContext(),
12122  variable_name, new_value);
12123  case ScopeIterator::ScopeTypeClosure:
12124  return SetClosureVariableValue(isolate_, CurrentContext(),
12125  variable_name, new_value);
12126  case ScopeIterator::ScopeTypeBlock:
12127  // TODO(2399): should we implement it?
12128  break;
12129  case ScopeIterator::ScopeTypeModule:
12130  // TODO(2399): should we implement it?
12131  break;
12132  }
12133  return false;
12134  }
12135 
12136  Handle<ScopeInfo> CurrentScopeInfo() {
12137  ASSERT(!failed_);
12138  if (!nested_scope_chain_.is_empty()) {
12139  return nested_scope_chain_.last();
12140  } else if (context_->IsBlockContext()) {
12141  return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension()));
12142  } else if (context_->IsFunctionContext()) {
12143  return Handle<ScopeInfo>(context_->closure()->shared()->scope_info());
12144  }
12145  return Handle<ScopeInfo>::null();
12146  }
12147 
12148  // Return the context for this scope. For the local context there might not
12149  // be an actual context.
12150  Handle<Context> CurrentContext() {
12151  ASSERT(!failed_);
12152  if (Type() == ScopeTypeGlobal ||
12153  nested_scope_chain_.is_empty()) {
12154  return context_;
12155  } else if (nested_scope_chain_.last()->HasContext()) {
12156  return context_;
12157  } else {
12158  return Handle<Context>();
12159  }
12160  }
12161 
12162 #ifdef DEBUG
12163  // Debug print of the content of the current scope.
12164  void DebugPrint() {
12165  ASSERT(!failed_);
12166  switch (Type()) {
12167  case ScopeIterator::ScopeTypeGlobal:
12168  PrintF("Global:\n");
12169  CurrentContext()->Print();
12170  break;
12171 
12172  case ScopeIterator::ScopeTypeLocal: {
12173  PrintF("Local:\n");
12174  function_->shared()->scope_info()->Print();
12175  if (!CurrentContext().is_null()) {
12176  CurrentContext()->Print();
12177  if (CurrentContext()->has_extension()) {
12178  Handle<Object> extension(CurrentContext()->extension(), isolate_);
12179  if (extension->IsJSContextExtensionObject()) {
12180  extension->Print();
12181  }
12182  }
12183  }
12184  break;
12185  }
12186 
12187  case ScopeIterator::ScopeTypeWith:
12188  PrintF("With:\n");
12189  CurrentContext()->extension()->Print();
12190  break;
12191 
12192  case ScopeIterator::ScopeTypeCatch:
12193  PrintF("Catch:\n");
12194  CurrentContext()->extension()->Print();
12195  CurrentContext()->get(Context::THROWN_OBJECT_INDEX)->Print();
12196  break;
12197 
12198  case ScopeIterator::ScopeTypeClosure:
12199  PrintF("Closure:\n");
12200  CurrentContext()->Print();
12201  if (CurrentContext()->has_extension()) {
12202  Handle<Object> extension(CurrentContext()->extension(), isolate_);
12203  if (extension->IsJSContextExtensionObject()) {
12204  extension->Print();
12205  }
12206  }
12207  break;
12208 
12209  default:
12210  UNREACHABLE();
12211  }
12212  PrintF("\n");
12213  }
12214 #endif
12215 
12216  private:
12217  Isolate* isolate_;
12218  JavaScriptFrame* frame_;
12219  int inlined_jsframe_index_;
12220  Handle<JSFunction> function_;
12221  Handle<Context> context_;
12222  List<Handle<ScopeInfo> > nested_scope_chain_;
12223  bool failed_;
12224 
12225  void RetrieveScopeChain(Scope* scope,
12226  Handle<SharedFunctionInfo> shared_info) {
12227  if (scope != NULL) {
12228  int source_position = shared_info->code()->SourcePosition(frame_->pc());
12229  scope->GetNestedScopeChain(&nested_scope_chain_, source_position);
12230  } else {
12231  // A failed reparse indicates that the preparser has diverged from the
12232  // parser or that the preparse data given to the initial parse has been
12233  // faulty. We fail in debug mode but in release mode we only provide the
12234  // information we get from the context chain but nothing about
12235  // completely stack allocated scopes or stack allocated locals.
12236  // Or it could be due to stack overflow.
12237  ASSERT(isolate_->has_pending_exception());
12238  failed_ = true;
12239  }
12240  }
12241 
12242  DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
12243 };
12244 
12245 
12246 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
12247  HandleScope scope(isolate);
12248  ASSERT(args.length() == 2);
12249 
12250  // Check arguments.
12251  Object* check;
12252  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12253  RUNTIME_ARGUMENTS(isolate, args));
12254  if (!maybe_check->ToObject(&check)) return maybe_check;
12255  }
12256  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12257 
12258  // Get the frame where the debugging is performed.
12259  StackFrame::Id id = UnwrapFrameId(wrapped_id);
12260  JavaScriptFrameIterator it(isolate, id);
12261  JavaScriptFrame* frame = it.frame();
12262 
12263  // Count the visible scopes.
12264  int n = 0;
12265  for (ScopeIterator it(isolate, frame, 0);
12266  !it.Done();
12267  it.Next()) {
12268  n++;
12269  }
12270 
12271  return Smi::FromInt(n);
12272 }
12273 
12274 
12275 // Returns the list of step-in positions (text offset) in a function of the
12276 // stack frame in a range from the current debug break position to the end
12277 // of the corresponding statement.
12278 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetStepInPositions) {
12279  HandleScope scope(isolate);
12280  ASSERT(args.length() == 2);
12281 
12282  // Check arguments.
12283  Object* check;
12284  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12285  RUNTIME_ARGUMENTS(isolate, args));
12286  if (!maybe_check->ToObject(&check)) return maybe_check;
12287  }
12288  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12289 
12290  // Get the frame where the debugging is performed.
12291  StackFrame::Id id = UnwrapFrameId(wrapped_id);
12292  JavaScriptFrameIterator frame_it(isolate, id);
12293  RUNTIME_ASSERT(!frame_it.done());
12294 
12295  JavaScriptFrame* frame = frame_it.frame();
12296 
12297  Handle<JSFunction> fun =
12298  Handle<JSFunction>(frame->function());
12299  Handle<SharedFunctionInfo> shared =
12300  Handle<SharedFunctionInfo>(fun->shared());
12301 
12302  if (!isolate->debug()->EnsureDebugInfo(shared, fun)) {
12303  return isolate->heap()->undefined_value();
12304  }
12305 
12306  Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared);
12307 
12308  int len = 0;
12309  Handle<JSArray> array(isolate->factory()->NewJSArray(10));
12310  // Find the break point where execution has stopped.
12311  BreakLocationIterator break_location_iterator(debug_info,
12312  ALL_BREAK_LOCATIONS);
12313 
12314  break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
12315  int current_statement_pos = break_location_iterator.statement_position();
12316 
12317  while (!break_location_iterator.Done()) {
12318  bool accept;
12319  if (break_location_iterator.pc() > frame->pc()) {
12320  accept = true;
12321  } else {
12322  StackFrame::Id break_frame_id = isolate->debug()->break_frame_id();
12323  // The break point is near our pc. Could be a step-in possibility,
12324  // that is currently taken by active debugger call.
12325  if (break_frame_id == StackFrame::NO_ID) {
12326  // We are not stepping.
12327  accept = false;
12328  } else {
12329  JavaScriptFrameIterator additional_frame_it(isolate, break_frame_id);
12330  // If our frame is a top frame and we are stepping, we can do step-in
12331  // at this place.
12332  accept = additional_frame_it.frame()->id() == id;
12333  }
12334  }
12335  if (accept) {
12336  if (break_location_iterator.IsStepInLocation(isolate)) {
12337  Smi* position_value = Smi::FromInt(break_location_iterator.position());
12338  JSObject::SetElement(array, len,
12339  Handle<Object>(position_value, isolate),
12340  NONE, SLOPPY);
12341  len++;
12342  }
12343  }
12344  // Advance iterator.
12345  break_location_iterator.Next();
12346  if (current_statement_pos !=
12347  break_location_iterator.statement_position()) {
12348  break;
12349  }
12350  }
12351  return *array;
12352 }
12353 
12354 
12355 static const int kScopeDetailsTypeIndex = 0;
12356 static const int kScopeDetailsObjectIndex = 1;
12357 static const int kScopeDetailsSize = 2;
12358 
12359 
12360 static Handle<JSObject> MaterializeScopeDetails(Isolate* isolate,
12361  ScopeIterator* it) {
12362  // Calculate the size of the result.
12363  int details_size = kScopeDetailsSize;
12364  Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
12365 
12366  // Fill in scope details.
12367  details->set(kScopeDetailsTypeIndex, Smi::FromInt(it->Type()));
12368  Handle<JSObject> scope_object = it->ScopeObject();
12369  RETURN_IF_EMPTY_HANDLE_VALUE(isolate, scope_object, Handle<JSObject>());
12370  details->set(kScopeDetailsObjectIndex, *scope_object);
12371 
12372  return isolate->factory()->NewJSArrayWithElements(details);
12373 }
12374 
12375 
12376 // Return an array with scope details
12377 // args[0]: number: break id
12378 // args[1]: number: frame index
12379 // args[2]: number: inlined frame index
12380 // args[3]: number: scope index
12381 //
12382 // The array returned contains the following information:
12383 // 0: Scope type
12384 // 1: Scope object
12385 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
12386  HandleScope scope(isolate);
12387  ASSERT(args.length() == 4);
12388 
12389  // Check arguments.
12390  Object* check;
12391  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12392  RUNTIME_ARGUMENTS(isolate, args));
12393  if (!maybe_check->ToObject(&check)) return maybe_check;
12394  }
12395  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12396  CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12397  CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
12398 
12399  // Get the frame where the debugging is performed.
12400  StackFrame::Id id = UnwrapFrameId(wrapped_id);
12401  JavaScriptFrameIterator frame_it(isolate, id);
12402  JavaScriptFrame* frame = frame_it.frame();
12403 
12404  // Find the requested scope.
12405  int n = 0;
12406  ScopeIterator it(isolate, frame, inlined_jsframe_index);
12407  for (; !it.Done() && n < index; it.Next()) {
12408  n++;
12409  }
12410  if (it.Done()) {
12411  return isolate->heap()->undefined_value();
12412  }
12413  Handle<JSObject> details = MaterializeScopeDetails(isolate, &it);
12414  RETURN_IF_EMPTY_HANDLE(isolate, details);
12415  return *details;
12416 }
12417 
12418 
12419 // Return an array of scope details
12420 // args[0]: number: break id
12421 // args[1]: number: frame index
12422 // args[2]: number: inlined frame index
12423 // args[3]: boolean: ignore nested scopes
12424 //
12425 // The array returned contains arrays with the following information:
12426 // 0: Scope type
12427 // 1: Scope object
12428 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetAllScopesDetails) {
12429  HandleScope scope(isolate);
12430  ASSERT(args.length() == 3 || args.length() == 4);
12431 
12432  // Check arguments.
12433  Object* check;
12434  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12435  RUNTIME_ARGUMENTS(isolate, args));
12436  if (!maybe_check->ToObject(&check)) return maybe_check;
12437  }
12438  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12439  CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12440 
12441  bool ignore_nested_scopes = false;
12442  if (args.length() == 4) {
12443  CONVERT_BOOLEAN_ARG_CHECKED(flag, 3);
12444  ignore_nested_scopes = flag;
12445  }
12446 
12447  // Get the frame where the debugging is performed.
12448  StackFrame::Id id = UnwrapFrameId(wrapped_id);
12449  JavaScriptFrameIterator frame_it(isolate, id);
12450  JavaScriptFrame* frame = frame_it.frame();
12451 
12452  List<Handle<JSObject> > result(4);
12453  ScopeIterator it(isolate, frame, inlined_jsframe_index, ignore_nested_scopes);
12454  for (; !it.Done(); it.Next()) {
12455  Handle<JSObject> details = MaterializeScopeDetails(isolate, &it);
12456  RETURN_IF_EMPTY_HANDLE(isolate, details);
12457  result.Add(details);
12458  }
12459 
12460  Handle<FixedArray> array = isolate->factory()->NewFixedArray(result.length());
12461  for (int i = 0; i < result.length(); ++i) {
12462  array->set(i, *result[i]);
12463  }
12464  return *isolate->factory()->NewJSArrayWithElements(array);
12465 }
12466 
12467 
12468 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeCount) {
12469  HandleScope scope(isolate);
12470  ASSERT(args.length() == 1);
12471 
12472  // Check arguments.
12473  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12474 
12475  // Count the visible scopes.
12476  int n = 0;
12477  for (ScopeIterator it(isolate, fun); !it.Done(); it.Next()) {
12478  n++;
12479  }
12480 
12481  return Smi::FromInt(n);
12482 }
12483 
12484 
12485 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeDetails) {
12486  HandleScope scope(isolate);
12487  ASSERT(args.length() == 2);
12488 
12489  // Check arguments.
12490  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12491  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
12492 
12493  // Find the requested scope.
12494  int n = 0;
12495  ScopeIterator it(isolate, fun);
12496  for (; !it.Done() && n < index; it.Next()) {
12497  n++;
12498  }
12499  if (it.Done()) {
12500  return isolate->heap()->undefined_value();
12501  }
12502 
12503  Handle<JSObject> details = MaterializeScopeDetails(isolate, &it);
12504  RETURN_IF_EMPTY_HANDLE(isolate, details);
12505  return *details;
12506 }
12507 
12508 
12509 static bool SetScopeVariableValue(ScopeIterator* it, int index,
12510  Handle<String> variable_name,
12511  Handle<Object> new_value) {
12512  for (int n = 0; !it->Done() && n < index; it->Next()) {
12513  n++;
12514  }
12515  if (it->Done()) {
12516  return false;
12517  }
12518  return it->SetVariableValue(variable_name, new_value);
12519 }
12520 
12521 
12522 // Change variable value in closure or local scope
12523 // args[0]: number or JsFunction: break id or function
12524 // args[1]: number: frame index (when arg[0] is break id)
12525 // args[2]: number: inlined frame index (when arg[0] is break id)
12526 // args[3]: number: scope index
12527 // args[4]: string: variable name
12528 // args[5]: object: new value
12529 //
12530 // Return true if success and false otherwise
12531 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScopeVariableValue) {
12532  HandleScope scope(isolate);
12533  ASSERT(args.length() == 6);
12534 
12535  // Check arguments.
12536  CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
12537  CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4);
12538  Handle<Object> new_value = args.at<Object>(5);
12539 
12540  bool res;
12541  if (args[0]->IsNumber()) {
12542  Object* check;
12543  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12544  RUNTIME_ARGUMENTS(isolate, args));
12545  if (!maybe_check->ToObject(&check)) return maybe_check;
12546  }
12547  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12548  CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12549 
12550  // Get the frame where the debugging is performed.
12551  StackFrame::Id id = UnwrapFrameId(wrapped_id);
12552  JavaScriptFrameIterator frame_it(isolate, id);
12553  JavaScriptFrame* frame = frame_it.frame();
12554 
12555  ScopeIterator it(isolate, frame, inlined_jsframe_index);
12556  res = SetScopeVariableValue(&it, index, variable_name, new_value);
12557  } else {
12558  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12559  ScopeIterator it(isolate, fun);
12560  res = SetScopeVariableValue(&it, index, variable_name, new_value);
12561  }
12562 
12563  return isolate->heap()->ToBoolean(res);
12564 }
12565 
12566 
12567 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) {
12568  HandleScope scope(isolate);
12569  ASSERT(args.length() == 0);
12570 
12571 #ifdef DEBUG
12572  // Print the scopes for the top frame.
12573  StackFrameLocator locator(isolate);
12574  JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
12575  for (ScopeIterator it(isolate, frame, 0);
12576  !it.Done();
12577  it.Next()) {
12578  it.DebugPrint();
12579  }
12580 #endif
12581  return isolate->heap()->undefined_value();
12582 }
12583 
12584 
12585 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadCount) {
12586  HandleScope scope(isolate);
12587  ASSERT(args.length() == 1);
12588 
12589  // Check arguments.
12590  Object* result;
12591  { MaybeObject* maybe_result = Runtime_CheckExecutionState(
12592  RUNTIME_ARGUMENTS(isolate, args));
12593  if (!maybe_result->ToObject(&result)) return maybe_result;
12594  }
12595 
12596  // Count all archived V8 threads.
12597  int n = 0;
12598  for (ThreadState* thread =
12599  isolate->thread_manager()->FirstThreadStateInUse();
12600  thread != NULL;
12601  thread = thread->Next()) {
12602  n++;
12603  }
12604 
12605  // Total number of threads is current thread and archived threads.
12606  return Smi::FromInt(n + 1);
12607 }
12608 
12609 
12610 static const int kThreadDetailsCurrentThreadIndex = 0;
12611 static const int kThreadDetailsThreadIdIndex = 1;
12612 static const int kThreadDetailsSize = 2;
12613 
12614 // Return an array with thread details
12615 // args[0]: number: break id
12616 // args[1]: number: thread index
12617 //
12618 // The array returned contains the following information:
12619 // 0: Is current thread?
12620 // 1: Thread id
12621 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadDetails) {
12622  HandleScope scope(isolate);
12623  ASSERT(args.length() == 2);
12624 
12625  // Check arguments.
12626  Object* check;
12627  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12628  RUNTIME_ARGUMENTS(isolate, args));
12629  if (!maybe_check->ToObject(&check)) return maybe_check;
12630  }
12631  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
12632 
12633  // Allocate array for result.
12634  Handle<FixedArray> details =
12635  isolate->factory()->NewFixedArray(kThreadDetailsSize);
12636 
12637  // Thread index 0 is current thread.
12638  if (index == 0) {
12639  // Fill the details.
12640  details->set(kThreadDetailsCurrentThreadIndex,
12641  isolate->heap()->true_value());
12642  details->set(kThreadDetailsThreadIdIndex,
12643  Smi::FromInt(ThreadId::Current().ToInteger()));
12644  } else {
12645  // Find the thread with the requested index.
12646  int n = 1;
12647  ThreadState* thread =
12648  isolate->thread_manager()->FirstThreadStateInUse();
12649  while (index != n && thread != NULL) {
12650  thread = thread->Next();
12651  n++;
12652  }
12653  if (thread == NULL) {
12654  return isolate->heap()->undefined_value();
12655  }
12656 
12657  // Fill the details.
12658  details->set(kThreadDetailsCurrentThreadIndex,
12659  isolate->heap()->false_value());
12660  details->set(kThreadDetailsThreadIdIndex,
12661  Smi::FromInt(thread->id().ToInteger()));
12662  }
12663 
12664  // Convert to JS array and return.
12665  return *isolate->factory()->NewJSArrayWithElements(details);
12666 }
12667 
12668 
12669 // Sets the disable break state
12670 // args[0]: disable break state
12671 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDisableBreak) {
12672  HandleScope scope(isolate);
12673  ASSERT(args.length() == 1);
12674  CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 0);
12675  isolate->debug()->set_disable_break(disable_break);
12676  return isolate->heap()->undefined_value();
12677 }
12678 
12679 
12680 static bool IsPositionAlignmentCodeCorrect(int alignment) {
12681  return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED;
12682 }
12683 
12684 
12685 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetBreakLocations) {
12686  HandleScope scope(isolate);
12687  ASSERT(args.length() == 2);
12688 
12689  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12690  CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[1]);
12691 
12692  if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
12693  return isolate->ThrowIllegalOperation();
12694  }
12695  BreakPositionAlignment alignment =
12696  static_cast<BreakPositionAlignment>(statement_aligned_code);
12697 
12698  Handle<SharedFunctionInfo> shared(fun->shared());
12699  // Find the number of break points
12700  Handle<Object> break_locations =
12701  Debug::GetSourceBreakLocations(shared, alignment);
12702  if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
12703  // Return array as JS array
12704  return *isolate->factory()->NewJSArrayWithElements(
12705  Handle<FixedArray>::cast(break_locations));
12706 }
12707 
12708 
12709 // Set a break point in a function.
12710 // args[0]: function
12711 // args[1]: number: break source position (within the function source)
12712 // args[2]: number: break point object
12713 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFunctionBreakPoint) {
12714  HandleScope scope(isolate);
12715  ASSERT(args.length() == 3);
12716  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
12717  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
12718  RUNTIME_ASSERT(source_position >= 0);
12719  Handle<Object> break_point_object_arg = args.at<Object>(2);
12720 
12721  // Set break point.
12722  isolate->debug()->SetBreakPoint(function, break_point_object_arg,
12723  &source_position);
12724 
12725  return Smi::FromInt(source_position);
12726 }
12727 
12728 
12729 // Changes the state of a break point in a script and returns source position
12730 // where break point was set. NOTE: Regarding performance see the NOTE for
12731 // GetScriptFromScriptData.
12732 // args[0]: script to set break point in
12733 // args[1]: number: break source position (within the script source)
12734 // args[2]: number, breakpoint position alignment
12735 // args[3]: number: break point object
12736 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScriptBreakPoint) {
12737  HandleScope scope(isolate);
12738  ASSERT(args.length() == 4);
12739  CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
12740  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
12741  RUNTIME_ASSERT(source_position >= 0);
12742  CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]);
12743  Handle<Object> break_point_object_arg = args.at<Object>(3);
12744 
12745  if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
12746  return isolate->ThrowIllegalOperation();
12747  }
12748  BreakPositionAlignment alignment =
12749  static_cast<BreakPositionAlignment>(statement_aligned_code);
12750 
12751  // Get the script from the script wrapper.
12752  RUNTIME_ASSERT(wrapper->value()->IsScript());
12753  Handle<Script> script(Script::cast(wrapper->value()));
12754 
12755  // Set break point.
12756  if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
12757  &source_position,
12758  alignment)) {
12759  return isolate->heap()->undefined_value();
12760  }
12761 
12762  return Smi::FromInt(source_position);
12763 }
12764 
12765 
12766 // Clear a break point
12767 // args[0]: number: break point object
12768 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearBreakPoint) {
12769  HandleScope scope(isolate);
12770  ASSERT(args.length() == 1);
12771  Handle<Object> break_point_object_arg = args.at<Object>(0);
12772 
12773  // Clear break point.
12774  isolate->debug()->ClearBreakPoint(break_point_object_arg);
12775 
12776  return isolate->heap()->undefined_value();
12777 }
12778 
12779 
12780 // Change the state of break on exceptions.
12781 // args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
12782 // args[1]: Boolean indicating on/off.
12783 RUNTIME_FUNCTION(MaybeObject*, Runtime_ChangeBreakOnException) {
12784  HandleScope scope(isolate);
12785  ASSERT(args.length() == 2);
12786  RUNTIME_ASSERT(args[0]->IsNumber());
12787  CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
12788 
12789  // If the number doesn't match an enum value, the ChangeBreakOnException
12790  // function will default to affecting caught exceptions.
12791  ExceptionBreakType type =
12792  static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
12793  // Update break point state.
12794  isolate->debug()->ChangeBreakOnException(type, enable);
12795  return isolate->heap()->undefined_value();
12796 }
12797 
12798 
12799 // Returns the state of break on exceptions
12800 // args[0]: boolean indicating uncaught exceptions
12801 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsBreakOnException) {
12802  HandleScope scope(isolate);
12803  ASSERT(args.length() == 1);
12804  RUNTIME_ASSERT(args[0]->IsNumber());
12805 
12806  ExceptionBreakType type =
12807  static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
12808  bool result = isolate->debug()->IsBreakOnException(type);
12809  return Smi::FromInt(result);
12810 }
12811 
12812 
12813 // Prepare for stepping
12814 // args[0]: break id for checking execution state
12815 // args[1]: step action from the enumeration StepAction
12816 // args[2]: number of times to perform the step, for step out it is the number
12817 // of frames to step down.
12818 RUNTIME_FUNCTION(MaybeObject*, Runtime_PrepareStep) {
12819  HandleScope scope(isolate);
12820  ASSERT(args.length() == 4);
12821  // Check arguments.
12822  Object* check;
12823  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12824  RUNTIME_ARGUMENTS(isolate, args));
12825  if (!maybe_check->ToObject(&check)) return maybe_check;
12826  }
12827  if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
12828  return isolate->Throw(isolate->heap()->illegal_argument_string());
12829  }
12830 
12831  CONVERT_NUMBER_CHECKED(int, wrapped_frame_id, Int32, args[3]);
12832 
12833  StackFrame::Id frame_id;
12834  if (wrapped_frame_id == 0) {
12835  frame_id = StackFrame::NO_ID;
12836  } else {
12837  frame_id = UnwrapFrameId(wrapped_frame_id);
12838  }
12839 
12840  // Get the step action and check validity.
12841  StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
12842  if (step_action != StepIn &&
12843  step_action != StepNext &&
12844  step_action != StepOut &&
12845  step_action != StepInMin &&
12846  step_action != StepMin) {
12847  return isolate->Throw(isolate->heap()->illegal_argument_string());
12848  }
12849 
12850  if (frame_id != StackFrame::NO_ID && step_action != StepNext &&
12851  step_action != StepMin && step_action != StepOut) {
12852  return isolate->ThrowIllegalOperation();
12853  }
12854 
12855  // Get the number of steps.
12856  int step_count = NumberToInt32(args[2]);
12857  if (step_count < 1) {
12858  return isolate->Throw(isolate->heap()->illegal_argument_string());
12859  }
12860 
12861  // Clear all current stepping setup.
12862  isolate->debug()->ClearStepping();
12863 
12864  // Prepare step.
12865  isolate->debug()->PrepareStep(static_cast<StepAction>(step_action),
12866  step_count,
12867  frame_id);
12868  return isolate->heap()->undefined_value();
12869 }
12870 
12871 
12872 // Clear all stepping set by PrepareStep.
12873 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) {
12874  HandleScope scope(isolate);
12875  ASSERT(args.length() == 0);
12876  isolate->debug()->ClearStepping();
12877  return isolate->heap()->undefined_value();
12878 }
12879 
12880 
12881 // Helper function to find or create the arguments object for
12882 // Runtime_DebugEvaluate.
12883 static Handle<JSObject> MaterializeArgumentsObject(
12884  Isolate* isolate,
12885  Handle<JSObject> target,
12886  Handle<JSFunction> function) {
12887  // Do not materialize the arguments object for eval or top-level code.
12888  // Skip if "arguments" is already taken.
12889  if (!function->shared()->is_function() ||
12891  isolate->factory()->arguments_string())) {
12892  return target;
12893  }
12894 
12895  // FunctionGetArguments can't throw an exception.
12896  Handle<JSObject> arguments = Handle<JSObject>::cast(
12898  Runtime::SetObjectProperty(isolate, target,
12899  isolate->factory()->arguments_string(),
12900  arguments,
12901  ::NONE,
12902  SLOPPY);
12903  return target;
12904 }
12905 
12906 
12907 // Compile and evaluate source for the given context.
12908 static MaybeObject* DebugEvaluate(Isolate* isolate,
12909  Handle<Context> context,
12910  Handle<Object> context_extension,
12911  Handle<Object> receiver,
12912  Handle<String> source) {
12913  if (context_extension->IsJSObject()) {
12914  Handle<JSObject> extension = Handle<JSObject>::cast(context_extension);
12915  Handle<JSFunction> closure(context->closure(), isolate);
12916  context = isolate->factory()->NewWithContext(closure, context, extension);
12917  }
12918 
12919  Handle<JSFunction> eval_fun =
12921  context,
12922  SLOPPY,
12924  RelocInfo::kNoPosition);
12925  RETURN_IF_EMPTY_HANDLE(isolate, eval_fun);
12926 
12927  bool pending_exception;
12928  Handle<Object> result = Execution::Call(
12929  isolate, eval_fun, receiver, 0, NULL, &pending_exception);
12930 
12931  if (pending_exception) return Failure::Exception();
12932 
12933  // Skip the global proxy as it has no properties and always delegates to the
12934  // real global object.
12935  if (result->IsJSGlobalProxy()) {
12936  result = Handle<JSObject>(JSObject::cast(result->GetPrototype(isolate)));
12937  }
12938 
12939  // Clear the oneshot breakpoints so that the debugger does not step further.
12940  isolate->debug()->ClearStepping();
12941  return *result;
12942 }
12943 
12944 
12945 // Evaluate a piece of JavaScript in the context of a stack frame for
12946 // debugging. Things that need special attention are:
12947 // - Parameters and stack-allocated locals need to be materialized. Altered
12948 // values need to be written back to the stack afterwards.
12949 // - The arguments object needs to materialized.
12950 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
12951  HandleScope scope(isolate);
12952 
12953  // Check the execution state and decode arguments frame and source to be
12954  // evaluated.
12955  ASSERT(args.length() == 6);
12956  Object* check_result;
12957  { MaybeObject* maybe_result = Runtime_CheckExecutionState(
12958  RUNTIME_ARGUMENTS(isolate, args));
12959  if (!maybe_result->ToObject(&check_result)) return maybe_result;
12960  }
12961  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12962  CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12963  CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
12964  CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
12965  Handle<Object> context_extension(args[5], isolate);
12966 
12967  // Handle the processing of break.
12968  DisableBreak disable_break_save(isolate, disable_break);
12969 
12970  // Get the frame where the debugging is performed.
12971  StackFrame::Id id = UnwrapFrameId(wrapped_id);
12972  JavaScriptFrameIterator it(isolate, id);
12973  JavaScriptFrame* frame = it.frame();
12974  FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
12975  Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
12976 
12977  // Traverse the saved contexts chain to find the active context for the
12978  // selected frame.
12979  SaveContext* save = FindSavedContextForFrame(isolate, frame);
12980 
12981  SaveContext savex(isolate);
12982  isolate->set_context(*(save->context()));
12983 
12984  // Evaluate on the context of the frame.
12985  Handle<Context> context(Context::cast(frame->context()));
12986  ASSERT(!context.is_null());
12987 
12988  // Materialize stack locals and the arguments object.
12989  Handle<JSObject> materialized =
12990  isolate->factory()->NewJSObject(isolate->object_function());
12991 
12992  materialized = MaterializeStackLocalsWithFrameInspector(
12993  isolate, materialized, function, &frame_inspector);
12994  RETURN_IF_EMPTY_HANDLE(isolate, materialized);
12995 
12996  materialized = MaterializeArgumentsObject(isolate, materialized, function);
12997  RETURN_IF_EMPTY_HANDLE(isolate, materialized);
12998 
12999  // Add the materialized object in a with-scope to shadow the stack locals.
13000  context = isolate->factory()->NewWithContext(function, context, materialized);
13001 
13002  Handle<Object> receiver(frame->receiver(), isolate);
13003  Object* evaluate_result_object;
13004  { MaybeObject* maybe_result =
13005  DebugEvaluate(isolate, context, context_extension, receiver, source);
13006  if (!maybe_result->ToObject(&evaluate_result_object)) return maybe_result;
13007  }
13008 
13009  Handle<Object> result(evaluate_result_object, isolate);
13010 
13011  // Write back potential changes to materialized stack locals to the stack.
13012  UpdateStackLocalsFromMaterializedObject(
13013  isolate, materialized, function, frame, inlined_jsframe_index);
13014 
13015  return *result;
13016 }
13017 
13018 
13019 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) {
13020  HandleScope scope(isolate);
13021 
13022  // Check the execution state and decode arguments frame and source to be
13023  // evaluated.
13024  ASSERT(args.length() == 4);
13025  Object* check_result;
13026  { MaybeObject* maybe_result = Runtime_CheckExecutionState(
13027  RUNTIME_ARGUMENTS(isolate, args));
13028  if (!maybe_result->ToObject(&check_result)) return maybe_result;
13029  }
13030  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
13031  CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
13032  Handle<Object> context_extension(args[3], isolate);
13033 
13034  // Handle the processing of break.
13035  DisableBreak disable_break_save(isolate, disable_break);
13036 
13037  // Enter the top context from before the debugger was invoked.
13038  SaveContext save(isolate);
13039  SaveContext* top = &save;
13040  while (top != NULL && *top->context() == *isolate->debug()->debug_context()) {
13041  top = top->prev();
13042  }
13043  if (top != NULL) {
13044  isolate->set_context(*top->context());
13045  }
13046 
13047  // Get the native context now set to the top context from before the
13048  // debugger was invoked.
13049  Handle<Context> context = isolate->native_context();
13050  Handle<Object> receiver = isolate->global_object();
13051  return DebugEvaluate(isolate, context, context_extension, receiver, source);
13052 }
13053 
13054 
13055 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetLoadedScripts) {
13056  HandleScope scope(isolate);
13057  ASSERT(args.length() == 0);
13058 
13059  // Fill the script objects.
13060  Handle<FixedArray> instances = isolate->debug()->GetLoadedScripts();
13061 
13062  // Convert the script objects to proper JS objects.
13063  for (int i = 0; i < instances->length(); i++) {
13064  Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
13065  // Get the script wrapper in a local handle before calling GetScriptWrapper,
13066  // because using
13067  // instances->set(i, *GetScriptWrapper(script))
13068  // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
13069  // already have dereferenced the instances handle.
13070  Handle<JSValue> wrapper = GetScriptWrapper(script);
13071  instances->set(i, *wrapper);
13072  }
13073 
13074  // Return result as a JS array.
13075  Handle<JSObject> result =
13076  isolate->factory()->NewJSObject(isolate->array_function());
13077  JSArray::SetContent(Handle<JSArray>::cast(result), instances);
13078  return *result;
13079 }
13080 
13081 
13082 // Helper function used by Runtime_DebugReferencedBy below.
13083 static int DebugReferencedBy(HeapIterator* iterator,
13084  JSObject* target,
13085  Object* instance_filter, int max_references,
13086  FixedArray* instances, int instances_size,
13087  JSFunction* arguments_function) {
13088  Isolate* isolate = target->GetIsolate();
13089  SealHandleScope shs(isolate);
13090  DisallowHeapAllocation no_allocation;
13091 
13092  // Iterate the heap.
13093  int count = 0;
13094  JSObject* last = NULL;
13095  HeapObject* heap_obj = NULL;
13096  while (((heap_obj = iterator->next()) != NULL) &&
13097  (max_references == 0 || count < max_references)) {
13098  // Only look at all JSObjects.
13099  if (heap_obj->IsJSObject()) {
13100  // Skip context extension objects and argument arrays as these are
13101  // checked in the context of functions using them.
13102  JSObject* obj = JSObject::cast(heap_obj);
13103  if (obj->IsJSContextExtensionObject() ||
13104  obj->map()->constructor() == arguments_function) {
13105  continue;
13106  }
13107 
13108  // Check if the JS object has a reference to the object looked for.
13109  if (obj->ReferencesObject(target)) {
13110  // Check instance filter if supplied. This is normally used to avoid
13111  // references from mirror objects (see Runtime_IsInPrototypeChain).
13112  if (!instance_filter->IsUndefined()) {
13113  Object* V = obj;
13114  while (true) {
13115  Object* prototype = V->GetPrototype(isolate);
13116  if (prototype->IsNull()) {
13117  break;
13118  }
13119  if (instance_filter == prototype) {
13120  obj = NULL; // Don't add this object.
13121  break;
13122  }
13123  V = prototype;
13124  }
13125  }
13126 
13127  if (obj != NULL) {
13128  // Valid reference found add to instance array if supplied an update
13129  // count.
13130  if (instances != NULL && count < instances_size) {
13131  instances->set(count, obj);
13132  }
13133  last = obj;
13134  count++;
13135  }
13136  }
13137  }
13138  }
13139 
13140  // Check for circular reference only. This can happen when the object is only
13141  // referenced from mirrors and has a circular reference in which case the
13142  // object is not really alive and would have been garbage collected if not
13143  // referenced from the mirror.
13144  if (count == 1 && last == target) {
13145  count = 0;
13146  }
13147 
13148  // Return the number of referencing objects found.
13149  return count;
13150 }
13151 
13152 
13153 // Scan the heap for objects with direct references to an object
13154 // args[0]: the object to find references to
13155 // args[1]: constructor function for instances to exclude (Mirror)
13156 // args[2]: the the maximum number of objects to return
13157 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugReferencedBy) {
13158  HandleScope scope(isolate);
13159  ASSERT(args.length() == 3);
13160 
13161  // First perform a full GC in order to avoid references from dead objects.
13162  Heap* heap = isolate->heap();
13163  heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugReferencedBy");
13164  // The heap iterator reserves the right to do a GC to make the heap iterable.
13165  // Due to the GC above we know it won't need to do that, but it seems cleaner
13166  // to get the heap iterator constructed before we start having unprotected
13167  // Object* locals that are not protected by handles.
13168 
13169  // Check parameters.
13170  CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
13171  Handle<Object> instance_filter = args.at<Object>(1);
13172  RUNTIME_ASSERT(instance_filter->IsUndefined() ||
13173  instance_filter->IsJSObject());
13174  CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
13175  RUNTIME_ASSERT(max_references >= 0);
13176 
13177 
13178  // Get the constructor function for context extension and arguments array.
13179  Handle<JSObject> arguments_boilerplate(
13180  isolate->context()->native_context()->sloppy_arguments_boilerplate());
13181  Handle<JSFunction> arguments_function(
13182  JSFunction::cast(arguments_boilerplate->map()->constructor()));
13183 
13184  // Get the number of referencing objects.
13185  int count;
13186  HeapIterator heap_iterator(heap);
13187  count = DebugReferencedBy(&heap_iterator,
13188  *target, *instance_filter, max_references,
13189  NULL, 0, *arguments_function);
13190 
13191  // Allocate an array to hold the result.
13192  Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count);
13193 
13194  // Fill the referencing objects.
13195  // AllocateFixedArray above does not make the heap non-iterable.
13196  ASSERT(heap->IsHeapIterable());
13197  HeapIterator heap_iterator2(heap);
13198  count = DebugReferencedBy(&heap_iterator2,
13199  *target, *instance_filter, max_references,
13200  *instances, count, *arguments_function);
13201 
13202  // Return result as JS array.
13203  Handle<JSFunction> constructor(
13204  isolate->context()->native_context()->array_function());
13205 
13206  Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
13207  JSArray::SetContent(Handle<JSArray>::cast(result), instances);
13208  return *result;
13209 }
13210 
13211 
13212 // Helper function used by Runtime_DebugConstructedBy below.
13213 static int DebugConstructedBy(HeapIterator* iterator,
13214  JSFunction* constructor,
13215  int max_references,
13216  FixedArray* instances,
13217  int instances_size) {
13218  DisallowHeapAllocation no_allocation;
13219 
13220  // Iterate the heap.
13221  int count = 0;
13222  HeapObject* heap_obj = NULL;
13223  while (((heap_obj = iterator->next()) != NULL) &&
13224  (max_references == 0 || count < max_references)) {
13225  // Only look at all JSObjects.
13226  if (heap_obj->IsJSObject()) {
13227  JSObject* obj = JSObject::cast(heap_obj);
13228  if (obj->map()->constructor() == constructor) {
13229  // Valid reference found add to instance array if supplied an update
13230  // count.
13231  if (instances != NULL && count < instances_size) {
13232  instances->set(count, obj);
13233  }
13234  count++;
13235  }
13236  }
13237  }
13238 
13239  // Return the number of referencing objects found.
13240  return count;
13241 }
13242 
13243 
13244 // Scan the heap for objects constructed by a specific function.
13245 // args[0]: the constructor to find instances of
13246 // args[1]: the the maximum number of objects to return
13247 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugConstructedBy) {
13248  HandleScope scope(isolate);
13249  ASSERT(args.length() == 2);
13250 
13251  // First perform a full GC in order to avoid dead objects.
13252  Heap* heap = isolate->heap();
13253  heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
13254 
13255  // Check parameters.
13256  CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
13257  CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
13258  RUNTIME_ASSERT(max_references >= 0);
13259 
13260  // Get the number of referencing objects.
13261  int count;
13262  HeapIterator heap_iterator(heap);
13263  count = DebugConstructedBy(&heap_iterator,
13264  *constructor,
13265  max_references,
13266  NULL,
13267  0);
13268 
13269  // Allocate an array to hold the result.
13270  Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count);
13271 
13272  ASSERT(heap->IsHeapIterable());
13273  // Fill the referencing objects.
13274  HeapIterator heap_iterator2(heap);
13275  count = DebugConstructedBy(&heap_iterator2,
13276  *constructor,
13277  max_references,
13278  *instances,
13279  count);
13280 
13281  // Return result as JS array.
13282  Handle<JSFunction> array_function(
13283  isolate->context()->native_context()->array_function());
13284  Handle<JSObject> result = isolate->factory()->NewJSObject(array_function);
13285  JSArray::SetContent(Handle<JSArray>::cast(result), instances);
13286  return *result;
13287 }
13288 
13289 
13290 // Find the effective prototype object as returned by __proto__.
13291 // args[0]: the object to find the prototype for.
13292 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPrototype) {
13293  SealHandleScope shs(isolate);
13294  ASSERT(args.length() == 1);
13295  CONVERT_ARG_CHECKED(JSObject, obj, 0);
13296  return GetPrototypeSkipHiddenPrototypes(isolate, obj);
13297 }
13298 
13299 
13300 // Patches script source (should be called upon BeforeCompile event).
13301 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugSetScriptSource) {
13302  HandleScope scope(isolate);
13303  ASSERT(args.length() == 2);
13304 
13305  CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
13306  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
13307 
13308  RUNTIME_ASSERT(script_wrapper->value()->IsScript());
13309  Handle<Script> script(Script::cast(script_wrapper->value()));
13310 
13311  int compilation_state = script->compilation_state();
13312  RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL);
13313  script->set_source(*source);
13314 
13315  return isolate->heap()->undefined_value();
13316 }
13317 
13318 
13319 RUNTIME_FUNCTION(MaybeObject*, Runtime_SystemBreak) {
13320  SealHandleScope shs(isolate);
13321  ASSERT(args.length() == 0);
13322  OS::DebugBreak();
13323  return isolate->heap()->undefined_value();
13324 }
13325 
13326 
13327 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleFunction) {
13328  HandleScope scope(isolate);
13329 #ifdef DEBUG
13330  ASSERT(args.length() == 1);
13331  // Get the function and make sure it is compiled.
13332  CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
13334  return Failure::Exception();
13335  }
13336  func->code()->PrintLn();
13337 #endif // DEBUG
13338  return isolate->heap()->undefined_value();
13339 }
13340 
13341 
13342 RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleConstructor) {
13343  HandleScope scope(isolate);
13344 #ifdef DEBUG
13345  ASSERT(args.length() == 1);
13346  // Get the function and make sure it is compiled.
13347  CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
13349  return Failure::Exception();
13350  }
13351  func->shared()->construct_stub()->PrintLn();
13352 #endif // DEBUG
13353  return isolate->heap()->undefined_value();
13354 }
13355 
13356 
13357 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetInferredName) {
13358  SealHandleScope shs(isolate);
13359  ASSERT(args.length() == 1);
13360 
13361  CONVERT_ARG_CHECKED(JSFunction, f, 0);
13362  return f->shared()->inferred_name();
13363 }
13364 
13365 
13366 static int FindSharedFunctionInfosForScript(HeapIterator* iterator,
13367  Script* script,
13368  FixedArray* buffer) {
13369  DisallowHeapAllocation no_allocation;
13370  int counter = 0;
13371  int buffer_size = buffer->length();
13372  for (HeapObject* obj = iterator->next();
13373  obj != NULL;
13374  obj = iterator->next()) {
13375  ASSERT(obj != NULL);
13376  if (!obj->IsSharedFunctionInfo()) {
13377  continue;
13378  }
13379  SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
13380  if (shared->script() != script) {
13381  continue;
13382  }
13383  if (counter < buffer_size) {
13384  buffer->set(counter, shared);
13385  }
13386  counter++;
13387  }
13388  return counter;
13389 }
13390 
13391 
13392 // For a script finds all SharedFunctionInfo's in the heap that points
13393 // to this script. Returns JSArray of SharedFunctionInfo wrapped
13394 // in OpaqueReferences.
13395 RUNTIME_FUNCTION(MaybeObject*,
13396  Runtime_LiveEditFindSharedFunctionInfosForScript) {
13397  HandleScope scope(isolate);
13398  CHECK(isolate->debugger()->live_edit_enabled());
13399  ASSERT(args.length() == 1);
13400  CONVERT_ARG_CHECKED(JSValue, script_value, 0);
13401 
13402  RUNTIME_ASSERT(script_value->value()->IsScript());
13403  Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
13404 
13405  const int kBufferSize = 32;
13406 
13407  Handle<FixedArray> array;
13408  array = isolate->factory()->NewFixedArray(kBufferSize);
13409  int number;
13410  Heap* heap = isolate->heap();
13411  {
13412  heap->EnsureHeapIsIterable();
13413  DisallowHeapAllocation no_allocation;
13414  HeapIterator heap_iterator(heap);
13415  Script* scr = *script;
13416  FixedArray* arr = *array;
13417  number = FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
13418  }
13419  if (number > kBufferSize) {
13420  array = isolate->factory()->NewFixedArray(number);
13421  heap->EnsureHeapIsIterable();
13422  DisallowHeapAllocation no_allocation;
13423  HeapIterator heap_iterator(heap);
13424  Script* scr = *script;
13425  FixedArray* arr = *array;
13426  FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
13427  }
13428 
13429  Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array);
13430  result->set_length(Smi::FromInt(number));
13431 
13432  LiveEdit::WrapSharedFunctionInfos(result);
13433 
13434  return *result;
13435 }
13436 
13437 
13438 // For a script calculates compilation information about all its functions.
13439 // The script source is explicitly specified by the second argument.
13440 // The source of the actual script is not used, however it is important that
13441 // all generated code keeps references to this particular instance of script.
13442 // Returns a JSArray of compilation infos. The array is ordered so that
13443 // each function with all its descendant is always stored in a continues range
13444 // with the function itself going first. The root function is a script function.
13445 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditGatherCompileInfo) {
13446  HandleScope scope(isolate);
13447  CHECK(isolate->debugger()->live_edit_enabled());
13448  ASSERT(args.length() == 2);
13449  CONVERT_ARG_CHECKED(JSValue, script, 0);
13450  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
13451 
13452  RUNTIME_ASSERT(script->value()->IsScript());
13453  Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
13454 
13455  JSArray* result = LiveEdit::GatherCompileInfo(script_handle, source);
13456 
13457  if (isolate->has_pending_exception()) {
13458  return Failure::Exception();
13459  }
13460 
13461  return result;
13462 }
13463 
13464 
13465 // Changes the source of the script to a new_source.
13466 // If old_script_name is provided (i.e. is a String), also creates a copy of
13467 // the script with its original source and sends notification to debugger.
13468 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceScript) {
13469  HandleScope scope(isolate);
13470  CHECK(isolate->debugger()->live_edit_enabled());
13471  ASSERT(args.length() == 3);
13472  CONVERT_ARG_CHECKED(JSValue, original_script_value, 0);
13473  CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
13474  Handle<Object> old_script_name(args[2], isolate);
13475 
13476  RUNTIME_ASSERT(original_script_value->value()->IsScript());
13477  Handle<Script> original_script(Script::cast(original_script_value->value()));
13478 
13479  Object* old_script = LiveEdit::ChangeScriptSource(original_script,
13480  new_source,
13481  old_script_name);
13482 
13483  if (old_script->IsScript()) {
13484  Handle<Script> script_handle(Script::cast(old_script));
13485  return *(GetScriptWrapper(script_handle));
13486  } else {
13487  return isolate->heap()->null_value();
13488  }
13489 }
13490 
13491 
13492 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSourceUpdated) {
13493  HandleScope scope(isolate);
13494  CHECK(isolate->debugger()->live_edit_enabled());
13495  ASSERT(args.length() == 1);
13496  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 0);
13497  return LiveEdit::FunctionSourceUpdated(shared_info);
13498 }
13499 
13500 
13501 // Replaces code of SharedFunctionInfo with a new one.
13502 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceFunctionCode) {
13503  HandleScope scope(isolate);
13504  CHECK(isolate->debugger()->live_edit_enabled());
13505  ASSERT(args.length() == 2);
13506  CONVERT_ARG_HANDLE_CHECKED(JSArray, new_compile_info, 0);
13507  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 1);
13508 
13509  return LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
13510 }
13511 
13512 
13513 // Connects SharedFunctionInfo to another script.
13514 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSetScript) {
13515  HandleScope scope(isolate);
13516  CHECK(isolate->debugger()->live_edit_enabled());
13517  ASSERT(args.length() == 2);
13518  Handle<Object> function_object(args[0], isolate);
13519  Handle<Object> script_object(args[1], isolate);
13520 
13521  if (function_object->IsJSValue()) {
13522  Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
13523  if (script_object->IsJSValue()) {
13524  RUNTIME_ASSERT(JSValue::cast(*script_object)->value()->IsScript());
13525  Script* script = Script::cast(JSValue::cast(*script_object)->value());
13526  script_object = Handle<Object>(script, isolate);
13527  }
13528 
13529  LiveEdit::SetFunctionScript(function_wrapper, script_object);
13530  } else {
13531  // Just ignore this. We may not have a SharedFunctionInfo for some functions
13532  // and we check it in this function.
13533  }
13534 
13535  return isolate->heap()->undefined_value();
13536 }
13537 
13538 
13539 // In a code of a parent function replaces original function as embedded object
13540 // with a substitution one.
13541 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceRefToNestedFunction) {
13542  HandleScope scope(isolate);
13543  CHECK(isolate->debugger()->live_edit_enabled());
13544  ASSERT(args.length() == 3);
13545 
13546  CONVERT_ARG_HANDLE_CHECKED(JSValue, parent_wrapper, 0);
13547  CONVERT_ARG_HANDLE_CHECKED(JSValue, orig_wrapper, 1);
13548  CONVERT_ARG_HANDLE_CHECKED(JSValue, subst_wrapper, 2);
13549 
13550  LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper,
13551  subst_wrapper);
13552 
13553  return isolate->heap()->undefined_value();
13554 }
13555 
13556 
13557 // Updates positions of a shared function info (first parameter) according
13558 // to script source change. Text change is described in second parameter as
13559 // array of groups of 3 numbers:
13560 // (change_begin, change_end, change_end_new_position).
13561 // Each group describes a change in text; groups are sorted by change_begin.
13562 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditPatchFunctionPositions) {
13563  HandleScope scope(isolate);
13564  CHECK(isolate->debugger()->live_edit_enabled());
13565  ASSERT(args.length() == 2);
13566  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
13567  CONVERT_ARG_HANDLE_CHECKED(JSArray, position_change_array, 1);
13568 
13569  return LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
13570 }
13571 
13572 
13573 // For array of SharedFunctionInfo's (each wrapped in JSValue)
13574 // checks that none of them have activations on stacks (of any thread).
13575 // Returns array of the same length with corresponding results of
13576 // LiveEdit::FunctionPatchabilityStatus type.
13577 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCheckAndDropActivations) {
13578  HandleScope scope(isolate);
13579  CHECK(isolate->debugger()->live_edit_enabled());
13580  ASSERT(args.length() == 2);
13581  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
13582  CONVERT_BOOLEAN_ARG_CHECKED(do_drop, 1);
13583 
13584  return *LiveEdit::CheckAndDropActivations(shared_array, do_drop);
13585 }
13586 
13587 
13588 // Compares 2 strings line-by-line, then token-wise and returns diff in form
13589 // of JSArray of triplets (pos1, pos1_end, pos2_end) describing list
13590 // of diff chunks.
13591 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCompareStrings) {
13592  HandleScope scope(isolate);
13593  CHECK(isolate->debugger()->live_edit_enabled());
13594  ASSERT(args.length() == 2);
13595  CONVERT_ARG_HANDLE_CHECKED(String, s1, 0);
13596  CONVERT_ARG_HANDLE_CHECKED(String, s2, 1);
13597 
13598  return *LiveEdit::CompareStrings(s1, s2);
13599 }
13600 
13601 
13602 // Restarts a call frame and completely drops all frames above.
13603 // Returns true if successful. Otherwise returns undefined or an error message.
13604 RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditRestartFrame) {
13605  HandleScope scope(isolate);
13606  CHECK(isolate->debugger()->live_edit_enabled());
13607  ASSERT(args.length() == 2);
13608 
13609  // Check arguments.
13610  Object* check;
13611  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
13612  RUNTIME_ARGUMENTS(isolate, args));
13613  if (!maybe_check->ToObject(&check)) return maybe_check;
13614  }
13615  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
13616  Heap* heap = isolate->heap();
13617 
13618  // Find the relevant frame with the requested index.
13619  StackFrame::Id id = isolate->debug()->break_frame_id();
13620  if (id == StackFrame::NO_ID) {
13621  // If there are no JavaScript stack frames return undefined.
13622  return heap->undefined_value();
13623  }
13624 
13625  int count = 0;
13626  JavaScriptFrameIterator it(isolate, id);
13627  for (; !it.done(); it.Advance()) {
13628  if (index < count + it.frame()->GetInlineCount()) break;
13629  count += it.frame()->GetInlineCount();
13630  }
13631  if (it.done()) return heap->undefined_value();
13632 
13633  const char* error_message = LiveEdit::RestartFrame(it.frame());
13634  if (error_message) {
13635  return *(isolate->factory()->InternalizeUtf8String(error_message));
13636  }
13637  return heap->true_value();
13638 }
13639 
13640 
13641 // A testing entry. Returns statement position which is the closest to
13642 // source_position.
13643 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionCodePositionFromSource) {
13644  HandleScope scope(isolate);
13645  CHECK(isolate->debugger()->live_edit_enabled());
13646  ASSERT(args.length() == 2);
13647  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
13648  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
13649 
13650  Handle<Code> code(function->code(), isolate);
13651 
13652  if (code->kind() != Code::FUNCTION &&
13653  code->kind() != Code::OPTIMIZED_FUNCTION) {
13654  return isolate->heap()->undefined_value();
13655  }
13656 
13657  RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION));
13658  int closest_pc = 0;
13659  int distance = kMaxInt;
13660  while (!it.done()) {
13661  int statement_position = static_cast<int>(it.rinfo()->data());
13662  // Check if this break point is closer that what was previously found.
13663  if (source_position <= statement_position &&
13664  statement_position - source_position < distance) {
13665  closest_pc =
13666  static_cast<int>(it.rinfo()->pc() - code->instruction_start());
13667  distance = statement_position - source_position;
13668  // Check whether we can't get any closer.
13669  if (distance == 0) break;
13670  }
13671  it.next();
13672  }
13673 
13674  return Smi::FromInt(closest_pc);
13675 }
13676 
13677 
13678 // Calls specified function with or without entering the debugger.
13679 // This is used in unit tests to run code as if debugger is entered or simply
13680 // to have a stack with C++ frame in the middle.
13681 RUNTIME_FUNCTION(MaybeObject*, Runtime_ExecuteInDebugContext) {
13682  HandleScope scope(isolate);
13683  ASSERT(args.length() == 2);
13684  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
13685  CONVERT_BOOLEAN_ARG_CHECKED(without_debugger, 1);
13686 
13687  Handle<Object> result;
13688  bool pending_exception;
13689  {
13690  if (without_debugger) {
13691  result = Execution::Call(isolate,
13692  function,
13693  isolate->global_object(),
13694  0,
13695  NULL,
13696  &pending_exception);
13697  } else {
13698  EnterDebugger enter_debugger(isolate);
13699  result = Execution::Call(isolate,
13700  function,
13701  isolate->global_object(),
13702  0,
13703  NULL,
13704  &pending_exception);
13705  }
13706  }
13707  if (!pending_exception) {
13708  return *result;
13709  } else {
13710  return Failure::Exception();
13711  }
13712 }
13713 
13714 
13715 // Sets a v8 flag.
13716 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFlags) {
13717  SealHandleScope shs(isolate);
13718  CONVERT_ARG_CHECKED(String, arg, 0);
13719  SmartArrayPointer<char> flags =
13720  arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
13721  FlagList::SetFlagsFromString(flags.get(), StrLength(flags.get()));
13722  return isolate->heap()->undefined_value();
13723 }
13724 
13725 
13726 // Performs a GC.
13727 // Presently, it only does a full GC.
13728 RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectGarbage) {
13729  SealHandleScope shs(isolate);
13730  isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage");
13731  return isolate->heap()->undefined_value();
13732 }
13733 
13734 
13735 // Gets the current heap usage.
13736 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHeapUsage) {
13737  SealHandleScope shs(isolate);
13738  int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
13739  if (!Smi::IsValid(usage)) {
13740  return *isolate->factory()->NewNumberFromInt(usage);
13741  }
13742  return Smi::FromInt(usage);
13743 }
13744 
13745 #endif // ENABLE_DEBUGGER_SUPPORT
13746 
13747 
13748 #ifdef V8_I18N_SUPPORT
13749 RUNTIME_FUNCTION(MaybeObject*, Runtime_CanonicalizeLanguageTag) {
13750  HandleScope scope(isolate);
13751 
13752  ASSERT(args.length() == 1);
13753  CONVERT_ARG_HANDLE_CHECKED(String, locale_id_str, 0);
13754 
13755  v8::String::Utf8Value locale_id(v8::Utils::ToLocal(locale_id_str));
13756 
13757  // Return value which denotes invalid language tag.
13758  const char* const kInvalidTag = "invalid-tag";
13759 
13760  UErrorCode error = U_ZERO_ERROR;
13761  char icu_result[ULOC_FULLNAME_CAPACITY];
13762  int icu_length = 0;
13763 
13764  uloc_forLanguageTag(*locale_id, icu_result, ULOC_FULLNAME_CAPACITY,
13765  &icu_length, &error);
13766  if (U_FAILURE(error) || icu_length == 0) {
13767  return isolate->heap()->AllocateStringFromOneByte(CStrVector(kInvalidTag));
13768  }
13769 
13770  char result[ULOC_FULLNAME_CAPACITY];
13771 
13772  // Force strict BCP47 rules.
13773  uloc_toLanguageTag(icu_result, result, ULOC_FULLNAME_CAPACITY, TRUE, &error);
13774 
13775  if (U_FAILURE(error)) {
13776  return isolate->heap()->AllocateStringFromOneByte(CStrVector(kInvalidTag));
13777  }
13778 
13779  return isolate->heap()->AllocateStringFromOneByte(CStrVector(result));
13780 }
13781 
13782 
13783 RUNTIME_FUNCTION(MaybeObject*, Runtime_AvailableLocalesOf) {
13784  HandleScope scope(isolate);
13785 
13786  ASSERT(args.length() == 1);
13787  CONVERT_ARG_HANDLE_CHECKED(String, service, 0);
13788 
13789  const icu::Locale* available_locales = NULL;
13790  int32_t count = 0;
13791 
13792  if (service->IsUtf8EqualTo(CStrVector("collator"))) {
13793  available_locales = icu::Collator::getAvailableLocales(count);
13794  } else if (service->IsUtf8EqualTo(CStrVector("numberformat"))) {
13795  available_locales = icu::NumberFormat::getAvailableLocales(count);
13796  } else if (service->IsUtf8EqualTo(CStrVector("dateformat"))) {
13797  available_locales = icu::DateFormat::getAvailableLocales(count);
13798  } else if (service->IsUtf8EqualTo(CStrVector("breakiterator"))) {
13799  available_locales = icu::BreakIterator::getAvailableLocales(count);
13800  }
13801 
13802  UErrorCode error = U_ZERO_ERROR;
13803  char result[ULOC_FULLNAME_CAPACITY];
13804  Handle<JSObject> locales =
13805  isolate->factory()->NewJSObject(isolate->object_function());
13806 
13807  for (int32_t i = 0; i < count; ++i) {
13808  const char* icu_name = available_locales[i].getName();
13809 
13810  error = U_ZERO_ERROR;
13811  // No need to force strict BCP47 rules.
13812  uloc_toLanguageTag(icu_name, result, ULOC_FULLNAME_CAPACITY, FALSE, &error);
13813  if (U_FAILURE(error)) {
13814  // This shouldn't happen, but lets not break the user.
13815  continue;
13816  }
13817 
13818  RETURN_IF_EMPTY_HANDLE(isolate,
13820  locales,
13821  isolate->factory()->NewStringFromAscii(CStrVector(result)),
13822  isolate->factory()->NewNumber(i),
13823  NONE));
13824  }
13825 
13826  return *locales;
13827 }
13828 
13829 
13830 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultICULocale) {
13831  SealHandleScope shs(isolate);
13832 
13833  ASSERT(args.length() == 0);
13834 
13835  icu::Locale default_locale;
13836 
13837  // Set the locale
13838  char result[ULOC_FULLNAME_CAPACITY];
13839  UErrorCode status = U_ZERO_ERROR;
13840  uloc_toLanguageTag(
13841  default_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
13842  if (U_SUCCESS(status)) {
13843  return isolate->heap()->AllocateStringFromOneByte(CStrVector(result));
13844  }
13845 
13846  return isolate->heap()->AllocateStringFromOneByte(CStrVector("und"));
13847 }
13848 
13849 
13850 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLanguageTagVariants) {
13851  HandleScope scope(isolate);
13852 
13853  ASSERT(args.length() == 1);
13854 
13855  CONVERT_ARG_HANDLE_CHECKED(JSArray, input, 0);
13856 
13857  uint32_t length = static_cast<uint32_t>(input->length()->Number());
13858  Handle<FixedArray> output = isolate->factory()->NewFixedArray(length);
13859  Handle<Name> maximized =
13860  isolate->factory()->NewStringFromAscii(CStrVector("maximized"));
13861  Handle<Name> base =
13862  isolate->factory()->NewStringFromAscii(CStrVector("base"));
13863  for (unsigned int i = 0; i < length; ++i) {
13864  Handle<Object> locale_id = Object::GetElement(isolate, input, i);
13865  RETURN_IF_EMPTY_HANDLE(isolate, locale_id);
13866  if (!locale_id->IsString()) {
13867  return isolate->Throw(isolate->heap()->illegal_argument_string());
13868  }
13869 
13870  v8::String::Utf8Value utf8_locale_id(
13872 
13873  UErrorCode error = U_ZERO_ERROR;
13874 
13875  // Convert from BCP47 to ICU format.
13876  // de-DE-u-co-phonebk -> de_DE@collation=phonebook
13877  char icu_locale[ULOC_FULLNAME_CAPACITY];
13878  int icu_locale_length = 0;
13879  uloc_forLanguageTag(*utf8_locale_id, icu_locale, ULOC_FULLNAME_CAPACITY,
13880  &icu_locale_length, &error);
13881  if (U_FAILURE(error) || icu_locale_length == 0) {
13882  return isolate->Throw(isolate->heap()->illegal_argument_string());
13883  }
13884 
13885  // Maximize the locale.
13886  // de_DE@collation=phonebook -> de_Latn_DE@collation=phonebook
13887  char icu_max_locale[ULOC_FULLNAME_CAPACITY];
13888  uloc_addLikelySubtags(
13889  icu_locale, icu_max_locale, ULOC_FULLNAME_CAPACITY, &error);
13890 
13891  // Remove extensions from maximized locale.
13892  // de_Latn_DE@collation=phonebook -> de_Latn_DE
13893  char icu_base_max_locale[ULOC_FULLNAME_CAPACITY];
13894  uloc_getBaseName(
13895  icu_max_locale, icu_base_max_locale, ULOC_FULLNAME_CAPACITY, &error);
13896 
13897  // Get original name without extensions.
13898  // de_DE@collation=phonebook -> de_DE
13899  char icu_base_locale[ULOC_FULLNAME_CAPACITY];
13900  uloc_getBaseName(
13901  icu_locale, icu_base_locale, ULOC_FULLNAME_CAPACITY, &error);
13902 
13903  // Convert from ICU locale format to BCP47 format.
13904  // de_Latn_DE -> de-Latn-DE
13905  char base_max_locale[ULOC_FULLNAME_CAPACITY];
13906  uloc_toLanguageTag(icu_base_max_locale, base_max_locale,
13907  ULOC_FULLNAME_CAPACITY, FALSE, &error);
13908 
13909  // de_DE -> de-DE
13910  char base_locale[ULOC_FULLNAME_CAPACITY];
13911  uloc_toLanguageTag(
13912  icu_base_locale, base_locale, ULOC_FULLNAME_CAPACITY, FALSE, &error);
13913 
13914  if (U_FAILURE(error)) {
13915  return isolate->Throw(isolate->heap()->illegal_argument_string());
13916  }
13917 
13918  Handle<JSObject> result =
13919  isolate->factory()->NewJSObject(isolate->object_function());
13920  RETURN_IF_EMPTY_HANDLE(isolate,
13922  result,
13923  maximized,
13924  isolate->factory()->NewStringFromAscii(CStrVector(base_max_locale)),
13925  NONE));
13926  RETURN_IF_EMPTY_HANDLE(isolate,
13928  result,
13929  base,
13930  isolate->factory()->NewStringFromAscii(CStrVector(base_locale)),
13931  NONE));
13932  output->set(i, *result);
13933  }
13934 
13935  Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(output);
13936  result->set_length(Smi::FromInt(length));
13937  return *result;
13938 }
13939 
13940 
13941 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateDateTimeFormat) {
13942  HandleScope scope(isolate);
13943 
13944  ASSERT(args.length() == 3);
13945 
13946  CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
13947  CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
13948  CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
13949 
13950  Handle<ObjectTemplateInfo> date_format_template =
13951  I18N::GetTemplate(isolate);
13952 
13953  // Create an empty object wrapper.
13954  bool has_pending_exception = false;
13955  Handle<JSObject> local_object = Execution::InstantiateObject(
13956  date_format_template, &has_pending_exception);
13957  if (has_pending_exception) {
13958  ASSERT(isolate->has_pending_exception());
13959  return Failure::Exception();
13960  }
13961 
13962  // Set date time formatter as internal field of the resulting JS object.
13963  icu::SimpleDateFormat* date_format = DateFormat::InitializeDateTimeFormat(
13964  isolate, locale, options, resolved);
13965 
13966  if (!date_format) return isolate->ThrowIllegalOperation();
13967 
13968  local_object->SetInternalField(0, reinterpret_cast<Smi*>(date_format));
13969 
13970  RETURN_IF_EMPTY_HANDLE(isolate,
13972  local_object,
13973  isolate->factory()->NewStringFromAscii(CStrVector("dateFormat")),
13974  isolate->factory()->NewStringFromAscii(CStrVector("valid")),
13975  NONE));
13976 
13977  // Make object handle weak so we can delete the data format once GC kicks in.
13978  Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
13979  GlobalHandles::MakeWeak(wrapper.location(),
13980  reinterpret_cast<void*>(wrapper.location()),
13982  return *local_object;
13983 }
13984 
13985 
13986 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateFormat) {
13987  HandleScope scope(isolate);
13988 
13989  ASSERT(args.length() == 2);
13990 
13991  CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
13992  CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 1);
13993 
13994  bool has_pending_exception = false;
13995  Handle<Object> value =
13996  Execution::ToNumber(isolate, date, &has_pending_exception);
13997  if (has_pending_exception) {
13998  ASSERT(isolate->has_pending_exception());
13999  return Failure::Exception();
14000  }
14001 
14002  icu::SimpleDateFormat* date_format =
14003  DateFormat::UnpackDateFormat(isolate, date_format_holder);
14004  if (!date_format) return isolate->ThrowIllegalOperation();
14005 
14006  icu::UnicodeString result;
14007  date_format->format(value->Number(), result);
14008 
14009  return *isolate->factory()->NewStringFromTwoByte(
14010  Vector<const uint16_t>(
14011  reinterpret_cast<const uint16_t*>(result.getBuffer()),
14012  result.length()));
14013 }
14014 
14015 
14016 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateParse) {
14017  HandleScope scope(isolate);
14018 
14019  ASSERT(args.length() == 2);
14020 
14021  CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
14022  CONVERT_ARG_HANDLE_CHECKED(String, date_string, 1);
14023 
14024  v8::String::Utf8Value utf8_date(v8::Utils::ToLocal(date_string));
14025  icu::UnicodeString u_date(icu::UnicodeString::fromUTF8(*utf8_date));
14026  icu::SimpleDateFormat* date_format =
14027  DateFormat::UnpackDateFormat(isolate, date_format_holder);
14028  if (!date_format) return isolate->ThrowIllegalOperation();
14029 
14030  UErrorCode status = U_ZERO_ERROR;
14031  UDate date = date_format->parse(u_date, status);
14032  if (U_FAILURE(status)) return isolate->heap()->undefined_value();
14033 
14034  bool has_pending_exception = false;
14035  Handle<JSDate> result = Handle<JSDate>::cast(
14037  isolate, static_cast<double>(date), &has_pending_exception));
14038  if (has_pending_exception) {
14039  ASSERT(isolate->has_pending_exception());
14040  return Failure::Exception();
14041  }
14042  return *result;
14043 }
14044 
14045 
14046 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateNumberFormat) {
14047  HandleScope scope(isolate);
14048 
14049  ASSERT(args.length() == 3);
14050 
14051  CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
14052  CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
14053  CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
14054 
14055  Handle<ObjectTemplateInfo> number_format_template =
14056  I18N::GetTemplate(isolate);
14057 
14058  // Create an empty object wrapper.
14059  bool has_pending_exception = false;
14060  Handle<JSObject> local_object = Execution::InstantiateObject(
14061  number_format_template, &has_pending_exception);
14062  if (has_pending_exception) {
14063  ASSERT(isolate->has_pending_exception());
14064  return Failure::Exception();
14065  }
14066 
14067  // Set number formatter as internal field of the resulting JS object.
14068  icu::DecimalFormat* number_format = NumberFormat::InitializeNumberFormat(
14069  isolate, locale, options, resolved);
14070 
14071  if (!number_format) return isolate->ThrowIllegalOperation();
14072 
14073  local_object->SetInternalField(0, reinterpret_cast<Smi*>(number_format));
14074 
14075  RETURN_IF_EMPTY_HANDLE(isolate,
14077  local_object,
14078  isolate->factory()->NewStringFromAscii(CStrVector("numberFormat")),
14079  isolate->factory()->NewStringFromAscii(CStrVector("valid")),
14080  NONE));
14081 
14082  Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
14083  GlobalHandles::MakeWeak(wrapper.location(),
14084  reinterpret_cast<void*>(wrapper.location()),
14086  return *local_object;
14087 }
14088 
14089 
14090 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberFormat) {
14091  HandleScope scope(isolate);
14092 
14093  ASSERT(args.length() == 2);
14094 
14095  CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
14096  CONVERT_ARG_HANDLE_CHECKED(Object, number, 1);
14097 
14098  bool has_pending_exception = false;
14099  Handle<Object> value = Execution::ToNumber(
14100  isolate, number, &has_pending_exception);
14101  if (has_pending_exception) {
14102  ASSERT(isolate->has_pending_exception());
14103  return Failure::Exception();
14104  }
14105 
14106  icu::DecimalFormat* number_format =
14107  NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
14108  if (!number_format) return isolate->ThrowIllegalOperation();
14109 
14110  icu::UnicodeString result;
14111  number_format->format(value->Number(), result);
14112 
14113  return *isolate->factory()->NewStringFromTwoByte(
14114  Vector<const uint16_t>(
14115  reinterpret_cast<const uint16_t*>(result.getBuffer()),
14116  result.length()));
14117 }
14118 
14119 
14120 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberParse) {
14121  HandleScope scope(isolate);
14122 
14123  ASSERT(args.length() == 2);
14124 
14125  CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
14126  CONVERT_ARG_HANDLE_CHECKED(String, number_string, 1);
14127 
14128  v8::String::Utf8Value utf8_number(v8::Utils::ToLocal(number_string));
14129  icu::UnicodeString u_number(icu::UnicodeString::fromUTF8(*utf8_number));
14130  icu::DecimalFormat* number_format =
14131  NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
14132  if (!number_format) return isolate->ThrowIllegalOperation();
14133 
14134  UErrorCode status = U_ZERO_ERROR;
14135  icu::Formattable result;
14136  // ICU 4.6 doesn't support parseCurrency call. We need to wait for ICU49
14137  // to be part of Chrome.
14138  // TODO(cira): Include currency parsing code using parseCurrency call.
14139  // We need to check if the formatter parses all currencies or only the
14140  // one it was constructed with (it will impact the API - how to return ISO
14141  // code and the value).
14142  number_format->parse(u_number, result, status);
14143  if (U_FAILURE(status)) return isolate->heap()->undefined_value();
14144 
14145  switch (result.getType()) {
14146  case icu::Formattable::kDouble:
14147  return *isolate->factory()->NewNumber(result.getDouble());
14148  case icu::Formattable::kLong:
14149  return *isolate->factory()->NewNumberFromInt(result.getLong());
14150  case icu::Formattable::kInt64:
14151  return *isolate->factory()->NewNumber(
14152  static_cast<double>(result.getInt64()));
14153  default:
14154  return isolate->heap()->undefined_value();
14155  }
14156 }
14157 
14158 
14159 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateCollator) {
14160  HandleScope scope(isolate);
14161 
14162  ASSERT(args.length() == 3);
14163 
14164  CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
14165  CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
14166  CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
14167 
14168  Handle<ObjectTemplateInfo> collator_template = I18N::GetTemplate(isolate);
14169 
14170  // Create an empty object wrapper.
14171  bool has_pending_exception = false;
14172  Handle<JSObject> local_object = Execution::InstantiateObject(
14173  collator_template, &has_pending_exception);
14174  if (has_pending_exception) {
14175  ASSERT(isolate->has_pending_exception());
14176  return Failure::Exception();
14177  }
14178 
14179  // Set collator as internal field of the resulting JS object.
14180  icu::Collator* collator = Collator::InitializeCollator(
14181  isolate, locale, options, resolved);
14182 
14183  if (!collator) return isolate->ThrowIllegalOperation();
14184 
14185  local_object->SetInternalField(0, reinterpret_cast<Smi*>(collator));
14186 
14187  RETURN_IF_EMPTY_HANDLE(isolate,
14189  local_object,
14190  isolate->factory()->NewStringFromAscii(CStrVector("collator")),
14191  isolate->factory()->NewStringFromAscii(CStrVector("valid")),
14192  NONE));
14193 
14194  Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
14195  GlobalHandles::MakeWeak(wrapper.location(),
14196  reinterpret_cast<void*>(wrapper.location()),
14198  return *local_object;
14199 }
14200 
14201 
14202 RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalCompare) {
14203  HandleScope scope(isolate);
14204 
14205  ASSERT(args.length() == 3);
14206 
14207  CONVERT_ARG_HANDLE_CHECKED(JSObject, collator_holder, 0);
14208  CONVERT_ARG_HANDLE_CHECKED(String, string1, 1);
14209  CONVERT_ARG_HANDLE_CHECKED(String, string2, 2);
14210 
14211  icu::Collator* collator = Collator::UnpackCollator(isolate, collator_holder);
14212  if (!collator) return isolate->ThrowIllegalOperation();
14213 
14214  v8::String::Value string_value1(v8::Utils::ToLocal(string1));
14215  v8::String::Value string_value2(v8::Utils::ToLocal(string2));
14216  const UChar* u_string1 = reinterpret_cast<const UChar*>(*string_value1);
14217  const UChar* u_string2 = reinterpret_cast<const UChar*>(*string_value2);
14218  UErrorCode status = U_ZERO_ERROR;
14219  UCollationResult result = collator->compare(u_string1,
14220  string_value1.length(),
14221  u_string2,
14222  string_value2.length(),
14223  status);
14224  if (U_FAILURE(status)) return isolate->ThrowIllegalOperation();
14225 
14226  return *isolate->factory()->NewNumberFromInt(result);
14227 }
14228 
14229 
14230 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringNormalize) {
14231  HandleScope scope(isolate);
14232  static const UNormalizationMode normalizationForms[] =
14233  { UNORM_NFC, UNORM_NFD, UNORM_NFKC, UNORM_NFKD };
14234 
14235  ASSERT(args.length() == 2);
14236 
14237  CONVERT_ARG_HANDLE_CHECKED(String, stringValue, 0);
14238  CONVERT_NUMBER_CHECKED(int, form_id, Int32, args[1]);
14239 
14240  v8::String::Value string_value(v8::Utils::ToLocal(stringValue));
14241  const UChar* u_value = reinterpret_cast<const UChar*>(*string_value);
14242 
14243  // TODO(mnita): check Normalizer2 (not available in ICU 46)
14244  UErrorCode status = U_ZERO_ERROR;
14245  icu::UnicodeString result;
14246  icu::Normalizer::normalize(u_value, normalizationForms[form_id], 0,
14247  result, status);
14248  if (U_FAILURE(status)) {
14249  return isolate->heap()->undefined_value();
14250  }
14251 
14252  return *isolate->factory()->NewStringFromTwoByte(
14253  Vector<const uint16_t>(
14254  reinterpret_cast<const uint16_t*>(result.getBuffer()),
14255  result.length()));
14256 }
14257 
14258 
14259 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateBreakIterator) {
14260  HandleScope scope(isolate);
14261 
14262  ASSERT(args.length() == 3);
14263 
14264  CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
14265  CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
14266  CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
14267 
14268  Handle<ObjectTemplateInfo> break_iterator_template =
14269  I18N::GetTemplate2(isolate);
14270 
14271  // Create an empty object wrapper.
14272  bool has_pending_exception = false;
14273  Handle<JSObject> local_object = Execution::InstantiateObject(
14274  break_iterator_template, &has_pending_exception);
14275  if (has_pending_exception) {
14276  ASSERT(isolate->has_pending_exception());
14277  return Failure::Exception();
14278  }
14279 
14280  // Set break iterator as internal field of the resulting JS object.
14281  icu::BreakIterator* break_iterator = BreakIterator::InitializeBreakIterator(
14282  isolate, locale, options, resolved);
14283 
14284  if (!break_iterator) return isolate->ThrowIllegalOperation();
14285 
14286  local_object->SetInternalField(0, reinterpret_cast<Smi*>(break_iterator));
14287  // Make sure that the pointer to adopted text is NULL.
14288  local_object->SetInternalField(1, reinterpret_cast<Smi*>(NULL));
14289 
14290  RETURN_IF_EMPTY_HANDLE(isolate,
14292  local_object,
14293  isolate->factory()->NewStringFromAscii(CStrVector("breakIterator")),
14294  isolate->factory()->NewStringFromAscii(CStrVector("valid")),
14295  NONE));
14296 
14297  // Make object handle weak so we can delete the break iterator once GC kicks
14298  // in.
14299  Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
14300  GlobalHandles::MakeWeak(wrapper.location(),
14301  reinterpret_cast<void*>(wrapper.location()),
14303  return *local_object;
14304 }
14305 
14306 
14307 RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorAdoptText) {
14308  HandleScope scope(isolate);
14309 
14310  ASSERT(args.length() == 2);
14311 
14312  CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14313  CONVERT_ARG_HANDLE_CHECKED(String, text, 1);
14314 
14315  icu::BreakIterator* break_iterator =
14316  BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14317  if (!break_iterator) return isolate->ThrowIllegalOperation();
14318 
14319  icu::UnicodeString* u_text = reinterpret_cast<icu::UnicodeString*>(
14320  break_iterator_holder->GetInternalField(1));
14321  delete u_text;
14322 
14323  v8::String::Value text_value(v8::Utils::ToLocal(text));
14324  u_text = new icu::UnicodeString(
14325  reinterpret_cast<const UChar*>(*text_value), text_value.length());
14326  break_iterator_holder->SetInternalField(1, reinterpret_cast<Smi*>(u_text));
14327 
14328  break_iterator->setText(*u_text);
14329 
14330  return isolate->heap()->undefined_value();
14331 }
14332 
14333 
14334 RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorFirst) {
14335  HandleScope scope(isolate);
14336 
14337  ASSERT(args.length() == 1);
14338 
14339  CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14340 
14341  icu::BreakIterator* break_iterator =
14342  BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14343  if (!break_iterator) return isolate->ThrowIllegalOperation();
14344 
14345  return *isolate->factory()->NewNumberFromInt(break_iterator->first());
14346 }
14347 
14348 
14349 RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorNext) {
14350  HandleScope scope(isolate);
14351 
14352  ASSERT(args.length() == 1);
14353 
14354  CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14355 
14356  icu::BreakIterator* break_iterator =
14357  BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14358  if (!break_iterator) return isolate->ThrowIllegalOperation();
14359 
14360  return *isolate->factory()->NewNumberFromInt(break_iterator->next());
14361 }
14362 
14363 
14364 RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorCurrent) {
14365  HandleScope scope(isolate);
14366 
14367  ASSERT(args.length() == 1);
14368 
14369  CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14370 
14371  icu::BreakIterator* break_iterator =
14372  BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14373  if (!break_iterator) return isolate->ThrowIllegalOperation();
14374 
14375  return *isolate->factory()->NewNumberFromInt(break_iterator->current());
14376 }
14377 
14378 
14379 RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorBreakType) {
14380  HandleScope scope(isolate);
14381 
14382  ASSERT(args.length() == 1);
14383 
14384  CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14385 
14386  icu::BreakIterator* break_iterator =
14387  BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14388  if (!break_iterator) return isolate->ThrowIllegalOperation();
14389 
14390  // TODO(cira): Remove cast once ICU fixes base BreakIterator class.
14391  icu::RuleBasedBreakIterator* rule_based_iterator =
14392  static_cast<icu::RuleBasedBreakIterator*>(break_iterator);
14393  int32_t status = rule_based_iterator->getRuleStatus();
14394  // Keep return values in sync with JavaScript BreakType enum.
14395  if (status >= UBRK_WORD_NONE && status < UBRK_WORD_NONE_LIMIT) {
14396  return *isolate->factory()->NewStringFromAscii(CStrVector("none"));
14397  } else if (status >= UBRK_WORD_NUMBER && status < UBRK_WORD_NUMBER_LIMIT) {
14398  return *isolate->factory()->NewStringFromAscii(CStrVector("number"));
14399  } else if (status >= UBRK_WORD_LETTER && status < UBRK_WORD_LETTER_LIMIT) {
14400  return *isolate->factory()->NewStringFromAscii(CStrVector("letter"));
14401  } else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) {
14402  return *isolate->factory()->NewStringFromAscii(CStrVector("kana"));
14403  } else if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) {
14404  return *isolate->factory()->NewStringFromAscii(CStrVector("ideo"));
14405  } else {
14406  return *isolate->factory()->NewStringFromAscii(CStrVector("unknown"));
14407  }
14408 }
14409 #endif // V8_I18N_SUPPORT
14410 
14411 
14412 // Finds the script object from the script data. NOTE: This operation uses
14413 // heap traversal to find the function generated for the source position
14414 // for the requested break point. For lazily compiled functions several heap
14415 // traversals might be required rendering this operation as a rather slow
14416 // operation. However for setting break points which is normally done through
14417 // some kind of user interaction the performance is not crucial.
14418 static Handle<Object> Runtime_GetScriptFromScriptName(
14419  Handle<String> script_name) {
14420  // Scan the heap for Script objects to find the script with the requested
14421  // script data.
14422  Handle<Script> script;
14423  Factory* factory = script_name->GetIsolate()->factory();
14424  Heap* heap = script_name->GetHeap();
14425  heap->EnsureHeapIsIterable();
14426  DisallowHeapAllocation no_allocation_during_heap_iteration;
14427  HeapIterator iterator(heap);
14428  HeapObject* obj = NULL;
14429  while (script.is_null() && ((obj = iterator.next()) != NULL)) {
14430  // If a script is found check if it has the script data requested.
14431  if (obj->IsScript()) {
14432  if (Script::cast(obj)->name()->IsString()) {
14433  if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) {
14434  script = Handle<Script>(Script::cast(obj));
14435  }
14436  }
14437  }
14438  }
14439 
14440  // If no script with the requested script data is found return undefined.
14441  if (script.is_null()) return factory->undefined_value();
14442 
14443  // Return the script found.
14444  return GetScriptWrapper(script);
14445 }
14446 
14447 
14448 // Get the script object from script data. NOTE: Regarding performance
14449 // see the NOTE for GetScriptFromScriptData.
14450 // args[0]: script data for the script to find the source for
14451 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScript) {
14452  HandleScope scope(isolate);
14453 
14454  ASSERT(args.length() == 1);
14455 
14456  CONVERT_ARG_CHECKED(String, script_name, 0);
14457 
14458  // Find the requested script.
14459  Handle<Object> result =
14460  Runtime_GetScriptFromScriptName(Handle<String>(script_name));
14461  return *result;
14462 }
14463 
14464 
14465 // Collect the raw data for a stack trace. Returns an array of 4
14466 // element segments each containing a receiver, function, code and
14467 // native code offset.
14468 RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectStackTrace) {
14469  HandleScope scope(isolate);
14470  ASSERT_EQ(args.length(), 3);
14471  CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
14472  Handle<Object> caller = args.at<Object>(1);
14473  CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[2]);
14474 
14475  // Optionally capture a more detailed stack trace for the message.
14476  isolate->CaptureAndSetDetailedStackTrace(error_object);
14477  // Capture a simple stack trace for the stack property.
14478  return *isolate->CaptureSimpleStackTrace(error_object, caller, limit);
14479 }
14480 
14481 
14482 // Retrieve the stack trace. This is the raw stack trace that yet has to
14483 // be formatted. Since we only need this once, clear it afterwards.
14484 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetAndClearOverflowedStackTrace) {
14485  HandleScope scope(isolate);
14486  ASSERT_EQ(args.length(), 1);
14487  CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
14488  Handle<String> key = isolate->factory()->hidden_stack_trace_string();
14489  Handle<Object> result(error_object->GetHiddenProperty(*key), isolate);
14490  if (result->IsTheHole()) return isolate->heap()->undefined_value();
14491  RUNTIME_ASSERT(result->IsJSArray() || result->IsUndefined());
14492  JSObject::DeleteHiddenProperty(error_object, key);
14493  return *result;
14494 }
14495 
14496 
14497 // Returns V8 version as a string.
14498 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetV8Version) {
14499  SealHandleScope shs(isolate);
14500  ASSERT_EQ(args.length(), 0);
14501 
14502  const char* version_string = v8::V8::GetVersion();
14503 
14504  return isolate->heap()->AllocateStringFromOneByte(CStrVector(version_string),
14505  NOT_TENURED);
14506 }
14507 
14508 
14509 RUNTIME_FUNCTION(MaybeObject*, Runtime_Abort) {
14510  SealHandleScope shs(isolate);
14511  ASSERT(args.length() == 1);
14512  CONVERT_SMI_ARG_CHECKED(message_id, 0);
14513  const char* message = GetBailoutReason(
14514  static_cast<BailoutReason>(message_id));
14515  OS::PrintError("abort: %s\n", message);
14516  isolate->PrintStack(stderr);
14517  OS::Abort();
14518  UNREACHABLE();
14519  return NULL;
14520 }
14521 
14522 
14523 RUNTIME_FUNCTION(MaybeObject*, Runtime_AbortJS) {
14524  HandleScope scope(isolate);
14525  ASSERT(args.length() == 1);
14527  OS::PrintError("abort: %s\n", message->ToCString().get());
14528  isolate->PrintStack(stderr);
14529  OS::Abort();
14530  UNREACHABLE();
14531  return NULL;
14532 }
14533 
14534 
14535 RUNTIME_FUNCTION(MaybeObject*, Runtime_FlattenString) {
14536  HandleScope scope(isolate);
14537  ASSERT(args.length() == 1);
14539  FlattenString(str);
14540  return isolate->heap()->undefined_value();
14541 }
14542 
14543 
14544 RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyContextDisposed) {
14545  HandleScope scope(isolate);
14546  ASSERT(args.length() == 0);
14547  isolate->heap()->NotifyContextDisposed();
14548  return isolate->heap()->undefined_value();
14549 }
14550 
14551 
14552 RUNTIME_FUNCTION(MaybeObject*, Runtime_TryMigrateInstance) {
14553  HandleScope scope(isolate);
14554  ASSERT(args.length() == 1);
14555  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
14556  if (!object->IsJSObject()) return Smi::FromInt(0);
14557  Handle<JSObject> js_object = Handle<JSObject>::cast(object);
14558  if (!js_object->map()->is_deprecated()) return Smi::FromInt(0);
14559  // This call must not cause lazy deopts, because it's called from deferred
14560  // code where we can't handle lazy deopts for lack of a suitable bailout
14561  // ID. So we just try migration and signal failure if necessary,
14562  // which will also trigger a deopt.
14563  Handle<Object> result = JSObject::TryMigrateInstance(js_object);
14564  if (result.is_null()) return Smi::FromInt(0);
14565  return *object;
14566 }
14567 
14568 
14569 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_GetFromCache) {
14570  SealHandleScope shs(isolate);
14571  // This is only called from codegen, so checks might be more lax.
14573  Object* key = args[1];
14574 
14575  int finger_index = cache->finger_index();
14576  Object* o = cache->get(finger_index);
14577  if (o == key) {
14578  // The fastest case: hit the same place again.
14579  return cache->get(finger_index + 1);
14580  }
14581 
14582  for (int i = finger_index - 2;
14584  i -= 2) {
14585  o = cache->get(i);
14586  if (o == key) {
14587  cache->set_finger_index(i);
14588  return cache->get(i + 1);
14589  }
14590  }
14591 
14592  int size = cache->size();
14593  ASSERT(size <= cache->length());
14594 
14595  for (int i = size - 2; i > finger_index; i -= 2) {
14596  o = cache->get(i);
14597  if (o == key) {
14598  cache->set_finger_index(i);
14599  return cache->get(i + 1);
14600  }
14601  }
14602 
14603  // There is no value in the cache. Invoke the function and cache result.
14604  HandleScope scope(isolate);
14605 
14606  Handle<JSFunctionResultCache> cache_handle(cache);
14607  Handle<Object> key_handle(key, isolate);
14608  Handle<Object> value;
14609  {
14611  cache_handle->get(JSFunctionResultCache::kFactoryIndex)));
14612  // TODO(antonm): consider passing a receiver when constructing a cache.
14613  Handle<Object> receiver(isolate->native_context()->global_object(),
14614  isolate);
14615  // This handle is nor shared, nor used later, so it's safe.
14616  Handle<Object> argv[] = { key_handle };
14617  bool pending_exception;
14618  value = Execution::Call(isolate,
14619  factory,
14620  receiver,
14621  ARRAY_SIZE(argv),
14622  argv,
14623  &pending_exception);
14624  if (pending_exception) return Failure::Exception();
14625  }
14626 
14627 #ifdef VERIFY_HEAP
14628  if (FLAG_verify_heap) {
14629  cache_handle->JSFunctionResultCacheVerify();
14630  }
14631 #endif
14632 
14633  // Function invocation may have cleared the cache. Reread all the data.
14634  finger_index = cache_handle->finger_index();
14635  size = cache_handle->size();
14636 
14637  // If we have spare room, put new data into it, otherwise evict post finger
14638  // entry which is likely to be the least recently used.
14639  int index = -1;
14640  if (size < cache_handle->length()) {
14641  cache_handle->set_size(size + JSFunctionResultCache::kEntrySize);
14642  index = size;
14643  } else {
14644  index = finger_index + JSFunctionResultCache::kEntrySize;
14645  if (index == cache_handle->length()) {
14647  }
14648  }
14649 
14650  ASSERT(index % 2 == 0);
14652  ASSERT(index < cache_handle->length());
14653 
14654  cache_handle->set(index, *key_handle);
14655  cache_handle->set(index + 1, *value);
14656  cache_handle->set_finger_index(index);
14657 
14658 #ifdef VERIFY_HEAP
14659  if (FLAG_verify_heap) {
14660  cache_handle->JSFunctionResultCacheVerify();
14661  }
14662 #endif
14663 
14664  return *value;
14665 }
14666 
14667 
14668 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetStartPosition) {
14669  SealHandleScope shs(isolate);
14671  return Smi::FromInt(message->start_position());
14672 }
14673 
14674 
14675 RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetScript) {
14676  SealHandleScope shs(isolate);
14678  return message->script();
14679 }
14680 
14681 
14682 #ifdef DEBUG
14683 // ListNatives is ONLY used by the fuzz-natives.js in debug mode
14684 // Exclude the code in release mode.
14685 RUNTIME_FUNCTION(MaybeObject*, Runtime_ListNatives) {
14686  HandleScope scope(isolate);
14687  ASSERT(args.length() == 0);
14688 #define COUNT_ENTRY(Name, argc, ressize) + 1
14689  int entry_count = 0
14690  RUNTIME_FUNCTION_LIST(COUNT_ENTRY)
14691  RUNTIME_HIDDEN_FUNCTION_LIST(COUNT_ENTRY)
14692  INLINE_FUNCTION_LIST(COUNT_ENTRY);
14693 #undef COUNT_ENTRY
14694  Factory* factory = isolate->factory();
14695  Handle<FixedArray> elements = factory->NewFixedArray(entry_count);
14696  int index = 0;
14697  bool inline_runtime_functions = false;
14698 #define ADD_ENTRY(Name, argc, ressize) \
14699  { \
14700  HandleScope inner(isolate); \
14701  Handle<String> name; \
14702  /* Inline runtime functions have an underscore in front of the name. */ \
14703  if (inline_runtime_functions) { \
14704  name = factory->NewStringFromAscii( \
14705  Vector<const char>("_" #Name, StrLength("_" #Name))); \
14706  } else { \
14707  name = factory->NewStringFromAscii( \
14708  Vector<const char>(#Name, StrLength(#Name))); \
14709  } \
14710  Handle<FixedArray> pair_elements = factory->NewFixedArray(2); \
14711  pair_elements->set(0, *name); \
14712  pair_elements->set(1, Smi::FromInt(argc)); \
14713  Handle<JSArray> pair = factory->NewJSArrayWithElements(pair_elements); \
14714  elements->set(index++, *pair); \
14715  }
14716  inline_runtime_functions = false;
14717  RUNTIME_FUNCTION_LIST(ADD_ENTRY)
14718  // Calling hidden runtime functions should just throw.
14719  RUNTIME_HIDDEN_FUNCTION_LIST(ADD_ENTRY)
14720  inline_runtime_functions = true;
14721  INLINE_FUNCTION_LIST(ADD_ENTRY)
14722 #undef ADD_ENTRY
14723  ASSERT_EQ(index, entry_count);
14724  Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
14725  return *result;
14726 }
14727 #endif
14728 
14729 
14730 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_Log) {
14731  HandleScope handle_scope(isolate);
14732  ASSERT(args.length() == 2);
14733  CONVERT_ARG_HANDLE_CHECKED(String, format, 0);
14735 
14736  SmartArrayPointer<char> format_chars = format->ToCString();
14737  isolate->logger()->LogRuntime(
14738  Vector<const char>(format_chars.get(), format->length()), elms);
14739  return isolate->heap()->undefined_value();
14740 }
14741 
14742 
14743 RUNTIME_FUNCTION(MaybeObject*, Runtime_IS_VAR) {
14744  UNREACHABLE(); // implemented as macro in the parser
14745  return NULL;
14746 }
14747 
14748 
14749 #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \
14750  RUNTIME_FUNCTION(MaybeObject*, Runtime_Has##Name) { \
14751  CONVERT_ARG_CHECKED(JSObject, obj, 0); \
14752  return isolate->heap()->ToBoolean(obj->Has##Name()); \
14753  }
14754 
14755 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiElements)
14756 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements)
14757 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements)
14758 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
14759 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
14760 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
14761 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SloppyArgumentsElements)
14762 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
14763 // Properties test sitting with elements tests - not fooling anyone.
14765 
14766 #undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
14767 
14768 
14769 #define TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, size) \
14770  RUNTIME_FUNCTION(MaybeObject*, Runtime_HasExternal##Type##Elements) { \
14771  CONVERT_ARG_CHECKED(JSObject, obj, 0); \
14772  return isolate->heap()->ToBoolean(obj->HasExternal##Type##Elements()); \
14773  }
14774 
14776 
14777 #undef TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
14778 
14779 
14780 #define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, s) \
14781  RUNTIME_FUNCTION(MaybeObject*, Runtime_HasFixed##Type##Elements) { \
14782  CONVERT_ARG_CHECKED(JSObject, obj, 0); \
14783  return isolate->heap()->ToBoolean(obj->HasFixed##Type##Elements()); \
14784  }
14785 
14787 
14788 #undef FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
14789 
14790 
14791 RUNTIME_FUNCTION(MaybeObject*, Runtime_HaveSameMap) {
14792  SealHandleScope shs(isolate);
14793  ASSERT(args.length() == 2);
14794  CONVERT_ARG_CHECKED(JSObject, obj1, 0);
14795  CONVERT_ARG_CHECKED(JSObject, obj2, 1);
14796  return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
14797 }
14798 
14799 
14800 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAccessCheckNeeded) {
14801  SealHandleScope shs(isolate);
14802  ASSERT(args.length() == 1);
14804  return isolate->heap()->ToBoolean(obj->IsAccessCheckNeeded());
14805 }
14806 
14807 
14808 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsObserved) {
14809  SealHandleScope shs(isolate);
14810  ASSERT(args.length() == 1);
14811 
14812  if (!args[0]->IsJSReceiver()) return isolate->heap()->false_value();
14813  JSReceiver* obj = JSReceiver::cast(args[0]);
14814  if (obj->IsJSGlobalProxy()) {
14815  Object* proto = obj->GetPrototype();
14816  if (proto->IsNull()) return isolate->heap()->false_value();
14817  ASSERT(proto->IsJSGlobalObject());
14818  obj = JSReceiver::cast(proto);
14819  }
14820  return isolate->heap()->ToBoolean(obj->map()->is_observed());
14821 }
14822 
14823 
14824 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetIsObserved) {
14825  HandleScope scope(isolate);
14826  ASSERT(args.length() == 1);
14828  if (obj->IsJSGlobalProxy()) {
14829  Object* proto = obj->GetPrototype();
14830  if (proto->IsNull()) return isolate->heap()->undefined_value();
14831  ASSERT(proto->IsJSGlobalObject());
14832  obj = handle(JSReceiver::cast(proto));
14833  }
14834  if (obj->IsJSProxy())
14835  return isolate->heap()->undefined_value();
14836 
14837  ASSERT(!(obj->map()->is_observed() && obj->IsJSObject() &&
14838  Handle<JSObject>::cast(obj)->HasFastElements()));
14839  ASSERT(obj->IsJSObject());
14841  return isolate->heap()->undefined_value();
14842 }
14843 
14844 
14845 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetMicrotaskPending) {
14846  SealHandleScope shs(isolate);
14847  ASSERT(args.length() == 1);
14848  CONVERT_BOOLEAN_ARG_CHECKED(new_state, 0);
14849  bool old_state = isolate->microtask_pending();
14850  isolate->set_microtask_pending(new_state);
14851  return isolate->heap()->ToBoolean(old_state);
14852 }
14853 
14854 
14855 RUNTIME_FUNCTION(MaybeObject*, Runtime_RunMicrotasks) {
14856  HandleScope scope(isolate);
14857  ASSERT(args.length() == 0);
14858  if (isolate->microtask_pending())
14859  Execution::RunMicrotasks(isolate);
14860  return isolate->heap()->undefined_value();
14861 }
14862 
14863 
14864 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetMicrotaskState) {
14865  SealHandleScope shs(isolate);
14866  ASSERT(args.length() == 0);
14867  return isolate->heap()->microtask_state();
14868 }
14869 
14870 
14871 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetObservationState) {
14872  SealHandleScope shs(isolate);
14873  ASSERT(args.length() == 0);
14874  return isolate->heap()->observation_state();
14875 }
14876 
14877 
14878 RUNTIME_FUNCTION(MaybeObject*, Runtime_ObservationWeakMapCreate) {
14879  HandleScope scope(isolate);
14880  ASSERT(args.length() == 0);
14881  // TODO(adamk): Currently this runtime function is only called three times per
14882  // isolate. If it's called more often, the map should be moved into the
14883  // strong root list.
14884  Handle<Map> map =
14885  isolate->factory()->NewMap(JS_WEAK_MAP_TYPE, JSWeakMap::kSize);
14886  Handle<JSWeakMap> weakmap =
14887  Handle<JSWeakMap>::cast(isolate->factory()->NewJSObjectFromMap(map));
14888  return WeakCollectionInitialize(isolate, weakmap);
14889 }
14890 
14891 
14892 RUNTIME_FUNCTION(MaybeObject*, Runtime_UnwrapGlobalProxy) {
14893  SealHandleScope shs(isolate);
14894  ASSERT(args.length() == 1);
14895  Object* object = args[0];
14896  if (object->IsJSGlobalProxy()) {
14897  object = object->GetPrototype(isolate);
14898  if (object->IsNull()) return isolate->heap()->undefined_value();
14899  }
14900  return object;
14901 }
14902 
14903 
14904 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAccessAllowedForObserver) {
14905  HandleScope scope(isolate);
14906  ASSERT(args.length() == 3);
14907  CONVERT_ARG_HANDLE_CHECKED(JSFunction, observer, 0);
14909  ASSERT(object->map()->is_access_check_needed());
14910  Handle<Object> key = args.at<Object>(2);
14911  SaveContext save(isolate);
14912  isolate->set_context(observer->context());
14913  if (!isolate->MayNamedAccessWrapper(object,
14914  isolate->factory()->undefined_value(),
14915  v8::ACCESS_KEYS)) {
14916  return isolate->heap()->false_value();
14917  }
14918  bool access_allowed = false;
14919  uint32_t index = 0;
14920  if (key->ToArrayIndex(&index) ||
14921  (key->IsString() && String::cast(*key)->AsArrayIndex(&index))) {
14922  access_allowed =
14923  isolate->MayIndexedAccessWrapper(object, index, v8::ACCESS_GET) &&
14924  isolate->MayIndexedAccessWrapper(object, index, v8::ACCESS_HAS);
14925  } else {
14926  access_allowed =
14927  isolate->MayNamedAccessWrapper(object, key, v8::ACCESS_GET) &&
14928  isolate->MayNamedAccessWrapper(object, key, v8::ACCESS_HAS);
14929  }
14930  return isolate->heap()->ToBoolean(access_allowed);
14931 }
14932 
14933 
14934 static MaybeObject* ArrayConstructorCommon(Isolate* isolate,
14935  Handle<JSFunction> constructor,
14937  Arguments* caller_args) {
14938  Factory* factory = isolate->factory();
14939 
14940  bool holey = false;
14941  bool can_use_type_feedback = true;
14942  if (caller_args->length() == 1) {
14943  Handle<Object> argument_one = caller_args->at<Object>(0);
14944  if (argument_one->IsSmi()) {
14945  int value = Handle<Smi>::cast(argument_one)->value();
14946  if (value < 0 || value >= JSObject::kInitialMaxFastElementArray) {
14947  // the array is a dictionary in this case.
14948  can_use_type_feedback = false;
14949  } else if (value != 0) {
14950  holey = true;
14951  }
14952  } else {
14953  // Non-smi length argument produces a dictionary
14954  can_use_type_feedback = false;
14955  }
14956  }
14957 
14958  Handle<JSArray> array;
14959  if (!site.is_null() && can_use_type_feedback) {
14960  ElementsKind to_kind = site->GetElementsKind();
14961  if (holey && !IsFastHoleyElementsKind(to_kind)) {
14962  to_kind = GetHoleyElementsKind(to_kind);
14963  // Update the allocation site info to reflect the advice alteration.
14964  site->SetElementsKind(to_kind);
14965  }
14966 
14967  // We should allocate with an initial map that reflects the allocation site
14968  // advice. Therefore we use AllocateJSObjectFromMap instead of passing
14969  // the constructor.
14970  Handle<Map> initial_map(constructor->initial_map(), isolate);
14971  if (to_kind != initial_map->elements_kind()) {
14972  initial_map = Map::AsElementsKind(initial_map, to_kind);
14973  RETURN_IF_EMPTY_HANDLE(isolate, initial_map);
14974  }
14975 
14976  // If we don't care to track arrays of to_kind ElementsKind, then
14977  // don't emit a memento for them.
14978  Handle<AllocationSite> allocation_site;
14980  allocation_site = site;
14981  }
14982 
14983  array = Handle<JSArray>::cast(factory->NewJSObjectFromMap(
14984  initial_map, NOT_TENURED, true, allocation_site));
14985  } else {
14986  array = Handle<JSArray>::cast(factory->NewJSObject(constructor));
14987 
14988  // We might need to transition to holey
14989  ElementsKind kind = constructor->initial_map()->elements_kind();
14990  if (holey && !IsFastHoleyElementsKind(kind)) {
14991  kind = GetHoleyElementsKind(kind);
14992  JSObject::TransitionElementsKind(array, kind);
14993  }
14994  }
14995 
14996  factory->NewJSArrayStorage(array, 0, 0, DONT_INITIALIZE_ARRAY_ELEMENTS);
14997 
14998  ElementsKind old_kind = array->GetElementsKind();
14999  RETURN_IF_EMPTY_HANDLE(isolate,
15000  ArrayConstructInitializeElements(array, caller_args));
15001  if (!site.is_null() &&
15002  (old_kind != array->GetElementsKind() ||
15003  !can_use_type_feedback)) {
15004  // The arguments passed in caused a transition. This kind of complexity
15005  // can't be dealt with in the inlined hydrogen array constructor case.
15006  // We must mark the allocationsite as un-inlinable.
15007  site->SetDoNotInlineCall();
15008  }
15009  return *array;
15010 }
15011 
15012 
15013 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_ArrayConstructor) {
15014  HandleScope scope(isolate);
15015  // If we get 2 arguments then they are the stub parameters (constructor, type
15016  // info). If we get 4, then the first one is a pointer to the arguments
15017  // passed by the caller, and the last one is the length of the arguments
15018  // passed to the caller (redundant, but useful to check on the deoptimizer
15019  // with an assert).
15020  Arguments empty_args(0, NULL);
15021  bool no_caller_args = args.length() == 2;
15022  ASSERT(no_caller_args || args.length() == 4);
15023  int parameters_start = no_caller_args ? 0 : 1;
15024  Arguments* caller_args = no_caller_args
15025  ? &empty_args
15026  : reinterpret_cast<Arguments*>(args[0]);
15027  CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start);
15028  CONVERT_ARG_HANDLE_CHECKED(Object, type_info, parameters_start + 1);
15029 #ifdef DEBUG
15030  if (!no_caller_args) {
15031  CONVERT_SMI_ARG_CHECKED(arg_count, parameters_start + 2);
15032  ASSERT(arg_count == caller_args->length());
15033  }
15034 #endif
15035 
15037  if (!type_info.is_null() &&
15038  *type_info != isolate->heap()->undefined_value()) {
15039  site = Handle<AllocationSite>::cast(type_info);
15040  ASSERT(!site->SitePointsToLiteral());
15041  }
15042 
15043  return ArrayConstructorCommon(isolate,
15044  constructor,
15045  site,
15046  caller_args);
15047 }
15048 
15049 
15050 RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_InternalArrayConstructor) {
15051  HandleScope scope(isolate);
15052  Arguments empty_args(0, NULL);
15053  bool no_caller_args = args.length() == 1;
15054  ASSERT(no_caller_args || args.length() == 3);
15055  int parameters_start = no_caller_args ? 0 : 1;
15056  Arguments* caller_args = no_caller_args
15057  ? &empty_args
15058  : reinterpret_cast<Arguments*>(args[0]);
15059  CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start);
15060 #ifdef DEBUG
15061  if (!no_caller_args) {
15062  CONVERT_SMI_ARG_CHECKED(arg_count, parameters_start + 1);
15063  ASSERT(arg_count == caller_args->length());
15064  }
15065 #endif
15066  return ArrayConstructorCommon(isolate,
15067  constructor,
15069  caller_args);
15070 }
15071 
15072 
15073 RUNTIME_FUNCTION(MaybeObject*, Runtime_MaxSmi) {
15074  return Smi::FromInt(Smi::kMaxValue);
15075 }
15076 
15077 
15078 // ----------------------------------------------------------------------------
15079 // Implementation of Runtime
15080 
15081 #define F(name, number_of_args, result_size) \
15082  { Runtime::k##name, Runtime::RUNTIME, #name, \
15083  FUNCTION_ADDR(Runtime_##name), number_of_args, result_size },
15084 
15085 
15086 #define FH(name, number_of_args, result_size) \
15087  { Runtime::kHidden##name, Runtime::RUNTIME_HIDDEN, NULL, \
15088  FUNCTION_ADDR(RuntimeHidden_##name), number_of_args, result_size },
15089 
15090 
15091 #define I(name, number_of_args, result_size) \
15092  { Runtime::kInline##name, Runtime::INLINE, \
15093  "_" #name, NULL, number_of_args, result_size },
15094 
15095 
15096 #define IO(name, number_of_args, result_size) \
15097  { Runtime::kInlineOptimized##name, Runtime::INLINE_OPTIMIZED, \
15098  "_" #name, FUNCTION_ADDR(Runtime_##name), number_of_args, result_size },
15099 
15100 
15101 static const Runtime::Function kIntrinsicFunctions[] = {
15106 };
15107 
15108 #undef IO
15109 #undef I
15110 #undef FH
15111 #undef F
15112 
15113 
15115  Object* dictionary) {
15116  ASSERT(dictionary != NULL);
15117  ASSERT(NameDictionary::cast(dictionary)->NumberOfElements() == 0);
15118  for (int i = 0; i < kNumFunctions; ++i) {
15119  const char* name = kIntrinsicFunctions[i].name;
15120  if (name == NULL) continue;
15121  Object* name_string;
15122  { MaybeObject* maybe_name_string =
15123  heap->InternalizeUtf8String(name);
15124  if (!maybe_name_string->ToObject(&name_string)) return maybe_name_string;
15125  }
15126  NameDictionary* name_dictionary = NameDictionary::cast(dictionary);
15127  { MaybeObject* maybe_dictionary = name_dictionary->Add(
15128  String::cast(name_string),
15129  Smi::FromInt(i),
15130  PropertyDetails(NONE, NORMAL, Representation::None()));
15131  if (!maybe_dictionary->ToObject(&dictionary)) {
15132  // Non-recoverable failure. Calling code must restart heap
15133  // initialization.
15134  return maybe_dictionary;
15135  }
15136  }
15137  }
15138  return dictionary;
15139 }
15140 
15141 
15143  Heap* heap = name->GetHeap();
15144  int entry = heap->intrinsic_function_names()->FindEntry(*name);
15145  if (entry != kNotFound) {
15146  Object* smi_index = heap->intrinsic_function_names()->ValueAt(entry);
15147  int function_index = Smi::cast(smi_index)->value();
15148  return &(kIntrinsicFunctions[function_index]);
15149  }
15150  return NULL;
15151 }
15152 
15153 
15155  return &(kIntrinsicFunctions[static_cast<int>(id)]);
15156 }
15157 
15158 
15159 void Runtime::PerformGC(Object* result, Isolate* isolate) {
15160  Failure* failure = Failure::cast(result);
15161  if (failure->IsRetryAfterGC()) {
15162  if (isolate->heap()->new_space()->AddFreshPage()) {
15163  return;
15164  }
15165 
15166  // Try to do a garbage collection; ignore it if it fails. The C
15167  // entry stub will throw an out-of-memory exception in that case.
15168  isolate->heap()->CollectGarbage(failure->allocation_space(),
15169  "Runtime::PerformGC");
15170  } else {
15171  // Handle last resort GC and make sure to allow future allocations
15172  // to grow the heap without causing GCs (if possible).
15173  isolate->counters()->gc_last_resort_from_js()->Increment();
15175  "Runtime::PerformGC");
15176  }
15177 }
15178 
15179 
15181  Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true);
15182  UNREACHABLE();
15183 }
15184 
15185 } } // namespace v8::internal
byte * Address
Definition: globals.h:186
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
Object * context() const
Definition: frames-inl.h:183
#define INLINE_FUNCTION_LIST(F)
Definition: runtime.h:643
static Handle< Object > SetElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, PropertyAttributes attributes, StrictMode strict_mode, bool check_prototype=true, SetPropertyMode set_mode=SET_PROPERTY)
Definition: objects.cc:12410
const SwVfpRegister s2
#define CHECK_NOT_EMPTY_HANDLE(isolate, call)
Definition: isolate.h:145
static Handle< Object > New(Handle< JSFunction > func, int argc, Handle< Object > argv[], bool *pending_exception)
Definition: execution.cc:190
STATIC_CHECK((kStringRepresentationMask|kStringEncodingMask)==Internals::kFullStringRepresentationMask)
static const int kMaxLength
Definition: objects.h:3085
static void Destroy(Object **location)
void FlattenString(Handle< String > string)
Definition: handles.cc:151
int fpclassify(double x)
int allow_osr_at_loop_nesting_level()
Definition: objects-inl.h:4442
Handle< JSObject > NewJSObject(Handle< JSFunction > constructor, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:1319
#define CHECK_EQ(expected, value)
Definition: checks.h:252
FixedArray * function_bindings()
Definition: objects-inl.h:5649
static Object *& Object_at(Address addr)
Definition: v8memory.h:83
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property keys(0 means random)" "(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(profile_deserialization
bool IsExternalArrayElementsKind(ElementsKind kind)
Handle< Context > NewModuleContext(Handle< ScopeInfo > scope_info)
Definition: factory.cc:605
#define DATA_VIEW_SETTER(TypeName, Type)
Definition: runtime.cc:1495
int16_t DataViewConvertValue< int16_t >(double value)
Definition: runtime.cc:1454
static Handle< Object > SetPropertyWithCallback(Handle< JSObject > object, Handle< Object > structure, Handle< Name > name, Handle< Object > value, Handle< JSObject > holder, StrictMode strict_mode)
Definition: objects.cc:2874
static const int kNotFound
Definition: runtime.h:790
static icu::DecimalFormat * InitializeNumberFormat(Isolate *isolate, Handle< String > locale, Handle< JSObject > options, Handle< JSObject > resolved)
Definition: i18n.cc:889
ElementsKind GetPackedElementsKind(ElementsKind holey_kind)
int Lookup(Map *map, Name *name)
Definition: heap.cc:7614
#define CONVERT_SMI_ARG_CHECKED(name, index)
Definition: runtime.cc:129
#define RETURN_IF_SCHEDULED_EXCEPTION(isolate)
Definition: isolate.h:120
static const int kGlobalFieldIndex
Definition: objects.h:7972
bool is_hidden_prototype()
Definition: objects.h:5889
void set(int index, Object *value)
Definition: objects-inl.h:2147
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths true
Definition: flags.cc:208
#define CONVERT_DOUBLE_ARG_CHECKED(name, index)
Definition: runtime.cc:136
JSModule * module()
Definition: contexts.h:381
#define ARRAY_ID_CASE(Type, type, TYPE, ctype, size)
void PrintF(const char *format,...)
Definition: v8utils.cc:40
void CollectAllGarbage(int flags, const char *gc_reason=NULL, const GCCallbackFlags gc_callback_flags=kNoGCCallbackFlags)
Definition: heap.cc:731
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf map
Definition: flags.cc:350
bool InNewSpace(Object *object)
Definition: heap-inl.h:307
static Handle< Object > ToNumber(Isolate *isolate, Handle< Object > obj, bool *exc)
Definition: execution.cc:713
static String * cast(Object *obj)
MUST_USE_RESULT MaybeObject * Add(Key key, Object *value, PropertyDetails details)
Definition: objects.cc:15239
Context * previous()
Definition: contexts.h:370
int64_t ToUTC(int64_t time_ms)
Definition: date.h:134
MaybeObject * TryFlatten(PretenureFlag pretenure=NOT_TENURED)
Definition: objects-inl.h:2978
static void DeleteHiddenProperty(Handle< JSObject > object, Handle< Name > key)
Definition: objects.cc:4903
uint32_t NumberToUint32(Object *number)
Definition: v8conversions.h:61
void ClearTypeFeedbackInfo(Heap *heap)
Definition: objects.cc:10590
static void SetObserved(Handle< JSObject > object)
Definition: objects.cc:5611
Object * ToBoolean(bool condition)
Definition: heap-inl.h:759
bool Compile(Handle< String > replacement, int capture_count, int subject_length)
Definition: runtime.cc:3733
Isolate * isolate()
Definition: heap-inl.h:624
double DoubleToInteger(double x)
void ReportFailedAccessCheckWrapper(Handle< JSObject > receiver, v8::AccessType type)
Definition: isolate.h:752
int64_t AdjustAmountOfExternalAllocatedMemory(int64_t change_in_bytes)
Definition: heap-inl.h:582
void set_length(Smi *length)
Definition: objects-inl.h:6628
static Smi * FromInt(int value)
Definition: objects-inl.h:1209
bool IsFastObjectElementsKind(ElementsKind kind)
static Handle< Code > GetUnoptimizedCode(Handle< JSFunction > function)
Definition: compiler.cc:651
v8::Handle< v8::Array > GetKeysForIndexedInterceptor(Handle< JSReceiver > receiver, Handle< JSObject > object)
Definition: handles.cc:452
static const Function * FunctionForName(Handle< String > name)
Definition: runtime.cc:15142
static Handle< Map > Copy(Handle< Map > map)
Definition: objects.cc:6985
uint8_t DataViewConvertValue< uint8_t >(double value)
Definition: runtime.cc:1466
uint64_t double_to_uint64(double d)
Definition: double.h:37
virtual void * AllocateUninitialized(size_t length)=0
static MemoryChunk * FromAddress(Address a)
Definition: spaces.h:305
static Handle< ObjectTemplateInfo > GetTemplate(Isolate *isolate)
Definition: i18n.cc:804
static Handle< JSFunction > GetFunctionFromEval(Handle< String > source, Handle< Context > context, StrictMode strict_mode, ParseRestriction restriction, int scope_position)
Definition: compiler.cc:865
MaybeObject * TransitionElements(Handle< Object > object, ElementsKind to_kind, Isolate *isolate)
Definition: runtime.cc:334
static HeapObject * cast(Object *obj)
static Handle< T > cast(Handle< S > that)
Definition: handles.h:75
double power_helper(double x, double y)
Definition: assembler.cc:1436
bool is_access_check_needed()
Definition: objects-inl.h:4085
static const int kSourceFieldIndex
Definition: objects.h:7971
#define DATA_VIEW_GETTER(TypeName, Type, Converter)
Definition: runtime.cc:1413
void Add(Object *value)
Definition: runtime.cc:3358
static bool Analyze(CompilationInfo *info)
Definition: scopes.cc:278
#define TYPED_ARRAY_GETTER(getter, accessor)
Definition: runtime.cc:1135
const int kSmiValueSize
Definition: v8.h:5540
static AccessorPair * cast(Object *obj)
static const int64_t kMaxTimeBeforeUTCInMs
Definition: date.h:56
static Handle< FixedArray > GetElements(Handle< FixedArray > value)
Definition: parser.cc:3128
double fast_sqrt(double input)
int32_t uc32
Definition: globals.h:310
void RestoreOperandStack(FixedArray *store, int stack_handler_index)
Definition: frames.cc:900
static Handle< Object > CreateRegExpLiteral(Handle< JSFunction > constructor, Handle< String > pattern, Handle< String > flags, bool *has_pending_exception)
Definition: jsregexp.cc:69
static Map * cast(Object *obj)
static bool Parse(Vector< Char > str, FixedArray *output, UnicodeCache *cache)
void SaveOperandStack(FixedArray *store, int *stack_handler_index) const
Definition: frames.cc:867
static icu::DecimalFormat * UnpackNumberFormat(Isolate *isolate, Handle< JSObject > obj)
Definition: i18n.cc:928
static void EnsureCanContainHeapObjectElements(Handle< JSObject > obj)
Definition: objects-inl.h:1590
BailoutType bailout_type() const
Definition: deoptimizer.h:159
static const uint32_t kMaxElementCount
Definition: objects.h:2725
kSerializedDataOffset Object
Definition: objects-inl.h:5016
static Handle< Object > SetPrototype(Handle< JSObject > object, Handle< Object > value, bool skip_hidden_prototypes=false)
Definition: objects.cc:11703
static bool HasRealNamedProperty(Handle< JSObject > object, Handle< Name > key)
Definition: objects.cc:13241
static const int kGeneratorClosed
Definition: objects.h:7321
TypeImpl< ZoneTypeConfig > Type
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage message
Definition: flags.cc:665
int int32_t
Definition: unicode.cc:47
static AllocationSite * cast(Object *obj)
static void DeleteCollator(const v8::WeakCallbackData< v8::Value, void > &data)
Definition: i18n.cc:997
size_t NumberToSize(Isolate *isolate, Object *number)
bool SameValue(Object *other)
Definition: objects.cc:1102
static SeqOneByteString * cast(Object *obj)
WriteBarrierMode GetWriteBarrierMode(const DisallowHeapAllocation &promise)
Definition: objects-inl.h:2350
static Failure * Exception()
Definition: objects-inl.h:1244
static Handle< Object > GetFunctionDelegate(Isolate *isolate, Handle< Object > object)
Definition: execution.cc:238
int Search(Vector< const SubjectChar > subject, int index)
ExternalArrayType type()
Definition: objects.cc:14472
bool MayIndexedAccessWrapper(Handle< JSObject > receiver, uint32_t index, v8::AccessType type)
Definition: isolate.h:747
const int kMaxInt
Definition: globals.h:248
static ScopeInfo * Empty(Isolate *isolate)
Definition: scopeinfo.cc:151
#define CONVERT_STRICT_MODE_ARG_CHECKED(name, index)
Definition: runtime.cc:158
PropertyDescriptorIndices
Definition: runtime.cc:1918
#define RUNTIME_ARGUMENTS(isolate, args)
Definition: arguments.h:314
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage including on console Map counters to a file Enable debugger compile events enable GDBJIT enable GDBJIT interface for all code objects dump only objects containing this substring stress the GC compactor to flush out pretty print source code print source AST function name where to insert a breakpoint print scopes for builtins trace contexts operations print stuff during garbage collection report code statistics after GC report handles after GC trace cache state transitions print interface inference details prints when objects are turned into dictionaries report heap spill statistics along with trace isolate state changes trace regexp bytecode execution Minimal Log all events to the log file Log API events to the log file Log heap samples on garbage collection for the hp2ps tool log positions Log suspect operations Used with turns on browser compatible mode for profiling v8 log
Definition: flags.cc:806
static const Function * FunctionForId(FunctionId id)
Definition: runtime.cc:15154
static Handle< Object > GetPropertyWithCallback(Handle< JSObject > object, Handle< Object > receiver, Handle< Object > structure, Handle< Name > name)
Definition: objects.cc:392
Context * global_context()
Definition: contexts.cc:58
static bool EnsureCompiled(Handle< JSFunction > function, ClearExceptionFlag flag)
Definition: compiler.cc:687
Handle< FixedArray > UnionOfKeys(Handle< FixedArray > first, Handle< FixedArray > second)
Definition: handles.cc:134
BitField< int, 0, kStringBuilderConcatHelperLengthBits > StringBuilderSubstringLength
Definition: runtime.cc:3410
static Handle< Object > SetHiddenProperty(Handle< JSObject > object, Handle< Name > key, Handle< Object > value)
Definition: objects.cc:4861
static Handle< Object > NewDate(Isolate *isolate, double time, bool *exc)
Definition: execution.cc:756
Handle< Object > ArrayConstructInitializeElements(Handle< JSArray > array, Arguments *args)
Definition: elements.cc:1950
#define ASSERT(condition)
Definition: checks.h:329
static void DeoptimizeFunction(JSFunction *function)
Definition: deoptimizer.cc:514
#define ASSERT_GE(v1, v2)
Definition: checks.h:332
virtual void * Allocate(size_t length)=0
Handle< JSArray > ToArray()
Definition: runtime.cc:10060
static void DeleteBreakIterator(const v8::WeakCallbackData< v8::Value, void > &data)
Definition: i18n.cc:1056
static Handle< Object > SetLocalPropertyIgnoreAttributes(Handle< JSObject > object, Handle< Name > key, Handle< Object > value, PropertyAttributes attributes, ValueType value_type=OPTIMAL_REPRESENTATION, StoreMode mode=ALLOW_AS_CONSTANT, ExtensibilityCheck extensibility_check=PERFORM_EXTENSIBILITY_CHECK)
Definition: objects.cc:4141
int IntegerLog2(uint32_t value)
KeyedLookupCache * keyed_lookup_cache()
Definition: isolate.h:888
static Handle< JSObject > DeepCopy(Handle< JSObject > object, AllocationSiteUsageContext *site_context, DeepCopyHints hints=kNoHints)
Definition: objects.cc:5861
void LocalLookup(Name *name, LookupResult *result, bool search_hidden_prototypes=false)
Definition: objects.cc:5956
static Handle< Object > TryGetFunctionDelegate(Isolate *isolate, Handle< Object > object, bool *has_pending_exception)
Definition: execution.cc:265
Handle< JSArray > GetKeysFor(Handle< JSReceiver > object, bool *threw)
Definition: handles.cc:606
static Script * cast(Object *obj)
ExternalArrayType
Definition: v8.h:2113
Handle< JSFunction > function() const
Definition: deoptimizer.h:157
unsigned short uint16_t
Definition: unicode.cc:46
ArrayConcatVisitor(Isolate *isolate, Handle< FixedArray > storage, bool fast_elements)
Definition: runtime.cc:10003
static Context * cast(Object *context)
Definition: contexts.h:244
static SharedFunctionInfo * cast(Object *obj)
static Handle< Object > SetAccessor(Handle< JSObject > object, Handle< AccessorInfo > info)
Definition: objects.cc:6482
static Handle< Object > FunctionSetPrototype(Handle< JSFunction > object, Handle< Object > value)
Definition: accessors.cc:546
void MaterializeHeapObjects(JavaScriptFrameIterator *it)
static v8::ArrayBuffer::Allocator * ArrayBufferAllocator()
Definition: v8.h:106
Object * DataAt(int index)
Definition: objects-inl.h:5986
Handle< Object > NewNumber(double value, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:998
static bool HasHiddenProperties(Handle< JSObject > object)
Definition: objects.cc:4925
#define CHECK(condition)
Definition: checks.h:75
bool IsInternalError() const
Definition: objects-inl.h:1227
FixedArrayBuilder(Handle< FixedArray > backing_store)
Definition: runtime.cc:3328
int isless(double x, double y)
#define IO(name, number_of_args, result_size)
Definition: runtime.cc:15096
static icu::BreakIterator * InitializeBreakIterator(Isolate *isolate, Handle< String > locale, Handle< JSObject > options, Handle< JSObject > resolved)
Definition: i18n.cc:1004
static const int kSize
Definition: objects.h:10099
Handle< Object > GetProperty(Handle< JSReceiver > obj, const char *name)
Definition: handles.cc:196
void set_module(JSModule *module)
Definition: contexts.h:382
#define RETURN_IF_EMPTY_HANDLE(isolate, call)
Definition: isolate.h:151
Factory * factory()
Definition: isolate.h:995
bool IsFastElementsKind(ElementsKind kind)
void Lookup(Name *name, LookupResult *result)
Definition: objects.cc:6002
static void NeuterArrayBuffer(Handle< JSArrayBuffer > array_buffer)
Definition: runtime.cc:820
TypedArraySetResultCodes
Definition: runtime.cc:1167
PropertyAttributes
static const int kInternalFieldCount
Definition: v8.h:2840
OptimizedCompileJob * FindReadyOSRCandidate(Handle< JSFunction > function, BailoutId osr_ast_id)
static Handle< Object > Freeze(Handle< JSObject > object)
Definition: objects.cc:5498
void visit(uint32_t i, Handle< Object > elm)
Definition: runtime.cc:10017
int ComputeParametersCount() const
Definition: frames.h:585
PerThreadAssertScopeDebugOnly< HEAP_ALLOCATION_ASSERT, true > AllowHeapAllocation
Definition: assert-scope.h:218
static void AddStackCheck(Handle< Code > code, uint32_t pc_offset)
#define CALL_HEAP_FUNCTION_PASS_EXCEPTION(ISOLATE, FUNCTION_CALL)
Definition: heap-inl.h:690
static MUST_USE_RESULT MaybeObject * HasObjectProperty(Isolate *isolate, Handle< JSReceiver > object, Handle< Object > key)
Definition: runtime.cc:4964
bool AsArrayIndex(uint32_t *index)
Definition: objects-inl.h:6272
static Symbol * cast(Object *obj)
static MUST_USE_RESULT Handle< String > Truncate(Handle< SeqString > string, int new_length)
Definition: objects.cc:9144
#define RUNTIME_FUNCTION_LIST(F)
Definition: runtime.h:548
Object * GetValue(int descriptor_number)
Definition: objects-inl.h:2646
int ToInt() const
Definition: utils.h:1162
static bool HasElement(Handle< JSReceiver > object, uint32_t index)
Definition: objects-inl.h:6356
static Object ** RawField(HeapObject *obj, int offset)
Definition: objects-inl.h:1199
#define RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, value)
Definition: isolate.h:137
bool MayNamedAccessWrapper(Handle< JSObject > receiver, Handle< Object > key, v8::AccessType type)
Definition: isolate.h:742
static Smi * cast(Object *object)
Handle< String > FlattenGetString(Handle< String > string)
Definition: handles.cc:156
void FindStringIndices(Isolate *isolate, Vector< const SubjectChar > subject, Vector< const PatternChar > pattern, ZoneList< int > *indices, unsigned int limit, Zone *zone)
Definition: runtime.cc:3859
bool Equals(String *other)
Definition: objects-inl.h:2969
static const int kHeaderSize
Definition: objects.h:1891
static MUST_USE_RESULT MaybeObject * InitializeIntrinsicFunctionNames(Heap *heap, Object *dictionary)
Definition: runtime.cc:15114
static const int kMultilineFieldIndex
Definition: objects.h:7974
void set_closure(JSFunction *closure)
Definition: contexts.h:368
kInstanceClassNameOffset flag
Definition: objects-inl.h:5115
static ScopeInfo * cast(Object *object)
static Handle< ObjectHashSet > Add(Handle< ObjectHashSet > table, Handle< Object > key)
Definition: objects.cc:15697
bool contains(byte *pc)
Definition: objects-inl.h:5892
int get(uchar c, uchar n, uchar *result)
Definition: unicode-inl.h:50
int isnan(double x)
static void TransitionElementsKind(Handle< JSObject > object, ElementsKind to_kind)
Definition: objects.cc:12779
static Handle< Object > TryMigrateInstance(Handle< JSObject > instance)
Definition: objects.cc:3866
static const int kInternalFieldCount
Definition: v8.h:2877
#define CONVERT_ARG_CHECKED(Type, name, index)
Definition: runtime.cc:111
GlobalObject * global_object()
Definition: contexts.h:388
static const char * GetVersion()
Definition: api.cc:5120
double StringToDouble(UnicodeCache *unicode_cache, const char *str, int flags, double empty_string_val)
Definition: conversions.cc:47
Object * ValueAt(int entry)
Definition: objects.h:3930
const int kStringBuilderConcatHelperPositionBits
Definition: runtime.cc:3401
Object * InObjectPropertyAtPut(int index, Object *value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
Definition: objects-inl.h:2002
uint64_t ObjectPair
Definition: runtime.cc:9288
static void SetContent(Handle< JSArray > array, Handle< FixedArrayBase > storage)
Definition: objects-inl.h:6641
Handle< SeededNumberDictionary > DictionaryAtNumberPut(Handle< SeededNumberDictionary >, uint32_t key, Handle< Object > value)
Definition: factory.cc:1631
Object * receiver() const
Definition: frames-inl.h:269
static Handle< Code > GetConcurrentlyOptimizedCode(OptimizedCompileJob *job)
Definition: compiler.cc:1204
static MUST_USE_RESULT MaybeObject * DeleteObjectProperty(Isolate *isolate, Handle< JSReceiver > object, Handle< Object > key, JSReceiver::DeleteMode mode)
Definition: runtime.cc:5442
double fast_exp(double input)
static void DefineAccessor(Handle< JSObject > object, Handle< Name > name, Handle< Object > getter, Handle< Object > setter, PropertyAttributes attributes, v8::AccessControl access_control=v8::DEFAULT)
Definition: objects.cc:6288
V8_INLINE bool IsNull() const
Definition: v8.h:6247
static icu::SimpleDateFormat * InitializeDateTimeFormat(Isolate *isolate, Handle< String > locale, Handle< JSObject > options, Handle< JSObject > resolved)
Definition: i18n.cc:816
static Handle< Object > CharAt(Handle< String > str, uint32_t index)
Definition: execution.cc:777
static bool CopyContextLocalsToScopeObject(Handle< ScopeInfo > scope_info, Handle< Context > context, Handle< JSObject > scope_object)
Definition: scopeinfo.cc:364
Handle< Object > Lookup(Handle< String > name, ContextLookupFlags flags, int *index, PropertyAttributes *attributes, BindingFlags *binding_flags)
Definition: contexts.cc:97
static JSGeneratorObject * cast(Object *obj)
Definition: objects-inl.h:5737
Handle< Code > compiled_code() const
Definition: deoptimizer.h:158
static icu::SimpleDateFormat * UnpackDateFormat(Isolate *isolate, Handle< JSObject > obj)
Definition: i18n.cc:854
static void Abort()
static const int kLiteralNativeContextIndex
Definition: objects.h:7531
#define UNREACHABLE()
Definition: checks.h:52
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction pairs(ARM only)") DEFINE_bool(enable_unaligned_accesses
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_string(expose_natives_as
Handle< JSArray > ToJSArray(Handle< JSArray > target_array)
Definition: runtime.cc:3385
static Handle< ObjectTemplateInfo > GetTemplate2(Isolate *isolate)
Definition: i18n.cc:810
double StringToInt(UnicodeCache *unicode_cache, String *str, int radix)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object size
Definition: flags.cc:211
T * start() const
Definition: utils.h:426
void set_global_object(GlobalObject *object)
Definition: contexts.h:393
Handle< SeqTwoByteString > NewRawTwoByteString(int length, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:300
static SeededNumberDictionary * cast(Object *obj)
Definition: objects.h:4104
void Apply(ReplacementStringBuilder *builder, int match_from, int match_to, int32_t *match)
Definition: runtime.cc:3781
bool IsConstructor() const
Definition: frames.cc:747
STATIC_ASSERT(sizeof(CPURegister)==sizeof(Register))
static icu::Collator * UnpackCollator(Isolate *isolate, Handle< JSObject > obj)
Definition: i18n.cc:985
static const int kInputIndex
Definition: objects.h:10102
Handle< String > NewSubString(Handle< String > str, int begin, int end)
Definition: factory.h:183
#define MUST_USE_RESULT
Definition: globals.h:381
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage including flags
Definition: flags.cc:665
bool IsSymbol() const
Definition: api.cc:2369
#define CONVERT_BOOLEAN_ARG_CHECKED(name, index)
Definition: runtime.cc:122
virtual void Free(void *data, size_t length)=0
static LiteralType GetLiteralType(Handle< FixedArray > value)
Definition: parser.cc:3121
static ThreadId Current()
Definition: isolate.h:170
MUST_USE_RESULT MaybeObject * AsElementsKind(ElementsKind kind)
Definition: objects.cc:3360
Context * native_context()
Definition: contexts.cc:67
int FastD2IChecked(double x)
Definition: conversions.h:63
Local< Value > GetPrototype()
Definition: api.cc:3192
static MUST_USE_RESULT MaybeObject * HandleStackGuardInterrupt(Isolate *isolate)
Definition: execution.cc:1006
Handle< Object > Create(Object *value)
bool CodeGenerationFromStringsAllowed(Isolate *isolate, Handle< Context > context)
Definition: runtime.cc:9820
static bool IsValidElementsTransition(ElementsKind from_kind, ElementsKind to_kind)
Definition: objects.cc:12848
static bool IsValid(intptr_t value)
Definition: objects-inl.h:1278
static Failure * cast(MaybeObject *object)
Definition: objects-inl.h:667
static void DeleteDateFormat(const v8::WeakCallbackData< v8::Value, void > &data)
Definition: i18n.cc:882
bool ToArrayIndex(uint32_t *index)
Definition: objects-inl.h:2072
bool(* AllowCodeGenerationFromStringsCallback)(Local< Context > context)
Definition: v8.h:4056
static const int kNoGCFlags
Definition: heap.h:1257
static Handle< Map > GetElementsTransitionMap(Handle< JSObject > object, ElementsKind to_kind)
Definition: objects.cc:3313
static void PrintTop(Isolate *isolate, FILE *file, bool print_args, bool print_line_number)
Definition: frames.cc:804
const int kPointerSize
Definition: globals.h:268
static void AddSubjectSlice(FixedArrayBuilder *builder, int from, int to)
Definition: runtime.cc:3432
bool TryNumberToSize(Isolate *isolate, Object *number, size_t *result)
Definition: v8conversions.h:76
void check(i::Vector< const uint8_t > string)
static ModuleInfo * cast(Object *description)
Definition: scopeinfo.h:141
Handle< Object > NewTypeError(const char *message, Vector< Handle< Object > > args)
Definition: factory.cc:1039
T * NewArray(size_t size)
Definition: allocation.h:83
Handle< String > StringReplaceOneCharWithString(Isolate *isolate, Handle< String > subject, Handle< String > search, Handle< String > replace, bool *found, int recursion_limit)
Definition: runtime.cc:4270
static const int kMaxWidth
Definition: unicode.h:253
void lazily_initialize_fast_exp()
static Handle< JSArray > SetLastMatchInfo(Handle< JSArray > last_match_info, Handle< String > subject, int capture_count, int32_t *match)
Definition: jsregexp.cc:688
static void PerformGC(Object *result, Isolate *isolate)
Definition: runtime.cc:15159
const char * DoubleToCString(double v, Vector< char > buffer)
Definition: conversions.cc:81
intptr_t OffsetFrom(T x)
Definition: utils.h:120
int ComputeOperandsCount() const
Definition: frames-inl.h:257
static Handle< Object > GetPropertyWithInterceptor(Handle< JSObject > object, Handle< Object > receiver, Handle< Name > name, PropertyAttributes *attributes)
Definition: objects.cc:13205
bool IsAligned(T value, U alignment)
Definition: utils.h:211
Object * GetPrototype(Isolate *isolate)
Definition: objects.cc:1032
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName)
Definition: globals.h:370
static Handle< Object > ForceSetObjectProperty(Isolate *isolate, Handle< JSObject > object, Handle< Object > key, Handle< Object > value, PropertyAttributes attr)
Definition: runtime.cc:5387
Object * RawFastPropertyAt(int index)
Definition: objects-inl.h:1964
static const int64_t kMaxTimeInMs
Definition: date.h:51
double power_double_double(double x, double y)
Definition: assembler.cc:1471
static Handle< ObjectHashSet > Remove(Handle< ObjectHashSet > table, Handle< Object > key)
Definition: objects.cc:15720
static Handle< Code > GetOptimizedCode(Handle< JSFunction > function, Handle< Code > current_code, ConcurrencyMode mode, BailoutId osr_ast_id=BailoutId::None())
Definition: compiler.cc:1162
GlobalHandles * global_handles()
Definition: isolate.h:918
Handle< JSValue > GetScriptWrapper(Handle< Script > script)
Definition: handles.cc:240
bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, ElementsKind to_kind)
AllocationSpace allocation_space() const
Definition: objects-inl.h:1232
void increase_index_offset(uint32_t delta)
Definition: runtime.cc:10048
static void TransformToFastProperties(Handle< JSObject > object, int unused_property_fields)
Definition: objects.cc:4663
const uintptr_t kUintptrAllBitsSet
Definition: globals.h:283
static const int kMaxRegularHeapObjectSize
Definition: spaces.h:820
bool IsNone() const
Definition: utils.h:1170
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
static void Enter(Heap *heap, String *key_string, Object *key_pattern, FixedArray *value_array, ResultsCacheType type)
Definition: heap.cc:3477
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: globals.h:359
double uint64_to_double(uint64_t d64)
Definition: double.h:38
const Register pc
static Handle< Object > Exec(Handle< JSRegExp > regexp, Handle< String > subject, int index, Handle< JSArray > lastMatchInfo)
Definition: jsregexp.cc:234
Vector< const uc16 > ToUC16Vector()
Definition: objects.h:8757
static PropertyAttributes GetPropertyAttribute(Handle< JSReceiver > object, Handle< Name > name)
Definition: objects-inl.h:6311
double modulo(double x, double y)
double DataViewConvertValue< double >(double value)
Definition: runtime.cc:1490
static JSTypedArray * cast(Object *obj)
int length() const
Definition: utils.h:420
void EnsureCapacity(int elements)
Definition: runtime.cc:3343
Handle< FixedArray > GetKeysInFixedArrayFor(Handle< JSReceiver > object, KeyCollectionType type, bool *threw)
Definition: handles.cc:505
static double TimeCurrentMillis()
static FixedDoubleArray * cast(Object *obj)
static NameDictionary * cast(Object *obj)
Definition: objects.h:4049
ElementsKind GetElementsKind()
Definition: objects.h:8360
static Handle< Object > TryGetConstructorDelegate(Isolate *isolate, Handle< Object > object, bool *has_pending_exception)
Definition: execution.cc:322
static Handle< Object > SetOwnElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, StrictMode strict_mode)
Definition: objects.cc:12401
bool IsFastSmiElementsKind(ElementsKind kind)
static const int kMakeHeapIterableMask
Definition: heap.h:1264
static const int kIgnoreCaseFieldIndex
Definition: objects.h:7973
double power_double_int(double x, int y)
Definition: assembler.cc:1456
AccessType
Definition: v8.h:3395
MUST_USE_RESULT MaybeObject * FastPropertyAt(Representation representation, int index)
Definition: objects-inl.h:1954
static Handle< Object > GetElementOrCharAt(Isolate *isolate, Handle< Object > object, uint32_t index)
Definition: runtime.cc:4924
int8_t DataViewConvertValue< int8_t >(double value)
Definition: runtime.cc:1448
static void FatalProcessOutOfMemory(const char *location, bool take_snapshot=false)
Definition: heap.cc:6887
int CompareChars(const lchar *lhs, const rchar *rhs, int chars)
Definition: utils.h:852
PropertyDetails GetDetails(int descriptor_number)
Definition: objects-inl.h:2652
static PropertyCell * cast(Object *obj)
Failure * Throw(Object *exception, MessageLocation *location=NULL)
Definition: isolate.cc:923
uint32_t DataViewConvertValue< uint32_t >(double value)
Definition: runtime.cc:1478
#define RUNTIME_UNARY_MATH(NAME)
Definition: runtime.cc:7764
#define STATIC_ASCII_VECTOR(x)
Definition: utils.h:570
static void DebugBreak()
static ExternalUint8ClampedArray * cast(Object *obj)
V8_INLINE bool IsUndefined() const
Definition: v8.h:6229
static const int kSize
Definition: objects.h:9807
int isinf(double x)
double get_scalar(int index)
Definition: objects-inl.h:2173
static v8::internal::Handle< To > OpenHandle(v8::Local< From > handle)
Definition: api.h:308
unibrow::Mapping< unibrow::ToUppercase, 128 > * to_upper_mapping()
Definition: runtime.h:710
static void Fix(Handle< JSProxy > proxy)
Definition: objects.cc:3776
static uint32_t MakeArrayIndexHash(uint32_t value, int length)
Definition: objects.cc:9183
static Object * Lookup(Heap *heap, String *key_string, Object *key_pattern, ResultsCacheType type)
Definition: heap.cc:3444
Handle< FixedArray > CopyFixedArray(Handle< FixedArray > array)
Definition: factory.cc:886
static void Sleep(const int milliseconds)
Vector< const char > CStrVector(const char *data)
Definition: utils.h:574
bool CollectGarbage(AllocationSpace space, const char *gc_reason=NULL, const GCCallbackFlags gc_callback_flags=kNoGCCallbackFlags)
Definition: heap-inl.h:554
MUST_USE_RESULT MaybeObject * GetProperty(Name *key)
Definition: objects-inl.h:1081
void VisitThread(Isolate *isolate, ThreadLocalTop *top)
Definition: runtime.cc:8534
int StrLength(const char *string)
Definition: utils.h:253
static Local< Context > ToLocal(v8::internal::Handle< v8::internal::Context > obj)
ReplacementStringBuilder(Heap *heap, Handle< String > subject, int estimated_part_count)
Definition: runtime.cc:3419
static JSArray * cast(Object *obj)
#define T(name, string, precedence)
Definition: token.cc:48
ContextLookupFlags
Definition: contexts.h:38
#define ASSERT_LT(v1, v2)
Definition: checks.h:333
Context * context()
Definition: isolate.h:557
static const int kMaxLoopNestingMarker
Definition: objects.h:5578
static bool HasProperty(Handle< JSReceiver > object, Handle< Name > name)
Definition: objects-inl.h:6291
bool IsFastSmiOrObjectElementsKind(ElementsKind kind)
void FindStringIndicesDispatch(Isolate *isolate, String *subject, String *pattern, ZoneList< int > *indices, unsigned int limit, Zone *zone)
Definition: runtime.cc:3881
V8_INLINE bool IsString() const
Definition: v8.h:6265
static int StringMatch(Isolate *isolate, Handle< String > sub, Handle< String > pat, int index)
Definition: runtime.cc:4347
static Handle< Object > SetFastElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, StrictMode strict_mode, bool check_prototype)
Definition: objects.cc:12018
const SwVfpRegister s1
static SeqTwoByteString * cast(Object *obj)
static Handle< AccessorInfo > MakeModuleExport(Handle< String > name, int index, PropertyAttributes attributes)
Definition: accessors.cc:952
#define RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, T)
Definition: isolate.h:128
void Lookup(Name *name, LookupResult *result)
Definition: objects.cc:135
void ExitScope(Handle< AllocationSite > scope_site, Handle< JSObject > object)
FlatContent GetFlatContent()
Definition: objects.cc:8229
int ArithmeticShiftRight(int x, int s)
Definition: utils.h:111
void set(int index, double value)
Definition: objects-inl.h:2207
void SetElementsKind(ElementsKind kind)
Definition: objects.h:8366
static JSDataView * cast(Object *obj)
static Handle< Object > FunctionGetArguments(Handle< JSFunction > object)
Definition: accessors.cc:687
void Update(Map *map, Name *name, int field_offset)
Definition: heap.cc:7626
uint32_t DoubleToUint32(double x)
Definition: conversions.h:106
bool AsArrayIndex(uint32_t *index)
Definition: objects-inl.h:6267
bool has_named_interceptor()
Definition: objects.h:5898
char * DoubleToPrecisionCString(double value, int p)
Definition: conversions.cc:305
int32_t DoubleToInt32(double x)
uint16_t DataViewConvertValue< uint16_t >(double value)
Definition: runtime.cc:1472
static HeapNumber * cast(Object *obj)
static icu::BreakIterator * UnpackBreakIterator(Isolate *isolate, Handle< JSObject > obj)
Definition: i18n.cc:1044
static void EnqueueChangeRecord(Handle< JSObject > object, const char *type, Handle< Name > name, Handle< Object > old_value)
Definition: objects.cc:2184
static void WriteToFlat(String *source, sinkchar *sink, int from, int to)
Definition: objects.cc:8635
NameDictionary * property_dictionary()
Definition: objects-inl.h:6142
const int kStringBuilderConcatHelperLengthBits
Definition: runtime.cc:3400
#define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, s)
Definition: runtime.cc:14780
void FindAsciiStringIndices(Vector< const uint8_t > subject, char pattern, ZoneList< int > *indices, unsigned int limit, Zone *zone)
Definition: runtime.cc:3819
const char * GetBailoutReason(BailoutReason reason)
Definition: objects.cc:16437
bool IsWhiteSpaceOrLineTerminator(unibrow::uchar c)
Definition: scanner.h:145
v8::Handle< v8::Array > GetKeysForNamedInterceptor(Handle< JSReceiver > receiver, Handle< JSObject > object)
Definition: handles.cc:429
static double nan_value()
static Handle< Object > GetElementWithInterceptor(Handle< JSObject > object, Handle< Object > receiver, uint32_t index)
Definition: objects.cc:12887
static ObjectHashTable * cast(Object *obj)
Definition: objects.h:4226
static Handle< Object > Call(Isolate *isolate, Handle< Object > callable, Handle< Object > receiver, int argc, Handle< Object > argv[], bool *pending_exception, bool convert_receiver=false)
Definition: execution.cc:153
static Handle< Object > SetProperty(Handle< JSReceiver > object, Handle< Name > key, Handle< Object > value, PropertyAttributes attributes, StrictMode strict_mode, StoreFromKeyed store_mode=MAY_BE_STORE_FROM_KEYED)
Definition: objects.cc:2858
bool is_null() const
Definition: handles.h:81
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:103
V8_INLINE bool IsEmpty() const
Definition: v8.h:248
static void SetNormalizedProperty(Handle< JSObject > object, const LookupResult *result, Handle< Object > value)
Definition: objects.cc:691
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function info
Definition: flags.cc:317
int32_t DataViewConvertValue< int32_t >(double value)
Definition: runtime.cc:1460
#define RUNTIME_ASSERT(value)
Definition: runtime.cc:105
bool IsNumber() const
Definition: api.cc:2416
Handle< String > LookupSingleCharacterStringFromCode(Isolate *isolate, uint32_t index)
Definition: handles.cc:212
static const int kAtomPatternIndex
Definition: objects.h:7932
void AddSubjectSlice(int from, int to)
Definition: runtime.cc:3456
static void Revert(Isolate *isolate, Code *unoptimized_code)
static Object * cast(Object *value)
Definition: objects.h:1641
static Deoptimizer * Grab(Isolate *isolate)
Definition: deoptimizer.cc:138
uint16_t uc16
Definition: globals.h:309
static bool IsUpperCaseChar(RuntimeState *runtime_state, uint16_t ch)
Definition: runtime.cc:6913
void set_extension(Object *object)
Definition: contexts.h:379
PropertyDetails DetailsAt(int entry)
Definition: objects.h:3940
static Handle< Object > CreateArrayLiteralBoilerplate(Isolate *isolate, Handle< FixedArray > literals, Handle< FixedArray > elements)
Definition: runtime.cc:352
void VisitFrames(JavaScriptFrameIterator *it)
Definition: runtime.cc:8539
static icu::Collator * InitializeCollator(Isolate *isolate, Handle< String > locale, Handle< JSObject > options, Handle< JSObject > resolved)
Definition: i18n.cc:948
static MUST_USE_RESULT MaybeObject * GetObjectPropertyOrFail(Isolate *isolate, Handle< Object > object, Handle< Object > key)
Definition: runtime.cc:4982
static Handle< Object > GetConstructorDelegate(Isolate *isolate, Handle< Object > object)
Definition: execution.cc:296
static void MakeWeak(Object **location, void *parameter, WeakCallback weak_callback)
static JSReceiver * cast(Object *obj)
static JSValue * cast(Object *obj)
Definition: objects-inl.h:5758
void CopyBytes(uint8_t *target, uint8_t *source)
Definition: runtime.cc:1309
bool IsFunctionContext()
Definition: contexts.h:417
Handle< JSModule > NewJSModule(Handle< Context > context, Handle< ScopeInfo > scope_info)
Definition: factory.cc:1339
void ShortPrint(FILE *out=stdout)
Definition: objects.cc:1123
void AddString(Handle< String > string)
Definition: runtime.cc:3462
static AllocationSiteMode GetMode(ElementsKind boilerplate_elements_kind)
Definition: objects-inl.h:1477
static void PrintError(const char *format,...)
static void SetupArrayBuffer(Isolate *isolate, Handle< JSArrayBuffer > array_buffer, bool is_external, void *data, size_t allocated_length)
Definition: runtime.cc:768
static Handle< SeededNumberDictionary > NormalizeElements(Handle< JSObject > object)
Definition: objects.cc:4704
bool is_observed()
Definition: objects.h:5930
#define TYPED_ARRAYS(V)
Definition: objects.h:4663
static Handle< T > null()
Definition: handles.h:80
bool is_undetectable()
Definition: objects.h:5921
void ExitScope(Handle< AllocationSite > site, Handle< JSObject > object)
Handle< SeqOneByteString > NewRawOneByteString(int length, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:291
void MemsetPointer(T **dest, U *value, int counter)
Definition: v8utils.h:198
#define RUNTIME_HIDDEN_FUNCTION_LIST(F)
Definition: runtime.h:558
void FlipBytes(uint8_t *target, uint8_t *source)
Definition: runtime.cc:1317
int SearchString(Isolate *isolate, Vector< const SubjectChar > subject, Vector< const PatternChar > pattern, int start_index)
static const int kGeneratorExecuting
Definition: objects.h:7320
void set_is_access_check_needed(bool access_check_needed)
Definition: objects-inl.h:4076
static MUST_USE_RESULT MaybeObject * GetObjectProperty(Isolate *isolate, Handle< Object > object, Handle< Object > key)
Definition: runtime.cc:4990
#define ASSERT_EQ(v1, v2)
Definition: checks.h:330
static const int kIndexIndex
Definition: objects.h:10101
Object * extension()
Definition: contexts.h:378
static PropertyAttributes GetLocalPropertyAttribute(Handle< JSReceiver > object, Handle< Name > name)
Definition: objects.cc:4384
InstanceType instance_type()
Definition: objects-inl.h:4012
#define CONVERT_ARG_HANDLE_CHECKED(Type, name, index)
Definition: runtime.cc:115
static Handle< Object > SetPropertyForResult(Handle< JSObject > object, LookupResult *result, Handle< Name > name, Handle< Object > value, PropertyAttributes attributes, StrictMode strict_mode, StoreFromKeyed store_mode=MAY_BE_STORE_FROM_KEYED)
Definition: objects.cc:4004
void USE(T)
Definition: globals.h:341
int32_t NumberToInt32(Object *number)
Definition: v8conversions.h:55
Counters * counters()
Definition: isolate.h:859
static Handle< JSObject > InstantiateObject(Handle< ObjectTemplateInfo > data, bool *exc)
Definition: execution.cc:832
#define ASSERT_NE(v1, v2)
Definition: checks.h:331
PerThreadAssertScopeDebugOnly< HEAP_ALLOCATION_ASSERT, false > DisallowHeapAllocation
Definition: assert-scope.h:214
static AccessorInfo * cast(Object *obj)
static FixedArray * cast(Object *obj)
void FindTwoByteStringIndices(const Vector< const uc16 > subject, uc16 pattern, ZoneList< int > *indices, unsigned int limit, Zone *zone)
Definition: runtime.cc:3841
MUST_USE_RESULT MaybeObject * InternalizeUtf8String(const char *str)
Definition: heap.h:1222
static const int kHeaderSize
Definition: objects.h:2757
static bool SetupArrayBufferAllocatingData(Isolate *isolate, Handle< JSArrayBuffer > array_buffer, size_t allocated_length, bool initialize=true)
Definition: runtime.cc:793
#define ASSERT_OBJECT_SIZE(size)
Definition: spaces.h:105
Handle< FixedDoubleArray > CopyFixedDoubleArray(Handle< FixedDoubleArray > array)
Definition: factory.cc:909
ElementsKind elements_kind()
Definition: objects.h:5945
void set_previous(Context *context)
Definition: contexts.h:375
static const int kBoundFunctionIndex
Definition: objects.h:7534
Failure * ThrowIllegalOperation()
Definition: isolate.cc:944
static Handle< Object > SetObjectProperty(Isolate *isolate, Handle< Object > object, Handle< Object > key, Handle< Object > value, PropertyAttributes attr, StrictMode strict_mode)
Definition: runtime.cc:5283
static Handle< Object > PreventExtensions(Handle< JSObject > object)
Definition: objects.cc:5420
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:39
bool HasCapacity(int elements)
Definition: runtime.cc:3337
static Handle< ObjectHashTable > Put(Handle< ObjectHashTable > table, Handle< Object > key, Handle< Object > value)
Definition: objects.cc:15775
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)
double FastI2D(int x)
Definition: conversions.h:81
static Handle< Object > DeleteElement(Handle< JSReceiver > object, uint32_t index, DeleteMode mode=NORMAL_DELETION)
Definition: objects.cc:5262
static void NormalizeProperties(Handle< JSObject > object, PropertyNormalizationMode mode, int expected_additional_properties)
Definition: objects.cc:4560
Object * get(int index)
Definition: objects-inl.h:2127
Handle< Object > ErrorMessageForCodeGenerationFromStrings()
Definition: contexts.cc:367
bool IsFastHoleyElementsKind(ElementsKind kind)
static Handle< Object > GetElement(Isolate *isolate, Handle< Object > object, uint32_t index)
Definition: objects-inl.h:1060
Handle< FixedArray > array()
Definition: runtime.cc:3373
static const int kMaxLength
Definition: objects.h:3174
Local< Object > ToObject() const
Definition: api.cc:2570
HeapObject * obj
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric literals(0o77, 0b11)") DEFINE_bool(harmony_strings
Handle< Object > ForceSetProperty(Handle< JSObject > object, Handle< Object > key, Handle< Object > value, PropertyAttributes attributes)
Definition: handles.cc:161
Object * array_buffers_list()
Definition: heap.h:1359
char * DoubleToExponentialCString(double value, int f)
Definition: conversions.cc:260
static Name * cast(Object *obj)
static JSArrayBuffer * cast(Object *obj)
BitField< int, kStringBuilderConcatHelperLengthBits, kStringBuilderConcatHelperPositionBits > StringBuilderSubstringPosition
Definition: runtime.cc:3414
static Representation None()
Handle< String > NewConsString(Handle< String > left, Handle< String > right)
Definition: factory.cc:370
static const int kMaxLength
Definition: objects.h:8922
JSFunction * closure()
Definition: contexts.h:367
bool IsImmutableVariableMode(VariableMode mode)
Definition: v8globals.h:513
static Handle< Object > Compile(Handle< JSRegExp > re, Handle< String > pattern, Handle< String > flags)
Definition: jsregexp.cc:171
Handle< Object > NewNumberFromSize(size_t value, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.h:623
Vector< Handle< Object > > HandleVector(v8::internal::Handle< T > *elms, int length)
Definition: v8utils.h:118
char * DoubleToRadixCString(double value, int radix)
Definition: conversions.cc:375
AccessorPair * GetLocalPropertyAccessorPair(Name *name)
Definition: objects.cc:11809
#define FH(name, number_of_args, result_size)
Definition: runtime.cc:15086
uint32_t hash_field()
Definition: objects-inl.h:2941
static Handle< Object > DeleteProperty(Handle< JSReceiver > object, Handle< Name > name, DeleteMode mode=NORMAL_DELETION)
Definition: objects.cc:5273
static const int kLastIndexFieldIndex
Definition: objects.h:7975
static const int kBoundThisIndex
Definition: objects.h:7535
Vector< const uint8_t > ToOneByteVector()
Definition: objects.h:8751
void DeleteArray(T *array)
Definition: allocation.h:91
T Min(T a, T b)
Definition: utils.h:234
void Flush(FILE *out)
Definition: v8utils.cc:65
signed short int16_t
Definition: unicode.cc:45
static void RunMicrotasks(Isolate *isolate)
Definition: execution.cc:357
static ConsString * cast(Object *obj)
static void DeleteNumberFormat(const v8::WeakCallbackData< v8::Value, void > &data)
Definition: i18n.cc:941
static FixedArrayBase * cast(Object *object)
Definition: objects-inl.h:2121
#define CONVERT_NUMBER_CHECKED(type, name, Type, obj)
Definition: runtime.cc:143
static Context * NativeContextFromLiterals(FixedArray *literals)
Definition: objects.cc:9845
float DataViewConvertValue< float >(double value)
Definition: runtime.cc:1484
void set_array_buffers_list(Object *object)
Definition: heap.h:1356
static const int kInitialMaxFastElementArray
Definition: objects.h:2744
#define CONVERT_PROPERTY_DETAILS_CHECKED(name, index)
Definition: runtime.cc:151
static void ArrayIdToTypeAndSize(int array_id, ExternalArrayType *type, ElementsKind *external_elements_kind, ElementsKind *fixed_elements_kind, size_t *element_size)
Definition: runtime.cc:928
static Handle< Object > GetAccessor(Handle< JSObject > object, Handle< Name > name, AccessorComponent component)
Definition: objects.cc:6565
static const int kMaxValue
Definition: objects.h:1681
static Handle< Object > PrepareElementsForSort(Handle< JSObject > object, uint32_t limit)
Definition: objects.cc:14342
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in name
Definition: flags.cc:505
static const int kBoundArgumentsStartIndex
Definition: objects.h:7536
static const int kNotFound
Definition: objects.h:3486
NewSpace * new_space()
Definition: heap.h:637
static Handle< Object > ToString(Isolate *isolate, Handle< Object > obj, bool *exc)
Definition: execution.cc:719
MUST_USE_RESULT MaybeObject * CopyReplaceDescriptor(DescriptorArray *descriptors, Descriptor *descriptor, int index, TransitionFlag flag)
Definition: objects.cc:7108
#define ARRAY_SIZE(a)
Definition: globals.h:333
ElementsKind GetHoleyElementsKind(ElementsKind packed_kind)
static const int32_t kMaxOneByteCharCode
Definition: objects.h:8914
Object * GetParameter(int index) const
Definition: frames-inl.h:236
static JSArrayBufferView * cast(Object *obj)
#define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name)
Definition: runtime.cc:14749
void set_hash_field(uint32_t value)
Definition: objects-inl.h:2946
void set_allow_osr_at_loop_nesting_level(int level)
Definition: objects-inl.h:4448
#define TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, size)
Definition: runtime.cc:14769
static void OutOfMemory()
Definition: runtime.cc:15180
static ObjectHashSet * cast(Object *obj)
Definition: objects.h:4194
static JSObject * cast(Object *obj)
void ClearInlineCaches()
Definition: objects.cc:10563
static const int kMaxArrayIndexSize
Definition: objects.h:8910
JSFunction * function() const
Definition: frames-inl.h:284
unsigned int uchar
Definition: unicode.h:40
bool IsQueuedForOSR(Handle< JSFunction > function, BailoutId osr_ast_id)
Handle< JSArray > NewJSArray(ElementsKind elements_kind, int length, int capacity, ArrayStorageAllocationMode mode=INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:1437
int FastD2I(double x)
Definition: conversions.h:74
Local< Uint32 > ToArrayIndex() const
Definition: api.cc:2901
bool IsFastDoubleElementsKind(ElementsKind kind)
static void FreeArrayBuffer(Isolate *isolate, JSArrayBuffer *phantom_array_buffer)
Definition: runtime.cc:748
char * DoubleToFixedCString(double value, int f)
Definition: conversions.cc:156
static Handle< JSObject > DeepWalk(Handle< JSObject > object, AllocationSiteCreationContext *site_context)
Definition: objects.cc:5850
Handle< SeededNumberDictionary > NewSeededNumberDictionary(int at_least_space_for)
Definition: factory.cc:116
static DeoptimizationInputData * cast(Object *obj)
FixedArrayBuilder(Isolate *isolate, int initial_capacity)
Definition: runtime.cc:3319
#define INLINE_OPTIMIZED_FUNCTION_LIST(F)
Definition: runtime.h:692
static bool HasLocalProperty(Handle< JSReceiver >, Handle< Name > name)
Definition: objects-inl.h:6301
static JSGlobalObject * cast(Object *obj)
static JSFunction * cast(Object *obj)