PageRenderTime 74ms CodeModel.GetById 38ms RepoModel.GetById 0ms app.codeStats 3ms

/deps/v8/src/runtime.cc

http://github.com/joyent/node
C++ | 14385 lines | 10694 code | 2137 blank | 1554 comment | 2149 complexity | 6eb8f07386c56851f7b612a3c3f30c3e MD5 | raw file
Possible License(s): 0BSD, BSD-3-Clause, MPL-2.0-no-copyleft-exception, GPL-2.0, ISC, Apache-2.0, MIT, AGPL-3.0
  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. #include <stdlib.h>
  28. #include <limits>
  29. #include "v8.h"
  30. #include "accessors.h"
  31. #include "api.h"
  32. #include "arguments.h"
  33. #include "bootstrapper.h"
  34. #include "codegen.h"
  35. #include "compilation-cache.h"
  36. #include "compiler.h"
  37. #include "cpu.h"
  38. #include "cpu-profiler.h"
  39. #include "dateparser-inl.h"
  40. #include "debug.h"
  41. #include "deoptimizer.h"
  42. #include "date.h"
  43. #include "execution.h"
  44. #include "full-codegen.h"
  45. #include "global-handles.h"
  46. #include "isolate-inl.h"
  47. #include "jsregexp.h"
  48. #include "jsregexp-inl.h"
  49. #include "json-parser.h"
  50. #include "json-stringifier.h"
  51. #include "liveedit.h"
  52. #include "misc-intrinsics.h"
  53. #include "parser.h"
  54. #include "platform.h"
  55. #include "runtime-profiler.h"
  56. #include "runtime.h"
  57. #include "scopeinfo.h"
  58. #include "smart-pointers.h"
  59. #include "string-search.h"
  60. #include "stub-cache.h"
  61. #include "uri.h"
  62. #include "v8conversions.h"
  63. #include "v8threads.h"
  64. #include "vm-state-inl.h"
  65. #ifdef V8_I18N_SUPPORT
  66. #include "i18n.h"
  67. #include "unicode/brkiter.h"
  68. #include "unicode/calendar.h"
  69. #include "unicode/coll.h"
  70. #include "unicode/curramt.h"
  71. #include "unicode/datefmt.h"
  72. #include "unicode/dcfmtsym.h"
  73. #include "unicode/decimfmt.h"
  74. #include "unicode/dtfmtsym.h"
  75. #include "unicode/dtptngen.h"
  76. #include "unicode/locid.h"
  77. #include "unicode/numfmt.h"
  78. #include "unicode/numsys.h"
  79. #include "unicode/smpdtfmt.h"
  80. #include "unicode/timezone.h"
  81. #include "unicode/uchar.h"
  82. #include "unicode/ucol.h"
  83. #include "unicode/ucurr.h"
  84. #include "unicode/uloc.h"
  85. #include "unicode/unum.h"
  86. #include "unicode/uversion.h"
  87. #endif
  88. #ifndef _STLP_VENDOR_CSTD
  89. // STLPort doesn't import fpclassify and isless into the std namespace.
  90. using std::fpclassify;
  91. using std::isless;
  92. #endif
  93. namespace v8 {
  94. namespace internal {
  95. #define RUNTIME_ASSERT(value) \
  96. if (!(value)) return isolate->ThrowIllegalOperation();
  97. // Cast the given object to a value of the specified type and store
  98. // it in a variable with the given name. If the object is not of the
  99. // expected type call IllegalOperation and return.
  100. #define CONVERT_ARG_CHECKED(Type, name, index) \
  101. RUNTIME_ASSERT(args[index]->Is##Type()); \
  102. Type* name = Type::cast(args[index]);
  103. #define CONVERT_ARG_HANDLE_CHECKED(Type, name, index) \
  104. RUNTIME_ASSERT(args[index]->Is##Type()); \
  105. Handle<Type> name = args.at<Type>(index);
  106. // Cast the given object to a boolean and store it in a variable with
  107. // the given name. If the object is not a boolean call IllegalOperation
  108. // and return.
  109. #define CONVERT_BOOLEAN_ARG_CHECKED(name, index) \
  110. RUNTIME_ASSERT(args[index]->IsBoolean()); \
  111. bool name = args[index]->IsTrue();
  112. // Cast the given argument to a Smi and store its value in an int variable
  113. // with the given name. If the argument is not a Smi call IllegalOperation
  114. // and return.
  115. #define CONVERT_SMI_ARG_CHECKED(name, index) \
  116. RUNTIME_ASSERT(args[index]->IsSmi()); \
  117. int name = args.smi_at(index);
  118. // Cast the given argument to a double and store it in a variable with
  119. // the given name. If the argument is not a number (as opposed to
  120. // the number not-a-number) call IllegalOperation and return.
  121. #define CONVERT_DOUBLE_ARG_CHECKED(name, index) \
  122. RUNTIME_ASSERT(args[index]->IsNumber()); \
  123. double name = args.number_at(index);
  124. // Call the specified converter on the object *comand store the result in
  125. // a variable of the specified type with the given name. If the
  126. // object is not a Number call IllegalOperation and return.
  127. #define CONVERT_NUMBER_CHECKED(type, name, Type, obj) \
  128. RUNTIME_ASSERT(obj->IsNumber()); \
  129. type name = NumberTo##Type(obj);
  130. // Cast the given argument to PropertyDetails and store its value in a
  131. // variable with the given name. If the argument is not a Smi call
  132. // IllegalOperation and return.
  133. #define CONVERT_PROPERTY_DETAILS_CHECKED(name, index) \
  134. RUNTIME_ASSERT(args[index]->IsSmi()); \
  135. PropertyDetails name = PropertyDetails(Smi::cast(args[index]));
  136. // Assert that the given argument has a valid value for a StrictModeFlag
  137. // and store it in a StrictModeFlag variable with the given name.
  138. #define CONVERT_STRICT_MODE_ARG_CHECKED(name, index) \
  139. RUNTIME_ASSERT(args[index]->IsSmi()); \
  140. RUNTIME_ASSERT(args.smi_at(index) == kStrictMode || \
  141. args.smi_at(index) == kNonStrictMode); \
  142. StrictModeFlag name = \
  143. static_cast<StrictModeFlag>(args.smi_at(index));
  144. // Assert that the given argument has a valid value for a LanguageMode
  145. // and store it in a LanguageMode variable with the given name.
  146. #define CONVERT_LANGUAGE_MODE_ARG(name, index) \
  147. ASSERT(args[index]->IsSmi()); \
  148. ASSERT(args.smi_at(index) == CLASSIC_MODE || \
  149. args.smi_at(index) == STRICT_MODE || \
  150. args.smi_at(index) == EXTENDED_MODE); \
  151. LanguageMode name = \
  152. static_cast<LanguageMode>(args.smi_at(index));
  153. static Handle<Map> ComputeObjectLiteralMap(
  154. Handle<Context> context,
  155. Handle<FixedArray> constant_properties,
  156. bool* is_result_from_cache) {
  157. Isolate* isolate = context->GetIsolate();
  158. int properties_length = constant_properties->length();
  159. int number_of_properties = properties_length / 2;
  160. // Check that there are only internal strings and array indices among keys.
  161. int number_of_string_keys = 0;
  162. for (int p = 0; p != properties_length; p += 2) {
  163. Object* key = constant_properties->get(p);
  164. uint32_t element_index = 0;
  165. if (key->IsInternalizedString()) {
  166. number_of_string_keys++;
  167. } else if (key->ToArrayIndex(&element_index)) {
  168. // An index key does not require space in the property backing store.
  169. number_of_properties--;
  170. } else {
  171. // Bail out as a non-internalized-string non-index key makes caching
  172. // impossible.
  173. // ASSERT to make sure that the if condition after the loop is false.
  174. ASSERT(number_of_string_keys != number_of_properties);
  175. break;
  176. }
  177. }
  178. // If we only have internalized strings and array indices among keys then we
  179. // can use the map cache in the native context.
  180. const int kMaxKeys = 10;
  181. if ((number_of_string_keys == number_of_properties) &&
  182. (number_of_string_keys < kMaxKeys)) {
  183. // Create the fixed array with the key.
  184. Handle<FixedArray> keys =
  185. isolate->factory()->NewFixedArray(number_of_string_keys);
  186. if (number_of_string_keys > 0) {
  187. int index = 0;
  188. for (int p = 0; p < properties_length; p += 2) {
  189. Object* key = constant_properties->get(p);
  190. if (key->IsInternalizedString()) {
  191. keys->set(index++, key);
  192. }
  193. }
  194. ASSERT(index == number_of_string_keys);
  195. }
  196. *is_result_from_cache = true;
  197. return isolate->factory()->ObjectLiteralMapFromCache(context, keys);
  198. }
  199. *is_result_from_cache = false;
  200. return isolate->factory()->CopyMap(
  201. Handle<Map>(context->object_function()->initial_map()),
  202. number_of_properties);
  203. }
  204. static Handle<Object> CreateLiteralBoilerplate(
  205. Isolate* isolate,
  206. Handle<FixedArray> literals,
  207. Handle<FixedArray> constant_properties);
  208. static Handle<Object> CreateObjectLiteralBoilerplate(
  209. Isolate* isolate,
  210. Handle<FixedArray> literals,
  211. Handle<FixedArray> constant_properties,
  212. bool should_have_fast_elements,
  213. bool has_function_literal) {
  214. // Get the native context from the literals array. This is the
  215. // context in which the function was created and we use the object
  216. // function from this context to create the object literal. We do
  217. // not use the object function from the current native context
  218. // because this might be the object function from another context
  219. // which we should not have access to.
  220. Handle<Context> context =
  221. Handle<Context>(JSFunction::NativeContextFromLiterals(*literals));
  222. // In case we have function literals, we want the object to be in
  223. // slow properties mode for now. We don't go in the map cache because
  224. // maps with constant functions can't be shared if the functions are
  225. // not the same (which is the common case).
  226. bool is_result_from_cache = false;
  227. Handle<Map> map = has_function_literal
  228. ? Handle<Map>(context->object_function()->initial_map())
  229. : ComputeObjectLiteralMap(context,
  230. constant_properties,
  231. &is_result_from_cache);
  232. Handle<JSObject> boilerplate =
  233. isolate->factory()->NewJSObjectFromMap(
  234. map, isolate->heap()->GetPretenureMode());
  235. // Normalize the elements of the boilerplate to save space if needed.
  236. if (!should_have_fast_elements) JSObject::NormalizeElements(boilerplate);
  237. // Add the constant properties to the boilerplate.
  238. int length = constant_properties->length();
  239. bool should_transform =
  240. !is_result_from_cache && boilerplate->HasFastProperties();
  241. if (should_transform || has_function_literal) {
  242. // Normalize the properties of object to avoid n^2 behavior
  243. // when extending the object multiple properties. Indicate the number of
  244. // properties to be added.
  245. JSObject::NormalizeProperties(
  246. boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2);
  247. }
  248. // TODO(verwaest): Support tracking representations in the boilerplate.
  249. for (int index = 0; index < length; index +=2) {
  250. Handle<Object> key(constant_properties->get(index+0), isolate);
  251. Handle<Object> value(constant_properties->get(index+1), isolate);
  252. if (value->IsFixedArray()) {
  253. // The value contains the constant_properties of a
  254. // simple object or array literal.
  255. Handle<FixedArray> array = Handle<FixedArray>::cast(value);
  256. value = CreateLiteralBoilerplate(isolate, literals, array);
  257. if (value.is_null()) return value;
  258. }
  259. Handle<Object> result;
  260. uint32_t element_index = 0;
  261. JSReceiver::StoreMode mode = value->IsJSObject()
  262. ? JSReceiver::FORCE_FIELD
  263. : JSReceiver::ALLOW_AS_CONSTANT;
  264. if (key->IsInternalizedString()) {
  265. if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
  266. // Array index as string (uint32).
  267. result = JSObject::SetOwnElement(
  268. boilerplate, element_index, value, kNonStrictMode);
  269. } else {
  270. Handle<String> name(String::cast(*key));
  271. ASSERT(!name->AsArrayIndex(&element_index));
  272. result = JSObject::SetLocalPropertyIgnoreAttributes(
  273. boilerplate, name, value, NONE,
  274. Object::OPTIMAL_REPRESENTATION, mode);
  275. }
  276. } else if (key->ToArrayIndex(&element_index)) {
  277. // Array index (uint32).
  278. result = JSObject::SetOwnElement(
  279. boilerplate, element_index, value, kNonStrictMode);
  280. } else {
  281. // Non-uint32 number.
  282. ASSERT(key->IsNumber());
  283. double num = key->Number();
  284. char arr[100];
  285. Vector<char> buffer(arr, ARRAY_SIZE(arr));
  286. const char* str = DoubleToCString(num, buffer);
  287. Handle<String> name =
  288. isolate->factory()->NewStringFromAscii(CStrVector(str));
  289. result = JSObject::SetLocalPropertyIgnoreAttributes(
  290. boilerplate, name, value, NONE,
  291. Object::OPTIMAL_REPRESENTATION, mode);
  292. }
  293. // If setting the property on the boilerplate throws an
  294. // exception, the exception is converted to an empty handle in
  295. // the handle based operations. In that case, we need to
  296. // convert back to an exception.
  297. if (result.is_null()) return result;
  298. }
  299. // Transform to fast properties if necessary. For object literals with
  300. // containing function literals we defer this operation until after all
  301. // computed properties have been assigned so that we can generate
  302. // constant function properties.
  303. if (should_transform && !has_function_literal) {
  304. JSObject::TransformToFastProperties(
  305. boilerplate, boilerplate->map()->unused_property_fields());
  306. }
  307. return boilerplate;
  308. }
  309. MaybeObject* TransitionElements(Handle<Object> object,
  310. ElementsKind to_kind,
  311. Isolate* isolate) {
  312. HandleScope scope(isolate);
  313. if (!object->IsJSObject()) return isolate->ThrowIllegalOperation();
  314. ElementsKind from_kind =
  315. Handle<JSObject>::cast(object)->map()->elements_kind();
  316. if (Map::IsValidElementsTransition(from_kind, to_kind)) {
  317. Handle<Object> result = JSObject::TransitionElementsKind(
  318. Handle<JSObject>::cast(object), to_kind);
  319. if (result.is_null()) return isolate->ThrowIllegalOperation();
  320. return *result;
  321. }
  322. return isolate->ThrowIllegalOperation();
  323. }
  324. static const int kSmiLiteralMinimumLength = 1024;
  325. Handle<Object> Runtime::CreateArrayLiteralBoilerplate(
  326. Isolate* isolate,
  327. Handle<FixedArray> literals,
  328. Handle<FixedArray> elements) {
  329. // Create the JSArray.
  330. Handle<JSFunction> constructor(
  331. JSFunction::NativeContextFromLiterals(*literals)->array_function());
  332. Handle<JSArray> object = Handle<JSArray>::cast(
  333. isolate->factory()->NewJSObject(
  334. constructor, isolate->heap()->GetPretenureMode()));
  335. ElementsKind constant_elements_kind =
  336. static_cast<ElementsKind>(Smi::cast(elements->get(0))->value());
  337. Handle<FixedArrayBase> constant_elements_values(
  338. FixedArrayBase::cast(elements->get(1)));
  339. ASSERT(IsFastElementsKind(constant_elements_kind));
  340. Context* native_context = isolate->context()->native_context();
  341. Object* maybe_maps_array = native_context->js_array_maps();
  342. ASSERT(!maybe_maps_array->IsUndefined());
  343. Object* maybe_map = FixedArray::cast(maybe_maps_array)->get(
  344. constant_elements_kind);
  345. ASSERT(maybe_map->IsMap());
  346. object->set_map(Map::cast(maybe_map));
  347. Handle<FixedArrayBase> copied_elements_values;
  348. if (IsFastDoubleElementsKind(constant_elements_kind)) {
  349. ASSERT(FLAG_smi_only_arrays);
  350. copied_elements_values = isolate->factory()->CopyFixedDoubleArray(
  351. Handle<FixedDoubleArray>::cast(constant_elements_values));
  352. } else {
  353. ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind));
  354. const bool is_cow =
  355. (constant_elements_values->map() ==
  356. isolate->heap()->fixed_cow_array_map());
  357. if (is_cow) {
  358. copied_elements_values = constant_elements_values;
  359. #if DEBUG
  360. Handle<FixedArray> fixed_array_values =
  361. Handle<FixedArray>::cast(copied_elements_values);
  362. for (int i = 0; i < fixed_array_values->length(); i++) {
  363. ASSERT(!fixed_array_values->get(i)->IsFixedArray());
  364. }
  365. #endif
  366. } else {
  367. Handle<FixedArray> fixed_array_values =
  368. Handle<FixedArray>::cast(constant_elements_values);
  369. Handle<FixedArray> fixed_array_values_copy =
  370. isolate->factory()->CopyFixedArray(fixed_array_values);
  371. copied_elements_values = fixed_array_values_copy;
  372. for (int i = 0; i < fixed_array_values->length(); i++) {
  373. Object* current = fixed_array_values->get(i);
  374. if (current->IsFixedArray()) {
  375. // The value contains the constant_properties of a
  376. // simple object or array literal.
  377. Handle<FixedArray> fa(FixedArray::cast(fixed_array_values->get(i)));
  378. Handle<Object> result =
  379. CreateLiteralBoilerplate(isolate, literals, fa);
  380. if (result.is_null()) return result;
  381. fixed_array_values_copy->set(i, *result);
  382. }
  383. }
  384. }
  385. }
  386. object->set_elements(*copied_elements_values);
  387. object->set_length(Smi::FromInt(copied_elements_values->length()));
  388. // Ensure that the boilerplate object has FAST_*_ELEMENTS, unless the flag is
  389. // on or the object is larger than the threshold.
  390. if (!FLAG_smi_only_arrays &&
  391. constant_elements_values->length() < kSmiLiteralMinimumLength) {
  392. ElementsKind elements_kind = object->GetElementsKind();
  393. if (!IsFastObjectElementsKind(elements_kind)) {
  394. if (IsFastHoleyElementsKind(elements_kind)) {
  395. CHECK(!TransitionElements(object, FAST_HOLEY_ELEMENTS,
  396. isolate)->IsFailure());
  397. } else {
  398. CHECK(!TransitionElements(object, FAST_ELEMENTS, isolate)->IsFailure());
  399. }
  400. }
  401. }
  402. object->ValidateElements();
  403. return object;
  404. }
  405. static Handle<Object> CreateLiteralBoilerplate(
  406. Isolate* isolate,
  407. Handle<FixedArray> literals,
  408. Handle<FixedArray> array) {
  409. Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
  410. const bool kHasNoFunctionLiteral = false;
  411. switch (CompileTimeValue::GetLiteralType(array)) {
  412. case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS:
  413. return CreateObjectLiteralBoilerplate(isolate,
  414. literals,
  415. elements,
  416. true,
  417. kHasNoFunctionLiteral);
  418. case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS:
  419. return CreateObjectLiteralBoilerplate(isolate,
  420. literals,
  421. elements,
  422. false,
  423. kHasNoFunctionLiteral);
  424. case CompileTimeValue::ARRAY_LITERAL:
  425. return Runtime::CreateArrayLiteralBoilerplate(
  426. isolate, literals, elements);
  427. default:
  428. UNREACHABLE();
  429. return Handle<Object>::null();
  430. }
  431. }
  432. RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteral) {
  433. HandleScope scope(isolate);
  434. ASSERT(args.length() == 4);
  435. CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
  436. CONVERT_SMI_ARG_CHECKED(literals_index, 1);
  437. CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2);
  438. CONVERT_SMI_ARG_CHECKED(flags, 3);
  439. bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
  440. bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
  441. // Check if boilerplate exists. If not, create it first.
  442. Handle<Object> boilerplate(literals->get(literals_index), isolate);
  443. if (*boilerplate == isolate->heap()->undefined_value()) {
  444. boilerplate = CreateObjectLiteralBoilerplate(isolate,
  445. literals,
  446. constant_properties,
  447. should_have_fast_elements,
  448. has_function_literal);
  449. RETURN_IF_EMPTY_HANDLE(isolate, boilerplate);
  450. // Update the functions literal and return the boilerplate.
  451. literals->set(literals_index, *boilerplate);
  452. }
  453. return JSObject::cast(*boilerplate)->DeepCopy(isolate);
  454. }
  455. RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteralShallow) {
  456. HandleScope scope(isolate);
  457. ASSERT(args.length() == 4);
  458. CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
  459. CONVERT_SMI_ARG_CHECKED(literals_index, 1);
  460. CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2);
  461. CONVERT_SMI_ARG_CHECKED(flags, 3);
  462. bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
  463. bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
  464. // Check if boilerplate exists. If not, create it first.
  465. Handle<Object> boilerplate(literals->get(literals_index), isolate);
  466. if (*boilerplate == isolate->heap()->undefined_value()) {
  467. boilerplate = CreateObjectLiteralBoilerplate(isolate,
  468. literals,
  469. constant_properties,
  470. should_have_fast_elements,
  471. has_function_literal);
  472. RETURN_IF_EMPTY_HANDLE(isolate, boilerplate);
  473. // Update the functions literal and return the boilerplate.
  474. literals->set(literals_index, *boilerplate);
  475. }
  476. return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate));
  477. }
  478. static Handle<AllocationSite> GetLiteralAllocationSite(
  479. Isolate* isolate,
  480. Handle<FixedArray> literals,
  481. int literals_index,
  482. Handle<FixedArray> elements) {
  483. // Check if boilerplate exists. If not, create it first.
  484. Handle<Object> literal_site(literals->get(literals_index), isolate);
  485. Handle<AllocationSite> site;
  486. if (*literal_site == isolate->heap()->undefined_value()) {
  487. ASSERT(*elements != isolate->heap()->empty_fixed_array());
  488. Handle<Object> boilerplate =
  489. Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
  490. if (boilerplate.is_null()) return site;
  491. site = isolate->factory()->NewAllocationSite();
  492. site->set_transition_info(*boilerplate);
  493. literals->set(literals_index, *site);
  494. } else {
  495. site = Handle<AllocationSite>::cast(literal_site);
  496. }
  497. return site;
  498. }
  499. RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteral) {
  500. HandleScope scope(isolate);
  501. ASSERT(args.length() == 3);
  502. CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
  503. CONVERT_SMI_ARG_CHECKED(literals_index, 1);
  504. CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
  505. Handle<AllocationSite> site = GetLiteralAllocationSite(isolate, literals,
  506. literals_index, elements);
  507. RETURN_IF_EMPTY_HANDLE(isolate, site);
  508. JSObject* boilerplate = JSObject::cast(site->transition_info());
  509. return boilerplate->DeepCopy(isolate);
  510. }
  511. RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralShallow) {
  512. HandleScope scope(isolate);
  513. ASSERT(args.length() == 3);
  514. CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
  515. CONVERT_SMI_ARG_CHECKED(literals_index, 1);
  516. CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
  517. Handle<AllocationSite> site = GetLiteralAllocationSite(isolate, literals,
  518. literals_index, elements);
  519. RETURN_IF_EMPTY_HANDLE(isolate, site);
  520. JSObject* boilerplate = JSObject::cast(site->transition_info());
  521. if (boilerplate->elements()->map() ==
  522. isolate->heap()->fixed_cow_array_map()) {
  523. isolate->counters()->cow_arrays_created_runtime()->Increment();
  524. }
  525. AllocationSiteMode mode = AllocationSite::GetMode(
  526. boilerplate->GetElementsKind());
  527. if (mode == TRACK_ALLOCATION_SITE) {
  528. return isolate->heap()->CopyJSObjectWithAllocationSite(
  529. boilerplate, *site);
  530. }
  531. return isolate->heap()->CopyJSObject(boilerplate);
  532. }
  533. RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateSymbol) {
  534. HandleScope scope(isolate);
  535. ASSERT(args.length() == 1);
  536. Handle<Object> name(args[0], isolate);
  537. RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
  538. Symbol* symbol;
  539. MaybeObject* maybe = isolate->heap()->AllocateSymbol();
  540. if (!maybe->To(&symbol)) return maybe;
  541. if (name->IsString()) symbol->set_name(*name);
  542. return symbol;
  543. }
  544. RUNTIME_FUNCTION(MaybeObject*, Runtime_SymbolName) {
  545. SealHandleScope shs(isolate);
  546. ASSERT(args.length() == 1);
  547. CONVERT_ARG_CHECKED(Symbol, symbol, 0);
  548. return symbol->name();
  549. }
  550. RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSProxy) {
  551. SealHandleScope shs(isolate);
  552. ASSERT(args.length() == 2);
  553. CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
  554. Object* prototype = args[1];
  555. Object* used_prototype =
  556. prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
  557. return isolate->heap()->AllocateJSProxy(handler, used_prototype);
  558. }
  559. RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSFunctionProxy) {
  560. SealHandleScope shs(isolate);
  561. ASSERT(args.length() == 4);
  562. CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
  563. Object* call_trap = args[1];
  564. RUNTIME_ASSERT(call_trap->IsJSFunction() || call_trap->IsJSFunctionProxy());
  565. CONVERT_ARG_CHECKED(JSFunction, construct_trap, 2);
  566. Object* prototype = args[3];
  567. Object* used_prototype =
  568. prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
  569. return isolate->heap()->AllocateJSFunctionProxy(
  570. handler, call_trap, construct_trap, used_prototype);
  571. }
  572. RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSProxy) {
  573. SealHandleScope shs(isolate);
  574. ASSERT(args.length() == 1);
  575. Object* obj = args[0];
  576. return isolate->heap()->ToBoolean(obj->IsJSProxy());
  577. }
  578. RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSFunctionProxy) {
  579. SealHandleScope shs(isolate);
  580. ASSERT(args.length() == 1);
  581. Object* obj = args[0];
  582. return isolate->heap()->ToBoolean(obj->IsJSFunctionProxy());
  583. }
  584. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHandler) {
  585. SealHandleScope shs(isolate);
  586. ASSERT(args.length() == 1);
  587. CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
  588. return proxy->handler();
  589. }
  590. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetCallTrap) {
  591. SealHandleScope shs(isolate);
  592. ASSERT(args.length() == 1);
  593. CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
  594. return proxy->call_trap();
  595. }
  596. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructTrap) {
  597. SealHandleScope shs(isolate);
  598. ASSERT(args.length() == 1);
  599. CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
  600. return proxy->construct_trap();
  601. }
  602. RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) {
  603. SealHandleScope shs(isolate);
  604. ASSERT(args.length() == 1);
  605. CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
  606. proxy->Fix();
  607. return isolate->heap()->undefined_value();
  608. }
  609. void Runtime::FreeArrayBuffer(Isolate* isolate,
  610. JSArrayBuffer* phantom_array_buffer) {
  611. if (phantom_array_buffer->is_external()) return;
  612. size_t allocated_length = NumberToSize(
  613. isolate, phantom_array_buffer->byte_length());
  614. isolate->heap()->AdjustAmountOfExternalAllocatedMemory(
  615. -static_cast<intptr_t>(allocated_length));
  616. CHECK(V8::ArrayBufferAllocator() != NULL);
  617. V8::ArrayBufferAllocator()->Free(
  618. phantom_array_buffer->backing_store(),
  619. allocated_length);
  620. }
  621. void Runtime::SetupArrayBuffer(Isolate* isolate,
  622. Handle<JSArrayBuffer> array_buffer,
  623. bool is_external,
  624. void* data,
  625. size_t allocated_length) {
  626. ASSERT(array_buffer->GetInternalFieldCount() ==
  627. v8::ArrayBuffer::kInternalFieldCount);
  628. for (int i = 0; i < v8::ArrayBuffer::kInternalFieldCount; i++) {
  629. array_buffer->SetInternalField(i, Smi::FromInt(0));
  630. }
  631. array_buffer->set_backing_store(data);
  632. array_buffer->set_flag(Smi::FromInt(0));
  633. array_buffer->set_is_external(is_external);
  634. Handle<Object> byte_length =
  635. isolate->factory()->NewNumberFromSize(allocated_length);
  636. CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber());
  637. array_buffer->set_byte_length(*byte_length);
  638. array_buffer->set_weak_next(isolate->heap()->array_buffers_list());
  639. isolate->heap()->set_array_buffers_list(*array_buffer);
  640. array_buffer->set_weak_first_view(isolate->heap()->undefined_value());
  641. }
  642. bool Runtime::SetupArrayBufferAllocatingData(
  643. Isolate* isolate,
  644. Handle<JSArrayBuffer> array_buffer,
  645. size_t allocated_length,
  646. bool initialize) {
  647. void* data;
  648. CHECK(V8::ArrayBufferAllocator() != NULL);
  649. if (allocated_length != 0) {
  650. if (initialize) {
  651. data = V8::ArrayBufferAllocator()->Allocate(allocated_length);
  652. } else {
  653. data =
  654. V8::ArrayBufferAllocator()->AllocateUninitialized(allocated_length);
  655. }
  656. if (data == NULL) return false;
  657. } else {
  658. data = NULL;
  659. }
  660. SetupArrayBuffer(isolate, array_buffer, false, data, allocated_length);
  661. isolate->heap()->AdjustAmountOfExternalAllocatedMemory(allocated_length);
  662. return true;
  663. }
  664. RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferInitialize) {
  665. HandleScope scope(isolate);
  666. ASSERT(args.length() == 2);
  667. CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, holder, 0);
  668. CONVERT_ARG_HANDLE_CHECKED(Object, byteLength, 1);
  669. size_t allocated_length;
  670. if (byteLength->IsSmi()) {
  671. allocated_length = Smi::cast(*byteLength)->value();
  672. } else {
  673. ASSERT(byteLength->IsHeapNumber());
  674. double value = HeapNumber::cast(*byteLength)->value();
  675. ASSERT(value >= 0);
  676. if (value > std::numeric_limits<size_t>::max()) {
  677. return isolate->Throw(
  678. *isolate->factory()->NewRangeError("invalid_array_buffer_length",
  679. HandleVector<Object>(NULL, 0)));
  680. }
  681. allocated_length = static_cast<size_t>(value);
  682. }
  683. if (!Runtime::SetupArrayBufferAllocatingData(isolate,
  684. holder, allocated_length)) {
  685. return isolate->Throw(*isolate->factory()->
  686. NewRangeError("invalid_array_buffer_length",
  687. HandleVector<Object>(NULL, 0)));
  688. }
  689. return *holder;
  690. }
  691. RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferGetByteLength) {
  692. SealHandleScope shs(isolate);
  693. ASSERT(args.length() == 1);
  694. CONVERT_ARG_CHECKED(JSArrayBuffer, holder, 0);
  695. return holder->byte_length();
  696. }
  697. RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferSliceImpl) {
  698. HandleScope scope(isolate);
  699. ASSERT(args.length() == 3);
  700. CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, source, 0);
  701. CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, target, 1);
  702. CONVERT_DOUBLE_ARG_CHECKED(first, 2);
  703. size_t start = static_cast<size_t>(first);
  704. size_t target_length = NumberToSize(isolate, target->byte_length());
  705. if (target_length == 0) return isolate->heap()->undefined_value();
  706. ASSERT(NumberToSize(isolate, source->byte_length()) - target_length >= start);
  707. uint8_t* source_data = reinterpret_cast<uint8_t*>(source->backing_store());
  708. uint8_t* target_data = reinterpret_cast<uint8_t*>(target->backing_store());
  709. CopyBytes(target_data, source_data + start, target_length);
  710. return isolate->heap()->undefined_value();
  711. }
  712. enum TypedArrayId {
  713. // arrayIds below should be synchromized with typedarray.js natives.
  714. ARRAY_ID_UINT8 = 1,
  715. ARRAY_ID_INT8 = 2,
  716. ARRAY_ID_UINT16 = 3,
  717. ARRAY_ID_INT16 = 4,
  718. ARRAY_ID_UINT32 = 5,
  719. ARRAY_ID_INT32 = 6,
  720. ARRAY_ID_FLOAT32 = 7,
  721. ARRAY_ID_FLOAT64 = 8,
  722. ARRAY_ID_UINT8C = 9
  723. };
  724. static void ArrayIdToTypeAndSize(
  725. int arrayId, ExternalArrayType* array_type, size_t* element_size) {
  726. switch (arrayId) {
  727. case ARRAY_ID_UINT8:
  728. *array_type = kExternalUnsignedByteArray;
  729. *element_size = 1;
  730. break;
  731. case ARRAY_ID_INT8:
  732. *array_type = kExternalByteArray;
  733. *element_size = 1;
  734. break;
  735. case ARRAY_ID_UINT16:
  736. *array_type = kExternalUnsignedShortArray;
  737. *element_size = 2;
  738. break;
  739. case ARRAY_ID_INT16:
  740. *array_type = kExternalShortArray;
  741. *element_size = 2;
  742. break;
  743. case ARRAY_ID_UINT32:
  744. *array_type = kExternalUnsignedIntArray;
  745. *element_size = 4;
  746. break;
  747. case ARRAY_ID_INT32:
  748. *array_type = kExternalIntArray;
  749. *element_size = 4;
  750. break;
  751. case ARRAY_ID_FLOAT32:
  752. *array_type = kExternalFloatArray;
  753. *element_size = 4;
  754. break;
  755. case ARRAY_ID_FLOAT64:
  756. *array_type = kExternalDoubleArray;
  757. *element_size = 8;
  758. break;
  759. case ARRAY_ID_UINT8C:
  760. *array_type = kExternalPixelArray;
  761. *element_size = 1;
  762. break;
  763. default:
  764. UNREACHABLE();
  765. }
  766. }
  767. RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) {
  768. HandleScope scope(isolate);
  769. ASSERT(args.length() == 5);
  770. CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
  771. CONVERT_SMI_ARG_CHECKED(arrayId, 1);
  772. CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 2);
  773. CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset_object, 3);
  774. CONVERT_ARG_HANDLE_CHECKED(Object, byte_length_object, 4);
  775. ASSERT(holder->GetInternalFieldCount() ==
  776. v8::ArrayBufferView::kInternalFieldCount);
  777. for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
  778. holder->SetInternalField(i, Smi::FromInt(0));
  779. }
  780. ExternalArrayType array_type = kExternalByteArray; // Bogus initialization.
  781. size_t element_size = 1; // Bogus initialization.
  782. ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
  783. holder->set_buffer(*buffer);
  784. holder->set_byte_offset(*byte_offset_object);
  785. holder->set_byte_length(*byte_length_object);
  786. size_t byte_offset = NumberToSize(isolate, *byte_offset_object);
  787. size_t byte_length = NumberToSize(isolate, *byte_length_object);
  788. ASSERT(byte_length % element_size == 0);
  789. size_t length = byte_length / element_size;
  790. Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length);
  791. holder->set_length(*length_obj);
  792. holder->set_weak_next(buffer->weak_first_view());
  793. buffer->set_weak_first_view(*holder);
  794. Handle<ExternalArray> elements =
  795. isolate->factory()->NewExternalArray(
  796. static_cast<int>(length), array_type,
  797. static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
  798. holder->set_elements(*elements);
  799. return isolate->heap()->undefined_value();
  800. }
  801. // Initializes a typed array from an array-like object.
  802. // If an array-like object happens to be a typed array of the same type,
  803. // initializes backing store using memove.
  804. //
  805. // Returns true if backing store was initialized or false otherwise.
  806. RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitializeFromArrayLike) {
  807. HandleScope scope(isolate);
  808. ASSERT(args.length() == 4);
  809. CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
  810. CONVERT_SMI_ARG_CHECKED(arrayId, 1);
  811. CONVERT_ARG_HANDLE_CHECKED(Object, source, 2);
  812. CONVERT_ARG_HANDLE_CHECKED(Object, length_obj, 3);
  813. ASSERT(holder->GetInternalFieldCount() ==
  814. v8::ArrayBufferView::kInternalFieldCount);
  815. for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
  816. holder->SetInternalField(i, Smi::FromInt(0));
  817. }
  818. ExternalArrayType array_type = kExternalByteArray; // Bogus initialization.
  819. size_t element_size = 1; // Bogus initialization.
  820. ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
  821. Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
  822. size_t length = NumberToSize(isolate, *length_obj);
  823. size_t byte_length = length * element_size;
  824. if (byte_length < length) { // Overflow
  825. return isolate->Throw(*isolate->factory()->
  826. NewRangeError("invalid_array_buffer_length",
  827. HandleVector<Object>(NULL, 0)));
  828. }
  829. // We assume that the caller of this function will initialize holder
  830. // with the loop
  831. // for(i = 0; i < length; i++) { holder[i] = source[i]; }
  832. // If source is a typed array, this loop will always run to completion,
  833. // so we are sure that the backing store will be initialized.
  834. // Otherwise, we do not know (the indexing operation might throw).
  835. // Hence we require zero initialization unless our source is a typed array.
  836. bool should_zero_initialize = !source->IsJSTypedArray();
  837. if (!Runtime::SetupArrayBufferAllocatingData(
  838. isolate, buffer, byte_length, should_zero_initialize)) {
  839. return isolate->Throw(*isolate->factory()->
  840. NewRangeError("invalid_array_buffer_length",
  841. HandleVector<Object>(NULL, 0)));
  842. }
  843. holder->set_buffer(*buffer);
  844. holder->set_byte_offset(Smi::FromInt(0));
  845. Handle<Object> byte_length_obj(
  846. isolate->factory()->NewNumberFromSize(byte_length));
  847. holder->set_byte_length(*byte_length_obj);
  848. holder->set_length(*length_obj);
  849. holder->set_weak_next(buffer->weak_first_view());
  850. buffer->set_weak_first_view(*holder);
  851. Handle<ExternalArray> elements =
  852. isolate->factory()->NewExternalArray(
  853. static_cast<int>(length), array_type,
  854. static_cast<uint8_t*>(buffer->backing_store()));
  855. holder->set_elements(*elements);
  856. if (source->IsJSTypedArray()) {
  857. Handle<JSTypedArray> typed_array(JSTypedArray::cast(*source));
  858. if (typed_array->type() == holder->type()) {
  859. uint8_t* backing_store =
  860. static_cast<uint8_t*>(
  861. JSArrayBuffer::cast(typed_array->buffer())->backing_store());
  862. size_t source_byte_offset =
  863. NumberToSize(isolate, typed_array->byte_offset());
  864. OS::MemCopy(
  865. buffer->backing_store(),
  866. backing_store + source_byte_offset,
  867. byte_length);
  868. return *isolate->factory()->true_value();
  869. } else {
  870. return *isolate->factory()->false_value();
  871. }
  872. }
  873. return *isolate->factory()->false_value();
  874. }
  875. #define TYPED_ARRAY_GETTER(getter, accessor) \
  876. RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayGet##getter) { \
  877. HandleScope scope(isolate); \
  878. ASSERT(args.length() == 1); \
  879. CONVERT_ARG_HANDLE_CHECKED(Object, holder, 0); \
  880. if (!holder->IsJSTypedArray()) \
  881. return isolate->Throw(*isolate->factory()->NewTypeError( \
  882. "not_typed_array", HandleVector<Object>(NULL, 0))); \
  883. Handle<JSTypedArray> typed_array(JSTypedArray::cast(*holder)); \
  884. return typed_array->accessor(); \
  885. }
  886. TYPED_ARRAY_GETTER(Buffer, buffer)
  887. TYPED_ARRAY_GETTER(ByteLength, byte_length)
  888. TYPED_ARRAY_GETTER(ByteOffset, byte_offset)
  889. TYPED_ARRAY_GETTER(Length, length)
  890. #undef TYPED_ARRAY_GETTER
  891. // Return codes for Runtime_TypedArraySetFastCases.
  892. // Should be synchronized with typedarray.js natives.
  893. enum TypedArraySetResultCodes {
  894. // Set from typed array of the same type.
  895. // This is processed by TypedArraySetFastCases
  896. TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE = 0,
  897. // Set from typed array of the different type, overlapping in memory.
  898. TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING = 1,
  899. // Set from typed array of the different type, non-overlapping.
  900. TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING = 2,
  901. // Set from non-typed array.
  902. TYPED_ARRAY_SET_NON_TYPED_ARRAY = 3
  903. };
  904. RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArraySetFastCases) {
  905. HandleScope scope(isolate);
  906. CONVERT_ARG_HANDLE_CHECKED(Object, target_obj, 0);
  907. CONVERT_ARG_HANDLE_CHECKED(Object, source_obj, 1);
  908. CONVERT_ARG_HANDLE_CHECKED(Object, offset_obj, 2);
  909. if (!target_obj->IsJSTypedArray())
  910. return isolate->Throw(*isolate->factory()->NewTypeError(
  911. "not_typed_array", HandleVector<Object>(NULL, 0)));
  912. if (!source_obj->IsJSTypedArray())
  913. return Smi::FromInt(TYPED_ARRAY_SET_NON_TYPED_ARRAY);
  914. Handle<JSTypedArray> target(JSTypedArray::cast(*target_obj));
  915. Handle<JSTypedArray> source(JSTypedArray::cast(*source_obj));
  916. size_t offset = NumberToSize(isolate, *offset_obj);
  917. size_t target_length = NumberToSize(isolate, target->length());
  918. size_t source_length = NumberToSize(isolate, source->length());
  919. size_t target_byte_length = NumberToSize(isolate, target->byte_length());
  920. size_t source_byte_length = NumberToSize(isolate, source->byte_length());
  921. if (offset > target_length ||
  922. offset + source_length > target_length ||
  923. offset + source_length < offset) // overflow
  924. return isolate->Throw(*isolate->factory()->NewRangeError(
  925. "typed_array_set_source_too_large", HandleVector<Object>(NULL, 0)));
  926. size_t target_offset = NumberToSize(isolate, target->byte_offset());
  927. size_t source_offset = NumberToSize(isolate, source->byte_offset());
  928. uint8_t* target_base =
  929. static_cast<uint8_t*>(
  930. JSArrayBuffer::cast(target->buffer())->backing_store()) + target_offset;
  931. uint8_t* source_base =
  932. static_cast<uint8_t*>(
  933. JSArrayBuffer::cast(source->buffer())->backing_store()) + source_offset;
  934. // Typed arrays of the same type: use memmove.
  935. if (target->type() == source->type()) {
  936. memmove(target_base + offset * target->element_size(),
  937. source_base, source_byte_length);
  938. return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE);
  939. }
  940. // Typed arrays of different types over the same backing store
  941. if ((source_base <= target_base &&
  942. source_base + source_byte_length > target_base) ||
  943. (target_base <= source_base &&
  944. target_base + target_byte_length > source_base)) {
  945. // We do not support overlapping ArrayBuffers
  946. ASSERT(
  947. JSArrayBuffer::cast(target->buffer())->backing_store() ==
  948. JSArrayBuffer::cast(source->buffer())->backing_store());
  949. return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING);
  950. } else { // Non-overlapping typed arrays
  951. return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING);
  952. }
  953. }
  954. RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewInitialize) {
  955. HandleScope scope(isolate);
  956. ASSERT(args.length() == 4);
  957. CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);
  958. CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 1);
  959. CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset, 2);
  960. CONVERT_ARG_HANDLE_CHECKED(Object, byte_length, 3);
  961. ASSERT(holder->GetInternalFieldCount() ==
  962. v8::ArrayBufferView::kInternalFieldCount);
  963. for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
  964. holder->SetInternalField(i, Smi::FromInt(0));
  965. }
  966. holder->set_buffer(*buffer);
  967. ASSERT(byte_offset->IsNumber());
  968. ASSERT(
  969. NumberToSize(isolate, buffer->byte_length()) >=
  970. NumberToSize(isolate, *byte_offset)
  971. + NumberToSize(isolate, *byte_length));
  972. holder->set_byte_offset(*byte_offset);
  973. ASSERT(byte_length->IsNumber());
  974. holder->set_byte_length(*byte_length);
  975. holder->set_weak_next(buffer->weak_first_view());
  976. buffer->set_weak_first_view(*holder);
  977. return isolate->heap()->undefined_value();
  978. }
  979. RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetBuffer) {
  980. HandleScope scope(isolate);
  981. ASSERT(args.length() == 1);
  982. CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
  983. return data_view->buffer();
  984. }
  985. RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteOffset) {
  986. HandleScope scope(isolate);
  987. ASSERT(args.length() == 1);
  988. CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
  989. return data_view->byte_offset();
  990. }
  991. RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteLength) {
  992. HandleScope scope(isolate);
  993. ASSERT(args.length() == 1);
  994. CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
  995. return data_view->byte_length();
  996. }
  997. inline static bool NeedToFlipBytes(bool is_little_endian) {
  998. #ifdef V8_TARGET_LITTLE_ENDIAN
  999. return !is_little_endian;
  1000. #else
  1001. return is_little_endian;
  1002. #endif
  1003. }
  1004. template<int n>
  1005. inline void CopyBytes(uint8_t* target, uint8_t* source) {
  1006. for (int i = 0; i < n; i++) {
  1007. *(target++) = *(source++);
  1008. }
  1009. }
  1010. template<int n>
  1011. inline void FlipBytes(uint8_t* target, uint8_t* source) {
  1012. source = source + (n-1);
  1013. for (int i = 0; i < n; i++) {
  1014. *(target++) = *(source--);
  1015. }
  1016. }
  1017. template<typename T>
  1018. inline static bool DataViewGetValue(
  1019. Isolate* isolate,
  1020. Handle<JSDataView> data_view,
  1021. Handle<Object> byte_offset_obj,
  1022. bool is_little_endian,
  1023. T* result) {
  1024. size_t byte_offset = NumberToSize(isolate, *byte_offset_obj);
  1025. Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer()));
  1026. size_t data_view_byte_offset =
  1027. NumberToSize(isolate, data_view->byte_offset());
  1028. size_t data_view_byte_length =
  1029. NumberToSize(isolate, data_view->byte_length());
  1030. if (byte_offset + sizeof(T) > data_view_byte_length ||
  1031. byte_offset + sizeof(T) < byte_offset) { // overflow
  1032. return false;
  1033. }
  1034. union Value {
  1035. T data;
  1036. uint8_t bytes[sizeof(T)];
  1037. };
  1038. Value value;
  1039. size_t buffer_offset = data_view_byte_offset + byte_offset;
  1040. ASSERT(
  1041. NumberToSize(isolate, buffer->byte_length())
  1042. >= buffer_offset + sizeof(T));
  1043. uint8_t* source =
  1044. static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset;
  1045. if (NeedToFlipBytes(is_little_endian)) {
  1046. FlipBytes<sizeof(T)>(value.bytes, source);
  1047. } else {
  1048. CopyBytes<sizeof(T)>(value.bytes, source);
  1049. }
  1050. *result = value.data;
  1051. return true;
  1052. }
  1053. template<typename T>
  1054. static bool DataViewSetValue(
  1055. Isolate* isolate,
  1056. Handle<JSDataView> data_view,
  1057. Handle<Object> byte_offset_obj,
  1058. bool is_little_endian,
  1059. T data) {
  1060. size_t byte_offset = NumberToSize(isolate, *byte_offset_obj);
  1061. Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer()));
  1062. size_t data_view_byte_offset =
  1063. NumberToSize(isolate, data_view->byte_offset());
  1064. size_t data_view_byte_length =
  1065. NumberToSize(isolate, data_view->byte_length());
  1066. if (byte_offset + sizeof(T) > data_view_byte_length ||
  1067. byte_offset + sizeof(T) < byte_offset) { // overflow
  1068. return false;
  1069. }
  1070. union Value {
  1071. T data;
  1072. uint8_t bytes[sizeof(T)];
  1073. };
  1074. Value value;
  1075. value.data = data;
  1076. size_t buffer_offset = data_view_byte_offset + byte_offset;
  1077. ASSERT(
  1078. NumberToSize(isolate, buffer->byte_length())
  1079. >= buffer_offset + sizeof(T));
  1080. uint8_t* target =
  1081. static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset;
  1082. if (NeedToFlipBytes(is_little_endian)) {
  1083. FlipBytes<sizeof(T)>(target, value.bytes);
  1084. } else {
  1085. CopyBytes<sizeof(T)>(target, value.bytes);
  1086. }
  1087. return true;
  1088. }
  1089. #define DATA_VIEW_GETTER(TypeName, Type, Converter) \
  1090. RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGet##TypeName) { \
  1091. HandleScope scope(isolate); \
  1092. ASSERT(args.length() == 3); \
  1093. CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); \
  1094. CONVERT_ARG_HANDLE_CHECKED(Object, offset, 1); \
  1095. CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 2); \
  1096. Type result; \
  1097. if (DataViewGetValue( \
  1098. isolate, holder, offset, is_little_endian, &result)) { \
  1099. return isolate->heap()->Converter(result); \
  1100. } else { \
  1101. return isolate->Throw(*isolate->factory()->NewRangeError( \
  1102. "invalid_data_view_accessor_offset", \
  1103. HandleVector<Object>(NULL, 0))); \
  1104. } \
  1105. }
  1106. DATA_VIEW_GETTER(Uint8, uint8_t, NumberFromUint32)
  1107. DATA_VIEW_GETTER(Int8, int8_t, NumberFromInt32)
  1108. DATA_VIEW_GETTER(Uint16, uint16_t, NumberFromUint32)
  1109. DATA_VIEW_GETTER(Int16, int16_t, NumberFromInt32)
  1110. DATA_VIEW_GETTER(Uint32, uint32_t, NumberFromUint32)
  1111. DATA_VIEW_GETTER(Int32, int32_t, NumberFromInt32)
  1112. DATA_VIEW_GETTER(Float32, float, NumberFromDouble)
  1113. DATA_VIEW_GETTER(Float64, double, NumberFromDouble)
  1114. #undef DATA_VIEW_GETTER
  1115. template <typename T>
  1116. static T DataViewConvertValue(double value);
  1117. template <>
  1118. int8_t DataViewConvertValue<int8_t>(double value) {
  1119. return static_cast<int8_t>(DoubleToInt32(value));
  1120. }
  1121. template <>
  1122. int16_t DataViewConvertValue<int16_t>(double value) {
  1123. return static_cast<int16_t>(DoubleToInt32(value));
  1124. }
  1125. template <>
  1126. int32_t DataViewConvertValue<int32_t>(double value) {
  1127. return DoubleToInt32(value);
  1128. }
  1129. template <>
  1130. uint8_t DataViewConvertValue<uint8_t>(double value) {
  1131. return static_cast<uint8_t>(DoubleToUint32(value));
  1132. }
  1133. template <>
  1134. uint16_t DataViewConvertValue<uint16_t>(double value) {
  1135. return static_cast<uint16_t>(DoubleToUint32(value));
  1136. }
  1137. template <>
  1138. uint32_t DataViewConvertValue<uint32_t>(double value) {
  1139. return DoubleToUint32(value);
  1140. }
  1141. template <>
  1142. float DataViewConvertValue<float>(double value) {
  1143. return static_cast<float>(value);
  1144. }
  1145. template <>
  1146. double DataViewConvertValue<double>(double value) {
  1147. return value;
  1148. }
  1149. #define DATA_VIEW_SETTER(TypeName, Type) \
  1150. RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewSet##TypeName) { \
  1151. HandleScope scope(isolate); \
  1152. ASSERT(args.length() == 4); \
  1153. CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0); \
  1154. CONVERT_ARG_HANDLE_CHECKED(Object, offset, 1); \
  1155. CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); \
  1156. CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 3); \
  1157. Type v = DataViewConvertValue<Type>(value->Number()); \
  1158. if (DataViewSetValue( \
  1159. isolate, holder, offset, is_little_endian, v)) { \
  1160. return isolate->heap()->undefined_value(); \
  1161. } else { \
  1162. return isolate->Throw(*isolate->factory()->NewRangeError( \
  1163. "invalid_data_view_accessor_offset", \
  1164. HandleVector<Object>(NULL, 0))); \
  1165. } \
  1166. }
  1167. DATA_VIEW_SETTER(Uint8, uint8_t)
  1168. DATA_VIEW_SETTER(Int8, int8_t)
  1169. DATA_VIEW_SETTER(Uint16, uint16_t)
  1170. DATA_VIEW_SETTER(Int16, int16_t)
  1171. DATA_VIEW_SETTER(Uint32, uint32_t)
  1172. DATA_VIEW_SETTER(Int32, int32_t)
  1173. DATA_VIEW_SETTER(Float32, float)
  1174. DATA_VIEW_SETTER(Float64, double)
  1175. #undef DATA_VIEW_SETTER
  1176. RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInitialize) {
  1177. HandleScope scope(isolate);
  1178. ASSERT(args.length() == 1);
  1179. CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
  1180. Handle<ObjectHashSet> table = isolate->factory()->NewObjectHashSet(0);
  1181. holder->set_table(*table);
  1182. return *holder;
  1183. }
  1184. RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAdd) {
  1185. HandleScope scope(isolate);
  1186. ASSERT(args.length() == 2);
  1187. CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
  1188. Handle<Object> key(args[1], isolate);
  1189. Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
  1190. table = ObjectHashSetAdd(table, key);
  1191. holder->set_table(*table);
  1192. return isolate->heap()->undefined_value();
  1193. }
  1194. RUNTIME_FUNCTION(MaybeObject*, Runtime_SetHas) {
  1195. HandleScope scope(isolate);
  1196. ASSERT(args.length() == 2);
  1197. CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
  1198. Handle<Object> key(args[1], isolate);
  1199. Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
  1200. return isolate->heap()->ToBoolean(table->Contains(*key));
  1201. }
  1202. RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDelete) {
  1203. HandleScope scope(isolate);
  1204. ASSERT(args.length() == 2);
  1205. CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
  1206. Handle<Object> key(args[1], isolate);
  1207. Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
  1208. table = ObjectHashSetRemove(table, key);
  1209. holder->set_table(*table);
  1210. return isolate->heap()->undefined_value();
  1211. }
  1212. RUNTIME_FUNCTION(MaybeObject*, Runtime_SetGetSize) {
  1213. HandleScope scope(isolate);
  1214. ASSERT(args.length() == 1);
  1215. CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
  1216. Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
  1217. return Smi::FromInt(table->NumberOfElements());
  1218. }
  1219. RUNTIME_FUNCTION(MaybeObject*, Runtime_MapInitialize) {
  1220. HandleScope scope(isolate);
  1221. ASSERT(args.length() == 1);
  1222. CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
  1223. Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
  1224. holder->set_table(*table);
  1225. return *holder;
  1226. }
  1227. RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGet) {
  1228. HandleScope scope(isolate);
  1229. ASSERT(args.length() == 2);
  1230. CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
  1231. CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
  1232. Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
  1233. Handle<Object> lookup(table->Lookup(*key), isolate);
  1234. return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
  1235. }
  1236. RUNTIME_FUNCTION(MaybeObject*, Runtime_MapHas) {
  1237. HandleScope scope(isolate);
  1238. ASSERT(args.length() == 2);
  1239. CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
  1240. CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
  1241. Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
  1242. Handle<Object> lookup(table->Lookup(*key), isolate);
  1243. return isolate->heap()->ToBoolean(!lookup->IsTheHole());
  1244. }
  1245. RUNTIME_FUNCTION(MaybeObject*, Runtime_MapDelete) {
  1246. HandleScope scope(isolate);
  1247. ASSERT(args.length() == 2);
  1248. CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
  1249. CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
  1250. Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
  1251. Handle<Object> lookup(table->Lookup(*key), isolate);
  1252. Handle<ObjectHashTable> new_table =
  1253. PutIntoObjectHashTable(table, key, isolate->factory()->the_hole_value());
  1254. holder->set_table(*new_table);
  1255. return isolate->heap()->ToBoolean(!lookup->IsTheHole());
  1256. }
  1257. RUNTIME_FUNCTION(MaybeObject*, Runtime_MapSet) {
  1258. HandleScope scope(isolate);
  1259. ASSERT(args.length() == 3);
  1260. CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
  1261. CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
  1262. CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
  1263. Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
  1264. Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
  1265. holder->set_table(*new_table);
  1266. return isolate->heap()->undefined_value();
  1267. }
  1268. RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGetSize) {
  1269. HandleScope scope(isolate);
  1270. ASSERT(args.length() == 1);
  1271. CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
  1272. Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
  1273. return Smi::FromInt(table->NumberOfElements());
  1274. }
  1275. static JSWeakCollection* WeakCollectionInitialize(Isolate* isolate,
  1276. Handle<JSWeakCollection> weak_collection) {
  1277. ASSERT(weak_collection->map()->inobject_properties() == 0);
  1278. Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
  1279. weak_collection->set_table(*table);
  1280. weak_collection->set_next(Smi::FromInt(0));
  1281. return *weak_collection;
  1282. }
  1283. RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionInitialize) {
  1284. HandleScope scope(isolate);
  1285. ASSERT(args.length() == 1);
  1286. CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
  1287. return WeakCollectionInitialize(isolate, weak_collection);
  1288. }
  1289. RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionGet) {
  1290. HandleScope scope(isolate);
  1291. ASSERT(args.length() == 2);
  1292. CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
  1293. CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
  1294. Handle<ObjectHashTable> table(
  1295. ObjectHashTable::cast(weak_collection->table()));
  1296. Handle<Object> lookup(table->Lookup(*key), isolate);
  1297. return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
  1298. }
  1299. RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionHas) {
  1300. HandleScope scope(isolate);
  1301. ASSERT(args.length() == 2);
  1302. CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
  1303. CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
  1304. Handle<ObjectHashTable> table(
  1305. ObjectHashTable::cast(weak_collection->table()));
  1306. Handle<Object> lookup(table->Lookup(*key), isolate);
  1307. return isolate->heap()->ToBoolean(!lookup->IsTheHole());
  1308. }
  1309. RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionDelete) {
  1310. HandleScope scope(isolate);
  1311. ASSERT(args.length() == 2);
  1312. CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
  1313. CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
  1314. Handle<ObjectHashTable> table(ObjectHashTable::cast(
  1315. weak_collection->table()));
  1316. Handle<Object> lookup(table->Lookup(*key), isolate);
  1317. Handle<ObjectHashTable> new_table =
  1318. PutIntoObjectHashTable(table, key, isolate->factory()->the_hole_value());
  1319. weak_collection->set_table(*new_table);
  1320. return isolate->heap()->ToBoolean(!lookup->IsTheHole());
  1321. }
  1322. RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionSet) {
  1323. HandleScope scope(isolate);
  1324. ASSERT(args.length() == 3);
  1325. CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
  1326. CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
  1327. Handle<Object> value(args[2], isolate);
  1328. Handle<ObjectHashTable> table(
  1329. ObjectHashTable::cast(weak_collection->table()));
  1330. Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
  1331. weak_collection->set_table(*new_table);
  1332. return isolate->heap()->undefined_value();
  1333. }
  1334. RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) {
  1335. SealHandleScope shs(isolate);
  1336. ASSERT(args.length() == 1);
  1337. Object* obj = args[0];
  1338. if (!obj->IsJSObject()) return isolate->heap()->null_value();
  1339. return JSObject::cast(obj)->class_name();
  1340. }
  1341. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) {
  1342. SealHandleScope shs(isolate);
  1343. ASSERT(args.length() == 1);
  1344. CONVERT_ARG_CHECKED(Object, obj, 0);
  1345. // We don't expect access checks to be needed on JSProxy objects.
  1346. ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
  1347. do {
  1348. if (obj->IsAccessCheckNeeded() &&
  1349. !isolate->MayNamedAccess(JSObject::cast(obj),
  1350. isolate->heap()->proto_string(),
  1351. v8::ACCESS_GET)) {
  1352. isolate->ReportFailedAccessCheck(JSObject::cast(obj), v8::ACCESS_GET);
  1353. RETURN_IF_SCHEDULED_EXCEPTION(isolate);
  1354. return isolate->heap()->undefined_value();
  1355. }
  1356. obj = obj->GetPrototype(isolate);
  1357. } while (obj->IsJSObject() &&
  1358. JSObject::cast(obj)->map()->is_hidden_prototype());
  1359. return obj;
  1360. }
  1361. static inline Object* GetPrototypeSkipHiddenPrototypes(Isolate* isolate,
  1362. Object* receiver) {
  1363. Object* current = receiver->GetPrototype(isolate);
  1364. while (current->IsJSObject() &&
  1365. JSObject::cast(current)->map()->is_hidden_prototype()) {
  1366. current = current->GetPrototype(isolate);
  1367. }
  1368. return current;
  1369. }
  1370. RUNTIME_FUNCTION(MaybeObject*, Runtime_SetPrototype) {
  1371. HandleScope scope(isolate);
  1372. ASSERT(args.length() == 2);
  1373. CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
  1374. CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
  1375. if (FLAG_harmony_observation && obj->map()->is_observed()) {
  1376. Handle<Object> old_value(
  1377. GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate);
  1378. Handle<Object> result = JSObject::SetPrototype(obj, prototype, true);
  1379. RETURN_IF_EMPTY_HANDLE(isolate, result);
  1380. Handle<Object> new_value(
  1381. GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate);
  1382. if (!new_value->SameValue(*old_value)) {
  1383. JSObject::EnqueueChangeRecord(obj, "prototype",
  1384. isolate->factory()->proto_string(),
  1385. old_value);
  1386. }
  1387. return *result;
  1388. }
  1389. Handle<Object> result = JSObject::SetPrototype(obj, prototype, true);
  1390. RETURN_IF_EMPTY_HANDLE(isolate, result);
  1391. return *result;
  1392. }
  1393. RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) {
  1394. SealHandleScope shs(isolate);
  1395. ASSERT(args.length() == 2);
  1396. // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
  1397. Object* O = args[0];
  1398. Object* V = args[1];
  1399. while (true) {
  1400. Object* prototype = V->GetPrototype(isolate);
  1401. if (prototype->IsNull()) return isolate->heap()->false_value();
  1402. if (O == prototype) return isolate->heap()->true_value();
  1403. V = prototype;
  1404. }
  1405. }
  1406. static bool CheckAccessException(Object* callback,
  1407. v8::AccessType access_type) {
  1408. if (callback->IsAccessorInfo()) {
  1409. AccessorInfo* info = AccessorInfo::cast(callback);
  1410. return
  1411. (access_type == v8::ACCESS_HAS &&
  1412. (info->all_can_read() || info->all_can_write())) ||
  1413. (access_type == v8::ACCESS_GET && info->all_can_read()) ||
  1414. (access_type == v8::ACCESS_SET && info->all_can_write());
  1415. }
  1416. return false;
  1417. }
  1418. template<class Key>
  1419. static bool CheckGenericAccess(
  1420. JSObject* receiver,
  1421. JSObject* holder,
  1422. Key key,
  1423. v8::AccessType access_type,
  1424. bool (Isolate::*mayAccess)(JSObject*, Key, v8::AccessType)) {
  1425. Isolate* isolate = receiver->GetIsolate();
  1426. for (JSObject* current = receiver;
  1427. true;
  1428. current = JSObject::cast(current->GetPrototype())) {
  1429. if (current->IsAccessCheckNeeded() &&
  1430. !(isolate->*mayAccess)(current, key, access_type)) {
  1431. return false;
  1432. }
  1433. if (current == holder) break;
  1434. }
  1435. return true;
  1436. }
  1437. enum AccessCheckResult {
  1438. ACCESS_FORBIDDEN,
  1439. ACCESS_ALLOWED,
  1440. ACCESS_ABSENT
  1441. };
  1442. static AccessCheckResult CheckPropertyAccess(
  1443. JSObject* obj,
  1444. Name* name,
  1445. v8::AccessType access_type) {
  1446. uint32_t index;
  1447. if (name->AsArrayIndex(&index)) {
  1448. // TODO(1095): we should traverse hidden prototype hierachy as well.
  1449. if (CheckGenericAccess(
  1450. obj, obj, index, access_type, &Isolate::MayIndexedAccess)) {
  1451. return ACCESS_ALLOWED;
  1452. }
  1453. obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type);
  1454. return ACCESS_FORBIDDEN;
  1455. }
  1456. LookupResult lookup(obj->GetIsolate());
  1457. obj->LocalLookup(name, &lookup, true);
  1458. if (!lookup.IsProperty()) return ACCESS_ABSENT;
  1459. if (CheckGenericAccess<Object*>(
  1460. obj, lookup.holder(), name, access_type, &Isolate::MayNamedAccess)) {
  1461. return ACCESS_ALLOWED;
  1462. }
  1463. // Access check callback denied the access, but some properties
  1464. // can have a special permissions which override callbacks descision
  1465. // (currently see v8::AccessControl).
  1466. // API callbacks can have per callback access exceptions.
  1467. switch (lookup.type()) {
  1468. case CALLBACKS:
  1469. if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
  1470. return ACCESS_ALLOWED;
  1471. }
  1472. break;
  1473. case INTERCEPTOR:
  1474. // If the object has an interceptor, try real named properties.
  1475. // Overwrite the result to fetch the correct property later.
  1476. lookup.holder()->LookupRealNamedProperty(name, &lookup);
  1477. if (lookup.IsProperty() && lookup.IsPropertyCallbacks()) {
  1478. if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
  1479. return ACCESS_ALLOWED;
  1480. }
  1481. }
  1482. break;
  1483. default:
  1484. break;
  1485. }
  1486. obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type);
  1487. return ACCESS_FORBIDDEN;
  1488. }
  1489. // Enumerator used as indices into the array returned from GetOwnProperty
  1490. enum PropertyDescriptorIndices {
  1491. IS_ACCESSOR_INDEX,
  1492. VALUE_INDEX,
  1493. GETTER_INDEX,
  1494. SETTER_INDEX,
  1495. WRITABLE_INDEX,
  1496. ENUMERABLE_INDEX,
  1497. CONFIGURABLE_INDEX,
  1498. DESCRIPTOR_SIZE
  1499. };
  1500. static MaybeObject* GetOwnProperty(Isolate* isolate,
  1501. Handle<JSObject> obj,
  1502. Handle<Name> name) {
  1503. Heap* heap = isolate->heap();
  1504. // Due to some WebKit tests, we want to make sure that we do not log
  1505. // more than one access failure here.
  1506. AccessCheckResult access_check_result =
  1507. CheckPropertyAccess(*obj, *name, v8::ACCESS_HAS);
  1508. RETURN_IF_SCHEDULED_EXCEPTION(isolate);
  1509. switch (access_check_result) {
  1510. case ACCESS_FORBIDDEN: return heap->false_value();
  1511. case ACCESS_ALLOWED: break;
  1512. case ACCESS_ABSENT: return heap->undefined_value();
  1513. }
  1514. PropertyAttributes attrs = obj->GetLocalPropertyAttribute(*name);
  1515. if (attrs == ABSENT) {
  1516. RETURN_IF_SCHEDULED_EXCEPTION(isolate);
  1517. return heap->undefined_value();
  1518. }
  1519. ASSERT(!isolate->has_scheduled_exception());
  1520. AccessorPair* raw_accessors = obj->GetLocalPropertyAccessorPair(*name);
  1521. Handle<AccessorPair> accessors(raw_accessors, isolate);
  1522. Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
  1523. elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
  1524. elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
  1525. elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(raw_accessors != NULL));
  1526. if (raw_accessors == NULL) {
  1527. elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
  1528. // GetProperty does access check.
  1529. Handle<Object> value = GetProperty(isolate, obj, name);
  1530. RETURN_IF_EMPTY_HANDLE(isolate, value);
  1531. elms->set(VALUE_INDEX, *value);
  1532. } else {
  1533. // Access checks are performed for both accessors separately.
  1534. // When they fail, the respective field is not set in the descriptor.
  1535. Object* getter = accessors->GetComponent(ACCESSOR_GETTER);
  1536. Object* setter = accessors->GetComponent(ACCESSOR_SETTER);
  1537. if (!getter->IsMap() && CheckPropertyAccess(*obj, *name, v8::ACCESS_GET)) {
  1538. ASSERT(!isolate->has_scheduled_exception());
  1539. elms->set(GETTER_INDEX, getter);
  1540. } else {
  1541. RETURN_IF_SCHEDULED_EXCEPTION(isolate);
  1542. }
  1543. if (!setter->IsMap() && CheckPropertyAccess(*obj, *name, v8::ACCESS_SET)) {
  1544. ASSERT(!isolate->has_scheduled_exception());
  1545. elms->set(SETTER_INDEX, setter);
  1546. } else {
  1547. RETURN_IF_SCHEDULED_EXCEPTION(isolate);
  1548. }
  1549. }
  1550. return *isolate->factory()->NewJSArrayWithElements(elms);
  1551. }
  1552. // Returns an array with the property description:
  1553. // if args[1] is not a property on args[0]
  1554. // returns undefined
  1555. // if args[1] is a data property on args[0]
  1556. // [false, value, Writeable, Enumerable, Configurable]
  1557. // if args[1] is an accessor on args[0]
  1558. // [true, GetFunction, SetFunction, Enumerable, Configurable]
  1559. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) {
  1560. HandleScope scope(isolate);
  1561. ASSERT(args.length() == 2);
  1562. CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
  1563. CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
  1564. return GetOwnProperty(isolate, obj, name);
  1565. }
  1566. RUNTIME_FUNCTION(MaybeObject*, Runtime_PreventExtensions) {
  1567. SealHandleScope shs(isolate);
  1568. ASSERT(args.length() == 1);
  1569. CONVERT_ARG_CHECKED(JSObject, obj, 0);
  1570. return obj->PreventExtensions();
  1571. }
  1572. RUNTIME_FUNCTION(MaybeObject*, Runtime_IsExtensible) {
  1573. SealHandleScope shs(isolate);
  1574. ASSERT(args.length() == 1);
  1575. CONVERT_ARG_CHECKED(JSObject, obj, 0);
  1576. if (obj->IsJSGlobalProxy()) {
  1577. Object* proto = obj->GetPrototype();
  1578. if (proto->IsNull()) return isolate->heap()->false_value();
  1579. ASSERT(proto->IsJSGlobalObject());
  1580. obj = JSObject::cast(proto);
  1581. }
  1582. return isolate->heap()->ToBoolean(obj->map()->is_extensible());
  1583. }
  1584. RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpCompile) {
  1585. HandleScope scope(isolate);
  1586. ASSERT(args.length() == 3);
  1587. CONVERT_ARG_HANDLE_CHECKED(JSRegExp, re, 0);
  1588. CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
  1589. CONVERT_ARG_HANDLE_CHECKED(String, flags, 2);
  1590. Handle<Object> result =
  1591. RegExpImpl::Compile(re, pattern, flags);
  1592. RETURN_IF_EMPTY_HANDLE(isolate, result);
  1593. return *result;
  1594. }
  1595. RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateApiFunction) {
  1596. HandleScope scope(isolate);
  1597. ASSERT(args.length() == 1);
  1598. CONVERT_ARG_HANDLE_CHECKED(FunctionTemplateInfo, data, 0);
  1599. return *isolate->factory()->CreateApiFunction(data);
  1600. }
  1601. RUNTIME_FUNCTION(MaybeObject*, Runtime_IsTemplate) {
  1602. SealHandleScope shs(isolate);
  1603. ASSERT(args.length() == 1);
  1604. Object* arg = args[0];
  1605. bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
  1606. return isolate->heap()->ToBoolean(result);
  1607. }
  1608. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetTemplateField) {
  1609. SealHandleScope shs(isolate);
  1610. ASSERT(args.length() == 2);
  1611. CONVERT_ARG_CHECKED(HeapObject, templ, 0);
  1612. CONVERT_SMI_ARG_CHECKED(index, 1)
  1613. int offset = index * kPointerSize + HeapObject::kHeaderSize;
  1614. InstanceType type = templ->map()->instance_type();
  1615. RUNTIME_ASSERT(type == FUNCTION_TEMPLATE_INFO_TYPE ||
  1616. type == OBJECT_TEMPLATE_INFO_TYPE);
  1617. RUNTIME_ASSERT(offset > 0);
  1618. if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
  1619. RUNTIME_ASSERT(offset < FunctionTemplateInfo::kSize);
  1620. } else {
  1621. RUNTIME_ASSERT(offset < ObjectTemplateInfo::kSize);
  1622. }
  1623. return *HeapObject::RawField(templ, offset);
  1624. }
  1625. RUNTIME_FUNCTION(MaybeObject*, Runtime_DisableAccessChecks) {
  1626. SealHandleScope shs(isolate);
  1627. ASSERT(args.length() == 1);
  1628. CONVERT_ARG_CHECKED(HeapObject, object, 0);
  1629. Map* old_map = object->map();
  1630. bool needs_access_checks = old_map->is_access_check_needed();
  1631. if (needs_access_checks) {
  1632. // Copy map so it won't interfere constructor's initial map.
  1633. Map* new_map;
  1634. MaybeObject* maybe_new_map = old_map->Copy();
  1635. if (!maybe_new_map->To(&new_map)) return maybe_new_map;
  1636. new_map->set_is_access_check_needed(false);
  1637. object->set_map(new_map);
  1638. }
  1639. return isolate->heap()->ToBoolean(needs_access_checks);
  1640. }
  1641. RUNTIME_FUNCTION(MaybeObject*, Runtime_EnableAccessChecks) {
  1642. SealHandleScope shs(isolate);
  1643. ASSERT(args.length() == 1);
  1644. CONVERT_ARG_CHECKED(HeapObject, object, 0);
  1645. Map* old_map = object->map();
  1646. if (!old_map->is_access_check_needed()) {
  1647. // Copy map so it won't interfere constructor's initial map.
  1648. Map* new_map;
  1649. MaybeObject* maybe_new_map = old_map->Copy();
  1650. if (!maybe_new_map->To(&new_map)) return maybe_new_map;
  1651. new_map->set_is_access_check_needed(true);
  1652. object->set_map(new_map);
  1653. }
  1654. return isolate->heap()->undefined_value();
  1655. }
  1656. static Failure* ThrowRedeclarationError(Isolate* isolate,
  1657. const char* type,
  1658. Handle<String> name) {
  1659. HandleScope scope(isolate);
  1660. Handle<Object> type_handle =
  1661. isolate->factory()->NewStringFromAscii(CStrVector(type));
  1662. Handle<Object> args[2] = { type_handle, name };
  1663. Handle<Object> error =
  1664. isolate->factory()->NewTypeError("redeclaration", HandleVector(args, 2));
  1665. return isolate->Throw(*error);
  1666. }
  1667. RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
  1668. HandleScope scope(isolate);
  1669. ASSERT(args.length() == 3);
  1670. Handle<GlobalObject> global = Handle<GlobalObject>(
  1671. isolate->context()->global_object());
  1672. Handle<Context> context = args.at<Context>(0);
  1673. CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1);
  1674. CONVERT_SMI_ARG_CHECKED(flags, 2);
  1675. // Traverse the name/value pairs and set the properties.
  1676. int length = pairs->length();
  1677. for (int i = 0; i < length; i += 2) {
  1678. HandleScope scope(isolate);
  1679. Handle<String> name(String::cast(pairs->get(i)));
  1680. Handle<Object> value(pairs->get(i + 1), isolate);
  1681. // We have to declare a global const property. To capture we only
  1682. // assign to it when evaluating the assignment for "const x =
  1683. // <expr>" the initial value is the hole.
  1684. bool is_var = value->IsUndefined();
  1685. bool is_const = value->IsTheHole();
  1686. bool is_function = value->IsSharedFunctionInfo();
  1687. ASSERT(is_var + is_const + is_function == 1);
  1688. if (is_var || is_const) {
  1689. // Lookup the property in the global object, and don't set the
  1690. // value of the variable if the property is already there.
  1691. // Do the lookup locally only, see ES5 erratum.
  1692. LookupResult lookup(isolate);
  1693. if (FLAG_es52_globals) {
  1694. global->LocalLookup(*name, &lookup, true);
  1695. } else {
  1696. global->Lookup(*name, &lookup);
  1697. }
  1698. if (lookup.IsFound()) {
  1699. // We found an existing property. Unless it was an interceptor
  1700. // that claims the property is absent, skip this declaration.
  1701. if (!lookup.IsInterceptor()) continue;
  1702. PropertyAttributes attributes = global->GetPropertyAttribute(*name);
  1703. if (attributes != ABSENT) continue;
  1704. // Fall-through and introduce the absent property by using
  1705. // SetProperty.
  1706. }
  1707. } else if (is_function) {
  1708. // Copy the function and update its context. Use it as value.
  1709. Handle<SharedFunctionInfo> shared =
  1710. Handle<SharedFunctionInfo>::cast(value);
  1711. Handle<JSFunction> function =
  1712. isolate->factory()->NewFunctionFromSharedFunctionInfo(
  1713. shared, context, TENURED);
  1714. value = function;
  1715. }
  1716. LookupResult lookup(isolate);
  1717. global->LocalLookup(*name, &lookup, true);
  1718. // Compute the property attributes. According to ECMA-262,
  1719. // the property must be non-configurable except in eval.
  1720. int attr = NONE;
  1721. bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
  1722. if (!is_eval) {
  1723. attr |= DONT_DELETE;
  1724. }
  1725. bool is_native = DeclareGlobalsNativeFlag::decode(flags);
  1726. if (is_const || (is_native && is_function)) {
  1727. attr |= READ_ONLY;
  1728. }
  1729. LanguageMode language_mode = DeclareGlobalsLanguageMode::decode(flags);
  1730. if (!lookup.IsFound() || is_function) {
  1731. // If the local property exists, check that we can reconfigure it
  1732. // as required for function declarations.
  1733. if (lookup.IsFound() && lookup.IsDontDelete()) {
  1734. if (lookup.IsReadOnly() || lookup.IsDontEnum() ||
  1735. lookup.IsPropertyCallbacks()) {
  1736. return ThrowRedeclarationError(isolate, "function", name);
  1737. }
  1738. // If the existing property is not configurable, keep its attributes.
  1739. attr = lookup.GetAttributes();
  1740. }
  1741. // Define or redefine own property.
  1742. RETURN_IF_EMPTY_HANDLE(isolate,
  1743. JSObject::SetLocalPropertyIgnoreAttributes(
  1744. global, name, value, static_cast<PropertyAttributes>(attr)));
  1745. } else {
  1746. // Do a [[Put]] on the existing (own) property.
  1747. RETURN_IF_EMPTY_HANDLE(isolate,
  1748. JSObject::SetProperty(
  1749. global, name, value, static_cast<PropertyAttributes>(attr),
  1750. language_mode == CLASSIC_MODE ? kNonStrictMode : kStrictMode));
  1751. }
  1752. }
  1753. ASSERT(!isolate->has_pending_exception());
  1754. return isolate->heap()->undefined_value();
  1755. }
  1756. RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
  1757. HandleScope scope(isolate);
  1758. ASSERT(args.length() == 4);
  1759. // Declarations are always made in a function or native context. In the
  1760. // case of eval code, the context passed is the context of the caller,
  1761. // which may be some nested context and not the declaration context.
  1762. RUNTIME_ASSERT(args[0]->IsContext());
  1763. Handle<Context> context(Context::cast(args[0])->declaration_context());
  1764. Handle<String> name(String::cast(args[1]));
  1765. PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2));
  1766. RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE);
  1767. Handle<Object> initial_value(args[3], isolate);
  1768. int index;
  1769. PropertyAttributes attributes;
  1770. ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
  1771. BindingFlags binding_flags;
  1772. Handle<Object> holder =
  1773. context->Lookup(name, flags, &index, &attributes, &binding_flags);
  1774. if (attributes != ABSENT) {
  1775. // The name was declared before; check for conflicting re-declarations.
  1776. // Note: this is actually inconsistent with what happens for globals (where
  1777. // we silently ignore such declarations).
  1778. if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
  1779. // Functions are not read-only.
  1780. ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
  1781. const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
  1782. return ThrowRedeclarationError(isolate, type, name);
  1783. }
  1784. // Initialize it if necessary.
  1785. if (*initial_value != NULL) {
  1786. if (index >= 0) {
  1787. ASSERT(holder.is_identical_to(context));
  1788. if (((attributes & READ_ONLY) == 0) ||
  1789. context->get(index)->IsTheHole()) {
  1790. context->set(index, *initial_value);
  1791. }
  1792. } else {
  1793. // Slow case: The property is in the context extension object of a
  1794. // function context or the global object of a native context.
  1795. Handle<JSObject> object = Handle<JSObject>::cast(holder);
  1796. RETURN_IF_EMPTY_HANDLE(
  1797. isolate,
  1798. JSReceiver::SetProperty(object, name, initial_value, mode,
  1799. kNonStrictMode));
  1800. }
  1801. }
  1802. } else {
  1803. // The property is not in the function context. It needs to be
  1804. // "declared" in the function context's extension context or as a
  1805. // property of the the global object.
  1806. Handle<JSObject> object;
  1807. if (context->has_extension()) {
  1808. object = Handle<JSObject>(JSObject::cast(context->extension()));
  1809. } else {
  1810. // Context extension objects are allocated lazily.
  1811. ASSERT(context->IsFunctionContext());
  1812. object = isolate->factory()->NewJSObject(
  1813. isolate->context_extension_function());
  1814. context->set_extension(*object);
  1815. }
  1816. ASSERT(*object != NULL);
  1817. // Declare the property by setting it to the initial value if provided,
  1818. // or undefined, and use the correct mode (e.g. READ_ONLY attribute for
  1819. // constant declarations).
  1820. ASSERT(!object->HasLocalProperty(*name));
  1821. Handle<Object> value(isolate->heap()->undefined_value(), isolate);
  1822. if (*initial_value != NULL) value = initial_value;
  1823. // Declaring a const context slot is a conflicting declaration if
  1824. // there is a callback with that name in a prototype. It is
  1825. // allowed to introduce const variables in
  1826. // JSContextExtensionObjects. They are treated specially in
  1827. // SetProperty and no setters are invoked for those since they are
  1828. // not real JSObjects.
  1829. if (initial_value->IsTheHole() &&
  1830. !object->IsJSContextExtensionObject()) {
  1831. LookupResult lookup(isolate);
  1832. object->Lookup(*name, &lookup);
  1833. if (lookup.IsPropertyCallbacks()) {
  1834. return ThrowRedeclarationError(isolate, "const", name);
  1835. }
  1836. }
  1837. if (object->IsJSGlobalObject()) {
  1838. // Define own property on the global object.
  1839. RETURN_IF_EMPTY_HANDLE(isolate,
  1840. JSObject::SetLocalPropertyIgnoreAttributes(object, name, value, mode));
  1841. } else {
  1842. RETURN_IF_EMPTY_HANDLE(isolate,
  1843. JSReceiver::SetProperty(object, name, value, mode, kNonStrictMode));
  1844. }
  1845. }
  1846. return isolate->heap()->undefined_value();
  1847. }
  1848. RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
  1849. SealHandleScope shs(isolate);
  1850. // args[0] == name
  1851. // args[1] == language_mode
  1852. // args[2] == value (optional)
  1853. // Determine if we need to assign to the variable if it already
  1854. // exists (based on the number of arguments).
  1855. RUNTIME_ASSERT(args.length() == 2 || args.length() == 3);
  1856. bool assign = args.length() == 3;
  1857. CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
  1858. GlobalObject* global = isolate->context()->global_object();
  1859. RUNTIME_ASSERT(args[1]->IsSmi());
  1860. CONVERT_LANGUAGE_MODE_ARG(language_mode, 1);
  1861. StrictModeFlag strict_mode_flag = (language_mode == CLASSIC_MODE)
  1862. ? kNonStrictMode : kStrictMode;
  1863. // According to ECMA-262, section 12.2, page 62, the property must
  1864. // not be deletable.
  1865. PropertyAttributes attributes = DONT_DELETE;
  1866. // Lookup the property locally in the global object. If it isn't
  1867. // there, there is a property with this name in the prototype chain.
  1868. // We follow Safari and Firefox behavior and only set the property
  1869. // locally if there is an explicit initialization value that we have
  1870. // to assign to the property.
  1871. // Note that objects can have hidden prototypes, so we need to traverse
  1872. // the whole chain of hidden prototypes to do a 'local' lookup.
  1873. Object* object = global;
  1874. LookupResult lookup(isolate);
  1875. JSObject::cast(object)->LocalLookup(*name, &lookup, true);
  1876. if (lookup.IsInterceptor()) {
  1877. HandleScope handle_scope(isolate);
  1878. PropertyAttributes intercepted =
  1879. lookup.holder()->GetPropertyAttribute(*name);
  1880. if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
  1881. // Found an interceptor that's not read only.
  1882. if (assign) {
  1883. return lookup.holder()->SetProperty(
  1884. &lookup, *name, args[2], attributes, strict_mode_flag);
  1885. } else {
  1886. return isolate->heap()->undefined_value();
  1887. }
  1888. }
  1889. }
  1890. // Reload global in case the loop above performed a GC.
  1891. global = isolate->context()->global_object();
  1892. if (assign) {
  1893. return global->SetProperty(*name, args[2], attributes, strict_mode_flag);
  1894. }
  1895. return isolate->heap()->undefined_value();
  1896. }
  1897. RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
  1898. SealHandleScope shs(isolate);
  1899. // All constants are declared with an initial value. The name
  1900. // of the constant is the first argument and the initial value
  1901. // is the second.
  1902. RUNTIME_ASSERT(args.length() == 2);
  1903. CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
  1904. Handle<Object> value = args.at<Object>(1);
  1905. // Get the current global object from top.
  1906. GlobalObject* global = isolate->context()->global_object();
  1907. // According to ECMA-262, section 12.2, page 62, the property must
  1908. // not be deletable. Since it's a const, it must be READ_ONLY too.
  1909. PropertyAttributes attributes =
  1910. static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
  1911. // Lookup the property locally in the global object. If it isn't
  1912. // there, we add the property and take special precautions to always
  1913. // add it as a local property even in case of callbacks in the
  1914. // prototype chain (this rules out using SetProperty).
  1915. // We use SetLocalPropertyIgnoreAttributes instead
  1916. LookupResult lookup(isolate);
  1917. global->LocalLookup(*name, &lookup);
  1918. if (!lookup.IsFound()) {
  1919. return global->SetLocalPropertyIgnoreAttributes(*name,
  1920. *value,
  1921. attributes);
  1922. }
  1923. if (!lookup.IsReadOnly()) {
  1924. // Restore global object from context (in case of GC) and continue
  1925. // with setting the value.
  1926. HandleScope handle_scope(isolate);
  1927. Handle<GlobalObject> global(isolate->context()->global_object());
  1928. // BUG 1213575: Handle the case where we have to set a read-only
  1929. // property through an interceptor and only do it if it's
  1930. // uninitialized, e.g. the hole. Nirk...
  1931. // Passing non-strict mode because the property is writable.
  1932. RETURN_IF_EMPTY_HANDLE(
  1933. isolate,
  1934. JSReceiver::SetProperty(global, name, value, attributes,
  1935. kNonStrictMode));
  1936. return *value;
  1937. }
  1938. // Set the value, but only if we're assigning the initial value to a
  1939. // constant. For now, we determine this by checking if the
  1940. // current value is the hole.
  1941. // Strict mode handling not needed (const is disallowed in strict mode).
  1942. if (lookup.IsField()) {
  1943. FixedArray* properties = global->properties();
  1944. int index = lookup.GetFieldIndex().field_index();
  1945. if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) {
  1946. properties->set(index, *value);
  1947. }
  1948. } else if (lookup.IsNormal()) {
  1949. if (global->GetNormalizedProperty(&lookup)->IsTheHole() ||
  1950. !lookup.IsReadOnly()) {
  1951. HandleScope scope(isolate);
  1952. JSObject::SetNormalizedProperty(Handle<JSObject>(global), &lookup, value);
  1953. }
  1954. } else {
  1955. // Ignore re-initialization of constants that have already been
  1956. // assigned a constant value.
  1957. ASSERT(lookup.IsReadOnly() && lookup.IsConstant());
  1958. }
  1959. // Use the set value as the result of the operation.
  1960. return *value;
  1961. }
  1962. RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) {
  1963. HandleScope scope(isolate);
  1964. ASSERT(args.length() == 3);
  1965. Handle<Object> value(args[0], isolate);
  1966. ASSERT(!value->IsTheHole());
  1967. // Initializations are always done in a function or native context.
  1968. RUNTIME_ASSERT(args[1]->IsContext());
  1969. Handle<Context> context(Context::cast(args[1])->declaration_context());
  1970. Handle<String> name(String::cast(args[2]));
  1971. int index;
  1972. PropertyAttributes attributes;
  1973. ContextLookupFlags flags = FOLLOW_CHAINS;
  1974. BindingFlags binding_flags;
  1975. Handle<Object> holder =
  1976. context->Lookup(name, flags, &index, &attributes, &binding_flags);
  1977. if (index >= 0) {
  1978. ASSERT(holder->IsContext());
  1979. // Property was found in a context. Perform the assignment if we
  1980. // found some non-constant or an uninitialized constant.
  1981. Handle<Context> context = Handle<Context>::cast(holder);
  1982. if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) {
  1983. context->set(index, *value);
  1984. }
  1985. return *value;
  1986. }
  1987. // The property could not be found, we introduce it as a property of the
  1988. // global object.
  1989. if (attributes == ABSENT) {
  1990. Handle<JSObject> global = Handle<JSObject>(
  1991. isolate->context()->global_object());
  1992. // Strict mode not needed (const disallowed in strict mode).
  1993. RETURN_IF_EMPTY_HANDLE(
  1994. isolate,
  1995. JSReceiver::SetProperty(global, name, value, NONE, kNonStrictMode));
  1996. return *value;
  1997. }
  1998. // The property was present in some function's context extension object,
  1999. // as a property on the subject of a with, or as a property of the global
  2000. // object.
  2001. //
  2002. // In most situations, eval-introduced consts should still be present in
  2003. // the context extension object. However, because declaration and
  2004. // initialization are separate, the property might have been deleted
  2005. // before we reach the initialization point.
  2006. //
  2007. // Example:
  2008. //
  2009. // function f() { eval("delete x; const x;"); }
  2010. //
  2011. // In that case, the initialization behaves like a normal assignment.
  2012. Handle<JSObject> object = Handle<JSObject>::cast(holder);
  2013. if (*object == context->extension()) {
  2014. // This is the property that was introduced by the const declaration.
  2015. // Set it if it hasn't been set before. NOTE: We cannot use
  2016. // GetProperty() to get the current value as it 'unholes' the value.
  2017. LookupResult lookup(isolate);
  2018. object->LocalLookupRealNamedProperty(*name, &lookup);
  2019. ASSERT(lookup.IsFound()); // the property was declared
  2020. ASSERT(lookup.IsReadOnly()); // and it was declared as read-only
  2021. if (lookup.IsField()) {
  2022. FixedArray* properties = object->properties();
  2023. int index = lookup.GetFieldIndex().field_index();
  2024. if (properties->get(index)->IsTheHole()) {
  2025. properties->set(index, *value);
  2026. }
  2027. } else if (lookup.IsNormal()) {
  2028. if (object->GetNormalizedProperty(&lookup)->IsTheHole()) {
  2029. JSObject::SetNormalizedProperty(object, &lookup, value);
  2030. }
  2031. } else {
  2032. // We should not reach here. Any real, named property should be
  2033. // either a field or a dictionary slot.
  2034. UNREACHABLE();
  2035. }
  2036. } else {
  2037. // The property was found on some other object. Set it if it is not a
  2038. // read-only property.
  2039. if ((attributes & READ_ONLY) == 0) {
  2040. // Strict mode not needed (const disallowed in strict mode).
  2041. RETURN_IF_EMPTY_HANDLE(
  2042. isolate,
  2043. JSReceiver::SetProperty(object, name, value, attributes,
  2044. kNonStrictMode));
  2045. }
  2046. }
  2047. return *value;
  2048. }
  2049. RUNTIME_FUNCTION(MaybeObject*,
  2050. Runtime_OptimizeObjectForAddingMultipleProperties) {
  2051. HandleScope scope(isolate);
  2052. ASSERT(args.length() == 2);
  2053. CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
  2054. CONVERT_SMI_ARG_CHECKED(properties, 1);
  2055. if (object->HasFastProperties()) {
  2056. JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties);
  2057. }
  2058. return *object;
  2059. }
  2060. RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) {
  2061. HandleScope scope(isolate);
  2062. ASSERT(args.length() == 4);
  2063. CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
  2064. CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
  2065. // Due to the way the JS calls are constructed this must be less than the
  2066. // length of a string, i.e. it is always a Smi. We check anyway for security.
  2067. CONVERT_SMI_ARG_CHECKED(index, 2);
  2068. CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
  2069. RUNTIME_ASSERT(index >= 0);
  2070. RUNTIME_ASSERT(index <= subject->length());
  2071. isolate->counters()->regexp_entry_runtime()->Increment();
  2072. Handle<Object> result = RegExpImpl::Exec(regexp,
  2073. subject,
  2074. index,
  2075. last_match_info);
  2076. RETURN_IF_EMPTY_HANDLE(isolate, result);
  2077. return *result;
  2078. }
  2079. RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpConstructResult) {
  2080. SealHandleScope shs(isolate);
  2081. ASSERT(args.length() == 3);
  2082. CONVERT_SMI_ARG_CHECKED(elements_count, 0);
  2083. if (elements_count < 0 ||
  2084. elements_count > FixedArray::kMaxLength ||
  2085. !Smi::IsValid(elements_count)) {
  2086. return isolate->ThrowIllegalOperation();
  2087. }
  2088. Object* new_object;
  2089. { MaybeObject* maybe_new_object =
  2090. isolate->heap()->AllocateFixedArray(elements_count);
  2091. if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
  2092. }
  2093. FixedArray* elements = FixedArray::cast(new_object);
  2094. { MaybeObject* maybe_new_object = isolate->heap()->AllocateRaw(
  2095. JSRegExpResult::kSize, NEW_SPACE, OLD_POINTER_SPACE);
  2096. if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
  2097. }
  2098. {
  2099. DisallowHeapAllocation no_gc;
  2100. HandleScope scope(isolate);
  2101. reinterpret_cast<HeapObject*>(new_object)->
  2102. set_map(isolate->native_context()->regexp_result_map());
  2103. }
  2104. JSArray* array = JSArray::cast(new_object);
  2105. array->set_properties(isolate->heap()->empty_fixed_array());
  2106. array->set_elements(elements);
  2107. array->set_length(Smi::FromInt(elements_count));
  2108. // Write in-object properties after the length of the array.
  2109. array->InObjectPropertyAtPut(JSRegExpResult::kIndexIndex, args[1]);
  2110. array->InObjectPropertyAtPut(JSRegExpResult::kInputIndex, args[2]);
  2111. return array;
  2112. }
  2113. RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) {
  2114. SealHandleScope shs(isolate);
  2115. DisallowHeapAllocation no_allocation;
  2116. ASSERT(args.length() == 5);
  2117. CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
  2118. CONVERT_ARG_CHECKED(String, source, 1);
  2119. // If source is the empty string we set it to "(?:)" instead as
  2120. // suggested by ECMA-262, 5th, section 15.10.4.1.
  2121. if (source->length() == 0) source = isolate->heap()->query_colon_string();
  2122. Object* global = args[2];
  2123. if (!global->IsTrue()) global = isolate->heap()->false_value();
  2124. Object* ignoreCase = args[3];
  2125. if (!ignoreCase->IsTrue()) ignoreCase = isolate->heap()->false_value();
  2126. Object* multiline = args[4];
  2127. if (!multiline->IsTrue()) multiline = isolate->heap()->false_value();
  2128. Map* map = regexp->map();
  2129. Object* constructor = map->constructor();
  2130. if (constructor->IsJSFunction() &&
  2131. JSFunction::cast(constructor)->initial_map() == map) {
  2132. // If we still have the original map, set in-object properties directly.
  2133. regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, source);
  2134. // Both true and false are immovable immortal objects so no need for write
  2135. // barrier.
  2136. regexp->InObjectPropertyAtPut(
  2137. JSRegExp::kGlobalFieldIndex, global, SKIP_WRITE_BARRIER);
  2138. regexp->InObjectPropertyAtPut(
  2139. JSRegExp::kIgnoreCaseFieldIndex, ignoreCase, SKIP_WRITE_BARRIER);
  2140. regexp->InObjectPropertyAtPut(
  2141. JSRegExp::kMultilineFieldIndex, multiline, SKIP_WRITE_BARRIER);
  2142. regexp->InObjectPropertyAtPut(
  2143. JSRegExp::kLastIndexFieldIndex, Smi::FromInt(0), SKIP_WRITE_BARRIER);
  2144. return regexp;
  2145. }
  2146. // Map has changed, so use generic, but slower, method.
  2147. PropertyAttributes final =
  2148. static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE);
  2149. PropertyAttributes writable =
  2150. static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
  2151. Heap* heap = isolate->heap();
  2152. MaybeObject* result;
  2153. result = regexp->SetLocalPropertyIgnoreAttributes(heap->source_string(),
  2154. source,
  2155. final);
  2156. // TODO(jkummerow): Turn these back into ASSERTs when we can be certain
  2157. // that it never fires in Release mode in the wild.
  2158. CHECK(!result->IsFailure());
  2159. result = regexp->SetLocalPropertyIgnoreAttributes(heap->global_string(),
  2160. global,
  2161. final);
  2162. CHECK(!result->IsFailure());
  2163. result =
  2164. regexp->SetLocalPropertyIgnoreAttributes(heap->ignore_case_string(),
  2165. ignoreCase,
  2166. final);
  2167. CHECK(!result->IsFailure());
  2168. result = regexp->SetLocalPropertyIgnoreAttributes(heap->multiline_string(),
  2169. multiline,
  2170. final);
  2171. CHECK(!result->IsFailure());
  2172. result =
  2173. regexp->SetLocalPropertyIgnoreAttributes(heap->last_index_string(),
  2174. Smi::FromInt(0),
  2175. writable);
  2176. CHECK(!result->IsFailure());
  2177. USE(result);
  2178. return regexp;
  2179. }
  2180. RUNTIME_FUNCTION(MaybeObject*, Runtime_FinishArrayPrototypeSetup) {
  2181. HandleScope scope(isolate);
  2182. ASSERT(args.length() == 1);
  2183. CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0);
  2184. // This is necessary to enable fast checks for absence of elements
  2185. // on Array.prototype and below.
  2186. prototype->set_elements(isolate->heap()->empty_fixed_array());
  2187. return Smi::FromInt(0);
  2188. }
  2189. static Handle<JSFunction> InstallBuiltin(Isolate* isolate,
  2190. Handle<JSObject> holder,
  2191. const char* name,
  2192. Builtins::Name builtin_name) {
  2193. Handle<String> key = isolate->factory()->InternalizeUtf8String(name);
  2194. Handle<Code> code(isolate->builtins()->builtin(builtin_name));
  2195. Handle<JSFunction> optimized =
  2196. isolate->factory()->NewFunction(key,
  2197. JS_OBJECT_TYPE,
  2198. JSObject::kHeaderSize,
  2199. code,
  2200. false);
  2201. optimized->shared()->DontAdaptArguments();
  2202. JSReceiver::SetProperty(holder, key, optimized, NONE, kStrictMode);
  2203. return optimized;
  2204. }
  2205. RUNTIME_FUNCTION(MaybeObject*, Runtime_SpecialArrayFunctions) {
  2206. HandleScope scope(isolate);
  2207. ASSERT(args.length() == 1);
  2208. CONVERT_ARG_HANDLE_CHECKED(JSObject, holder, 0);
  2209. InstallBuiltin(isolate, holder, "pop", Builtins::kArrayPop);
  2210. InstallBuiltin(isolate, holder, "push", Builtins::kArrayPush);
  2211. InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift);
  2212. InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift);
  2213. InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice);
  2214. InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
  2215. InstallBuiltin(isolate, holder, "concat", Builtins::kArrayConcat);
  2216. return *holder;
  2217. }
  2218. RUNTIME_FUNCTION(MaybeObject*, Runtime_IsClassicModeFunction) {
  2219. SealHandleScope shs(isolate);
  2220. ASSERT(args.length() == 1);
  2221. CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
  2222. if (!callable->IsJSFunction()) {
  2223. HandleScope scope(isolate);
  2224. bool threw = false;
  2225. Handle<Object> delegate =
  2226. Execution::TryGetFunctionDelegate(Handle<JSReceiver>(callable), &threw);
  2227. if (threw) return Failure::Exception();
  2228. callable = JSFunction::cast(*delegate);
  2229. }
  2230. JSFunction* function = JSFunction::cast(callable);
  2231. SharedFunctionInfo* shared = function->shared();
  2232. return isolate->heap()->ToBoolean(shared->is_classic_mode());
  2233. }
  2234. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultReceiver) {
  2235. SealHandleScope shs(isolate);
  2236. ASSERT(args.length() == 1);
  2237. CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
  2238. if (!callable->IsJSFunction()) {
  2239. HandleScope scope(isolate);
  2240. bool threw = false;
  2241. Handle<Object> delegate =
  2242. Execution::TryGetFunctionDelegate(Handle<JSReceiver>(callable), &threw);
  2243. if (threw) return Failure::Exception();
  2244. callable = JSFunction::cast(*delegate);
  2245. }
  2246. JSFunction* function = JSFunction::cast(callable);
  2247. SharedFunctionInfo* shared = function->shared();
  2248. if (shared->native() || !shared->is_classic_mode()) {
  2249. return isolate->heap()->undefined_value();
  2250. }
  2251. // Returns undefined for strict or native functions, or
  2252. // the associated global receiver for "normal" functions.
  2253. Context* native_context =
  2254. function->context()->global_object()->native_context();
  2255. return native_context->global_object()->global_receiver();
  2256. }
  2257. RUNTIME_FUNCTION(MaybeObject*, Runtime_MaterializeRegExpLiteral) {
  2258. HandleScope scope(isolate);
  2259. ASSERT(args.length() == 4);
  2260. CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
  2261. int index = args.smi_at(1);
  2262. Handle<String> pattern = args.at<String>(2);
  2263. Handle<String> flags = args.at<String>(3);
  2264. // Get the RegExp function from the context in the literals array.
  2265. // This is the RegExp function from the context in which the
  2266. // function was created. We do not use the RegExp function from the
  2267. // current native context because this might be the RegExp function
  2268. // from another context which we should not have access to.
  2269. Handle<JSFunction> constructor =
  2270. Handle<JSFunction>(
  2271. JSFunction::NativeContextFromLiterals(*literals)->regexp_function());
  2272. // Compute the regular expression literal.
  2273. bool has_pending_exception;
  2274. Handle<Object> regexp =
  2275. RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
  2276. &has_pending_exception);
  2277. if (has_pending_exception) {
  2278. ASSERT(isolate->has_pending_exception());
  2279. return Failure::Exception();
  2280. }
  2281. literals->set(index, *regexp);
  2282. return *regexp;
  2283. }
  2284. RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetName) {
  2285. SealHandleScope shs(isolate);
  2286. ASSERT(args.length() == 1);
  2287. CONVERT_ARG_CHECKED(JSFunction, f, 0);
  2288. return f->shared()->name();
  2289. }
  2290. RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetName) {
  2291. SealHandleScope shs(isolate);
  2292. ASSERT(args.length() == 2);
  2293. CONVERT_ARG_CHECKED(JSFunction, f, 0);
  2294. CONVERT_ARG_CHECKED(String, name, 1);
  2295. f->shared()->set_name(name);
  2296. return isolate->heap()->undefined_value();
  2297. }
  2298. RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionNameShouldPrintAsAnonymous) {
  2299. SealHandleScope shs(isolate);
  2300. ASSERT(args.length() == 1);
  2301. CONVERT_ARG_CHECKED(JSFunction, f, 0);
  2302. return isolate->heap()->ToBoolean(
  2303. f->shared()->name_should_print_as_anonymous());
  2304. }
  2305. RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) {
  2306. SealHandleScope shs(isolate);
  2307. ASSERT(args.length() == 1);
  2308. CONVERT_ARG_CHECKED(JSFunction, f, 0);
  2309. f->shared()->set_name_should_print_as_anonymous(true);
  2310. return isolate->heap()->undefined_value();
  2311. }
  2312. RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsGenerator) {
  2313. SealHandleScope shs(isolate);
  2314. ASSERT(args.length() == 1);
  2315. CONVERT_ARG_CHECKED(JSFunction, f, 0);
  2316. return isolate->heap()->ToBoolean(f->shared()->is_generator());
  2317. }
  2318. RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) {
  2319. SealHandleScope shs(isolate);
  2320. ASSERT(args.length() == 1);
  2321. CONVERT_ARG_CHECKED(JSFunction, f, 0);
  2322. f->RemovePrototype();
  2323. return isolate->heap()->undefined_value();
  2324. }
  2325. RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScript) {
  2326. HandleScope scope(isolate);
  2327. ASSERT(args.length() == 1);
  2328. CONVERT_ARG_CHECKED(JSFunction, fun, 0);
  2329. Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate);
  2330. if (!script->IsScript()) return isolate->heap()->undefined_value();
  2331. return *GetScriptWrapper(Handle<Script>::cast(script));
  2332. }
  2333. RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetSourceCode) {
  2334. HandleScope scope(isolate);
  2335. ASSERT(args.length() == 1);
  2336. CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0);
  2337. Handle<SharedFunctionInfo> shared(f->shared());
  2338. return *shared->GetSourceCode();
  2339. }
  2340. RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScriptSourcePosition) {
  2341. SealHandleScope shs(isolate);
  2342. ASSERT(args.length() == 1);
  2343. CONVERT_ARG_CHECKED(JSFunction, fun, 0);
  2344. int pos = fun->shared()->start_position();
  2345. return Smi::FromInt(pos);
  2346. }
  2347. RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetPositionForOffset) {
  2348. SealHandleScope shs(isolate);
  2349. ASSERT(args.length() == 2);
  2350. CONVERT_ARG_CHECKED(Code, code, 0);
  2351. CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]);
  2352. RUNTIME_ASSERT(0 <= offset && offset < code->Size());
  2353. Address pc = code->address() + offset;
  2354. return Smi::FromInt(code->SourcePosition(pc));
  2355. }
  2356. RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetInstanceClassName) {
  2357. SealHandleScope shs(isolate);
  2358. ASSERT(args.length() == 2);
  2359. CONVERT_ARG_CHECKED(JSFunction, fun, 0);
  2360. CONVERT_ARG_CHECKED(String, name, 1);
  2361. fun->SetInstanceClassName(name);
  2362. return isolate->heap()->undefined_value();
  2363. }
  2364. RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetLength) {
  2365. SealHandleScope shs(isolate);
  2366. ASSERT(args.length() == 2);
  2367. CONVERT_ARG_CHECKED(JSFunction, fun, 0);
  2368. CONVERT_SMI_ARG_CHECKED(length, 1);
  2369. fun->shared()->set_length(length);
  2370. return isolate->heap()->undefined_value();
  2371. }
  2372. RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) {
  2373. SealHandleScope shs(isolate);
  2374. ASSERT(args.length() == 2);
  2375. CONVERT_ARG_CHECKED(JSFunction, fun, 0);
  2376. ASSERT(fun->should_have_prototype());
  2377. Object* obj;
  2378. { MaybeObject* maybe_obj =
  2379. Accessors::FunctionSetPrototype(fun, args[1], NULL);
  2380. if (!maybe_obj->ToObject(&obj)) return maybe_obj;
  2381. }
  2382. return args[0]; // return TOS
  2383. }
  2384. RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) {
  2385. SealHandleScope shs(isolate);
  2386. RUNTIME_ASSERT(args.length() == 1);
  2387. CONVERT_ARG_CHECKED(JSFunction, function, 0);
  2388. String* name = isolate->heap()->prototype_string();
  2389. if (function->HasFastProperties()) {
  2390. // Construct a new field descriptor with updated attributes.
  2391. DescriptorArray* instance_desc = function->map()->instance_descriptors();
  2392. int index = instance_desc->SearchWithCache(name, function->map());
  2393. ASSERT(index != DescriptorArray::kNotFound);
  2394. PropertyDetails details = instance_desc->GetDetails(index);
  2395. CallbacksDescriptor new_desc(name,
  2396. instance_desc->GetValue(index),
  2397. static_cast<PropertyAttributes>(details.attributes() | READ_ONLY));
  2398. // Create a new map featuring the new field descriptors array.
  2399. Map* new_map;
  2400. MaybeObject* maybe_map =
  2401. function->map()->CopyReplaceDescriptor(
  2402. instance_desc, &new_desc, index, OMIT_TRANSITION);
  2403. if (!maybe_map->To(&new_map)) return maybe_map;
  2404. function->set_map(new_map);
  2405. } else { // Dictionary properties.
  2406. // Directly manipulate the property details.
  2407. int entry = function->property_dictionary()->FindEntry(name);
  2408. ASSERT(entry != NameDictionary::kNotFound);
  2409. PropertyDetails details = function->property_dictionary()->DetailsAt(entry);
  2410. PropertyDetails new_details(
  2411. static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
  2412. details.type(),
  2413. details.dictionary_index());
  2414. function->property_dictionary()->DetailsAtPut(entry, new_details);
  2415. }
  2416. return function;
  2417. }
  2418. RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) {
  2419. SealHandleScope shs(isolate);
  2420. ASSERT(args.length() == 1);
  2421. CONVERT_ARG_CHECKED(JSFunction, f, 0);
  2422. return isolate->heap()->ToBoolean(f->shared()->IsApiFunction());
  2423. }
  2424. RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) {
  2425. SealHandleScope shs(isolate);
  2426. ASSERT(args.length() == 1);
  2427. CONVERT_ARG_CHECKED(JSFunction, f, 0);
  2428. return isolate->heap()->ToBoolean(f->IsBuiltin());
  2429. }
  2430. RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
  2431. HandleScope scope(isolate);
  2432. ASSERT(args.length() == 2);
  2433. CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
  2434. Handle<Object> code = args.at<Object>(1);
  2435. if (code->IsNull()) return *target;
  2436. RUNTIME_ASSERT(code->IsJSFunction());
  2437. Handle<JSFunction> source = Handle<JSFunction>::cast(code);
  2438. Handle<SharedFunctionInfo> target_shared(target->shared());
  2439. Handle<SharedFunctionInfo> source_shared(source->shared());
  2440. if (!JSFunction::EnsureCompiled(source, KEEP_EXCEPTION)) {
  2441. return Failure::Exception();
  2442. }
  2443. // Mark both, the source and the target, as un-flushable because the
  2444. // shared unoptimized code makes them impossible to enqueue in a list.
  2445. ASSERT(target_shared->code()->gc_metadata() == NULL);
  2446. ASSERT(source_shared->code()->gc_metadata() == NULL);
  2447. target_shared->set_dont_flush(true);
  2448. source_shared->set_dont_flush(true);
  2449. // Set the code, scope info, formal parameter count, and the length
  2450. // of the target shared function info. Set the source code of the
  2451. // target function to undefined. SetCode is only used for built-in
  2452. // constructors like String, Array, and Object, and some web code
  2453. // doesn't like seeing source code for constructors.
  2454. target_shared->ReplaceCode(source_shared->code());
  2455. target_shared->set_scope_info(source_shared->scope_info());
  2456. target_shared->set_length(source_shared->length());
  2457. target_shared->set_formal_parameter_count(
  2458. source_shared->formal_parameter_count());
  2459. target_shared->set_script(isolate->heap()->undefined_value());
  2460. // Since we don't store the source we should never optimize this.
  2461. target_shared->code()->set_optimizable(false);
  2462. // Set the code of the target function.
  2463. target->ReplaceCode(source_shared->code());
  2464. ASSERT(target->next_function_link()->IsUndefined());
  2465. // Make sure we get a fresh copy of the literal vector to avoid cross
  2466. // context contamination.
  2467. Handle<Context> context(source->context());
  2468. int number_of_literals = source->NumberOfLiterals();
  2469. Handle<FixedArray> literals =
  2470. isolate->factory()->NewFixedArray(number_of_literals, TENURED);
  2471. if (number_of_literals > 0) {
  2472. literals->set(JSFunction::kLiteralNativeContextIndex,
  2473. context->native_context());
  2474. }
  2475. target->set_context(*context);
  2476. target->set_literals(*literals);
  2477. if (isolate->logger()->is_logging_code_events() ||
  2478. isolate->cpu_profiler()->is_profiling()) {
  2479. isolate->logger()->LogExistingFunction(
  2480. source_shared, Handle<Code>(source_shared->code()));
  2481. }
  2482. return *target;
  2483. }
  2484. RUNTIME_FUNCTION(MaybeObject*, Runtime_SetExpectedNumberOfProperties) {
  2485. HandleScope scope(isolate);
  2486. ASSERT(args.length() == 2);
  2487. CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
  2488. CONVERT_SMI_ARG_CHECKED(num, 1);
  2489. RUNTIME_ASSERT(num >= 0);
  2490. SetExpectedNofProperties(function, num);
  2491. return isolate->heap()->undefined_value();
  2492. }
  2493. RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSGeneratorObject) {
  2494. SealHandleScope shs(isolate);
  2495. ASSERT(args.length() == 0);
  2496. JavaScriptFrameIterator it(isolate);
  2497. JavaScriptFrame* frame = it.frame();
  2498. JSFunction* function = frame->function();
  2499. RUNTIME_ASSERT(function->shared()->is_generator());
  2500. JSGeneratorObject* generator;
  2501. if (frame->IsConstructor()) {
  2502. generator = JSGeneratorObject::cast(frame->receiver());
  2503. } else {
  2504. MaybeObject* maybe_generator =
  2505. isolate->heap()->AllocateJSGeneratorObject(function);
  2506. if (!maybe_generator->To(&generator)) return maybe_generator;
  2507. }
  2508. generator->set_function(function);
  2509. generator->set_context(Context::cast(frame->context()));
  2510. generator->set_receiver(frame->receiver());
  2511. generator->set_continuation(0);
  2512. generator->set_operand_stack(isolate->heap()->empty_fixed_array());
  2513. generator->set_stack_handler_index(-1);
  2514. return generator;
  2515. }
  2516. RUNTIME_FUNCTION(MaybeObject*, Runtime_SuspendJSGeneratorObject) {
  2517. SealHandleScope shs(isolate);
  2518. ASSERT(args.length() == 1);
  2519. CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
  2520. JavaScriptFrameIterator stack_iterator(isolate);
  2521. JavaScriptFrame* frame = stack_iterator.frame();
  2522. RUNTIME_ASSERT(frame->function()->shared()->is_generator());
  2523. ASSERT_EQ(frame->function(), generator_object->function());
  2524. // The caller should have saved the context and continuation already.
  2525. ASSERT_EQ(generator_object->context(), Context::cast(frame->context()));
  2526. ASSERT_LT(0, generator_object->continuation());
  2527. // We expect there to be at least two values on the operand stack: the return
  2528. // value of the yield expression, and the argument to this runtime call.
  2529. // Neither of those should be saved.
  2530. int operands_count = frame->ComputeOperandsCount();
  2531. ASSERT_GE(operands_count, 2);
  2532. operands_count -= 2;
  2533. if (operands_count == 0) {
  2534. // Although it's semantically harmless to call this function with an
  2535. // operands_count of zero, it is also unnecessary.
  2536. ASSERT_EQ(generator_object->operand_stack(),
  2537. isolate->heap()->empty_fixed_array());
  2538. ASSERT_EQ(generator_object->stack_handler_index(), -1);
  2539. // If there are no operands on the stack, there shouldn't be a handler
  2540. // active either.
  2541. ASSERT(!frame->HasHandler());
  2542. } else {
  2543. int stack_handler_index = -1;
  2544. MaybeObject* alloc = isolate->heap()->AllocateFixedArray(operands_count);
  2545. FixedArray* operand_stack;
  2546. if (!alloc->To(&operand_stack)) return alloc;
  2547. frame->SaveOperandStack(operand_stack, &stack_handler_index);
  2548. generator_object->set_operand_stack(operand_stack);
  2549. generator_object->set_stack_handler_index(stack_handler_index);
  2550. }
  2551. return isolate->heap()->undefined_value();
  2552. }
  2553. // Note that this function is the slow path for resuming generators. It is only
  2554. // called if the suspended activation had operands on the stack, stack handlers
  2555. // needing rewinding, or if the resume should throw an exception. The fast path
  2556. // is handled directly in FullCodeGenerator::EmitGeneratorResume(), which is
  2557. // inlined into GeneratorNext and GeneratorThrow. EmitGeneratorResumeResume is
  2558. // called in any case, as it needs to reconstruct the stack frame and make space
  2559. // for arguments and operands.
  2560. RUNTIME_FUNCTION(MaybeObject*, Runtime_ResumeJSGeneratorObject) {
  2561. SealHandleScope shs(isolate);
  2562. ASSERT(args.length() == 3);
  2563. CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
  2564. CONVERT_ARG_CHECKED(Object, value, 1);
  2565. CONVERT_SMI_ARG_CHECKED(resume_mode_int, 2);
  2566. JavaScriptFrameIterator stack_iterator(isolate);
  2567. JavaScriptFrame* frame = stack_iterator.frame();
  2568. ASSERT_EQ(frame->function(), generator_object->function());
  2569. ASSERT(frame->function()->is_compiled());
  2570. STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting <= 0);
  2571. STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed <= 0);
  2572. Address pc = generator_object->function()->code()->instruction_start();
  2573. int offset = generator_object->continuation();
  2574. ASSERT(offset > 0);
  2575. frame->set_pc(pc + offset);
  2576. generator_object->set_continuation(JSGeneratorObject::kGeneratorExecuting);
  2577. FixedArray* operand_stack = generator_object->operand_stack();
  2578. int operands_count = operand_stack->length();
  2579. if (operands_count != 0) {
  2580. frame->RestoreOperandStack(operand_stack,
  2581. generator_object->stack_handler_index());
  2582. generator_object->set_operand_stack(isolate->heap()->empty_fixed_array());
  2583. generator_object->set_stack_handler_index(-1);
  2584. }
  2585. JSGeneratorObject::ResumeMode resume_mode =
  2586. static_cast<JSGeneratorObject::ResumeMode>(resume_mode_int);
  2587. switch (resume_mode) {
  2588. case JSGeneratorObject::NEXT:
  2589. return value;
  2590. case JSGeneratorObject::THROW:
  2591. return isolate->Throw(value);
  2592. }
  2593. UNREACHABLE();
  2594. return isolate->ThrowIllegalOperation();
  2595. }
  2596. RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowGeneratorStateError) {
  2597. HandleScope scope(isolate);
  2598. ASSERT(args.length() == 1);
  2599. CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
  2600. int continuation = generator->continuation();
  2601. const char* message = continuation == JSGeneratorObject::kGeneratorClosed ?
  2602. "generator_finished" : "generator_running";
  2603. Vector< Handle<Object> > argv = HandleVector<Object>(NULL, 0);
  2604. Handle<Object> error = isolate->factory()->NewError(message, argv);
  2605. return isolate->Throw(*error);
  2606. }
  2607. RUNTIME_FUNCTION(MaybeObject*, Runtime_ObjectFreeze) {
  2608. SealHandleScope shs(isolate);
  2609. ASSERT(args.length() == 1);
  2610. CONVERT_ARG_CHECKED(JSObject, object, 0);
  2611. return object->Freeze(isolate);
  2612. }
  2613. MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate,
  2614. Object* char_code) {
  2615. if (char_code->IsNumber()) {
  2616. return isolate->heap()->LookupSingleCharacterStringFromCode(
  2617. NumberToUint32(char_code) & 0xffff);
  2618. }
  2619. return isolate->heap()->empty_string();
  2620. }
  2621. RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCharCodeAt) {
  2622. SealHandleScope shs(isolate);
  2623. ASSERT(args.length() == 2);
  2624. CONVERT_ARG_CHECKED(String, subject, 0);
  2625. CONVERT_NUMBER_CHECKED(uint32_t, i, Uint32, args[1]);
  2626. // Flatten the string. If someone wants to get a char at an index
  2627. // in a cons string, it is likely that more indices will be
  2628. // accessed.
  2629. Object* flat;
  2630. { MaybeObject* maybe_flat = subject->TryFlatten();
  2631. if (!maybe_flat->ToObject(&flat)) return maybe_flat;
  2632. }
  2633. subject = String::cast(flat);
  2634. if (i >= static_cast<uint32_t>(subject->length())) {
  2635. return isolate->heap()->nan_value();
  2636. }
  2637. return Smi::FromInt(subject->Get(i));
  2638. }
  2639. RUNTIME_FUNCTION(MaybeObject*, Runtime_CharFromCode) {
  2640. SealHandleScope shs(isolate);
  2641. ASSERT(args.length() == 1);
  2642. return CharFromCode(isolate, args[0]);
  2643. }
  2644. class FixedArrayBuilder {
  2645. public:
  2646. explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity)
  2647. : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)),
  2648. length_(0),
  2649. has_non_smi_elements_(false) {
  2650. // Require a non-zero initial size. Ensures that doubling the size to
  2651. // extend the array will work.
  2652. ASSERT(initial_capacity > 0);
  2653. }
  2654. explicit FixedArrayBuilder(Handle<FixedArray> backing_store)
  2655. : array_(backing_store),
  2656. length_(0),
  2657. has_non_smi_elements_(false) {
  2658. // Require a non-zero initial size. Ensures that doubling the size to
  2659. // extend the array will work.
  2660. ASSERT(backing_store->length() > 0);
  2661. }
  2662. bool HasCapacity(int elements) {
  2663. int length = array_->length();
  2664. int required_length = length_ + elements;
  2665. return (length >= required_length);
  2666. }
  2667. void EnsureCapacity(int elements) {
  2668. int length = array_->length();
  2669. int required_length = length_ + elements;
  2670. if (length < required_length) {
  2671. int new_length = length;
  2672. do {
  2673. new_length *= 2;
  2674. } while (new_length < required_length);
  2675. Handle<FixedArray> extended_array =
  2676. array_->GetIsolate()->factory()->NewFixedArrayWithHoles(new_length);
  2677. array_->CopyTo(0, *extended_array, 0, length_);
  2678. array_ = extended_array;
  2679. }
  2680. }
  2681. void Add(Object* value) {
  2682. ASSERT(!value->IsSmi());
  2683. ASSERT(length_ < capacity());
  2684. array_->set(length_, value);
  2685. length_++;
  2686. has_non_smi_elements_ = true;
  2687. }
  2688. void Add(Smi* value) {
  2689. ASSERT(value->IsSmi());
  2690. ASSERT(length_ < capacity());
  2691. array_->set(length_, value);
  2692. length_++;
  2693. }
  2694. Handle<FixedArray> array() {
  2695. return array_;
  2696. }
  2697. int length() {
  2698. return length_;
  2699. }
  2700. int capacity() {
  2701. return array_->length();
  2702. }
  2703. Handle<JSArray> ToJSArray(Handle<JSArray> target_array) {
  2704. Factory* factory = target_array->GetIsolate()->factory();
  2705. factory->SetContent(target_array, array_);
  2706. target_array->set_length(Smi::FromInt(length_));
  2707. return target_array;
  2708. }
  2709. private:
  2710. Handle<FixedArray> array_;
  2711. int length_;
  2712. bool has_non_smi_elements_;
  2713. };
  2714. // Forward declarations.
  2715. const int kStringBuilderConcatHelperLengthBits = 11;
  2716. const int kStringBuilderConcatHelperPositionBits = 19;
  2717. template <typename schar>
  2718. static inline void StringBuilderConcatHelper(String*,
  2719. schar*,
  2720. FixedArray*,
  2721. int);
  2722. typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits>
  2723. StringBuilderSubstringLength;
  2724. typedef BitField<int,
  2725. kStringBuilderConcatHelperLengthBits,
  2726. kStringBuilderConcatHelperPositionBits>
  2727. StringBuilderSubstringPosition;
  2728. class ReplacementStringBuilder {
  2729. public:
  2730. ReplacementStringBuilder(Heap* heap,
  2731. Handle<String> subject,
  2732. int estimated_part_count)
  2733. : heap_(heap),
  2734. array_builder_(heap->isolate(), estimated_part_count),
  2735. subject_(subject),
  2736. character_count_(0),
  2737. is_ascii_(subject->IsOneByteRepresentation()) {
  2738. // Require a non-zero initial size. Ensures that doubling the size to
  2739. // extend the array will work.
  2740. ASSERT(estimated_part_count > 0);
  2741. }
  2742. static inline void AddSubjectSlice(FixedArrayBuilder* builder,
  2743. int from,
  2744. int to) {
  2745. ASSERT(from >= 0);
  2746. int length = to - from;
  2747. ASSERT(length > 0);
  2748. if (StringBuilderSubstringLength::is_valid(length) &&
  2749. StringBuilderSubstringPosition::is_valid(from)) {
  2750. int encoded_slice = StringBuilderSubstringLength::encode(length) |
  2751. StringBuilderSubstringPosition::encode(from);
  2752. builder->Add(Smi::FromInt(encoded_slice));
  2753. } else {
  2754. // Otherwise encode as two smis.
  2755. builder->Add(Smi::FromInt(-length));
  2756. builder->Add(Smi::FromInt(from));
  2757. }
  2758. }
  2759. void EnsureCapacity(int elements) {
  2760. array_builder_.EnsureCapacity(elements);
  2761. }
  2762. void AddSubjectSlice(int from, int to) {
  2763. AddSubjectSlice(&array_builder_, from, to);
  2764. IncrementCharacterCount(to - from);
  2765. }
  2766. void AddString(Handle<String> string) {
  2767. int length = string->length();
  2768. ASSERT(length > 0);
  2769. AddElement(*string);
  2770. if (!string->IsOneByteRepresentation()) {
  2771. is_ascii_ = false;
  2772. }
  2773. IncrementCharacterCount(length);
  2774. }
  2775. Handle<String> ToString() {
  2776. if (array_builder_.length() == 0) {
  2777. return heap_->isolate()->factory()->empty_string();
  2778. }
  2779. Handle<String> joined_string;
  2780. if (is_ascii_) {
  2781. Handle<SeqOneByteString> seq = NewRawOneByteString(character_count_);
  2782. DisallowHeapAllocation no_gc;
  2783. uint8_t* char_buffer = seq->GetChars();
  2784. StringBuilderConcatHelper(*subject_,
  2785. char_buffer,
  2786. *array_builder_.array(),
  2787. array_builder_.length());
  2788. joined_string = Handle<String>::cast(seq);
  2789. } else {
  2790. // Non-ASCII.
  2791. Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_);
  2792. DisallowHeapAllocation no_gc;
  2793. uc16* char_buffer = seq->GetChars();
  2794. StringBuilderConcatHelper(*subject_,
  2795. char_buffer,
  2796. *array_builder_.array(),
  2797. array_builder_.length());
  2798. joined_string = Handle<String>::cast(seq);
  2799. }
  2800. return joined_string;
  2801. }
  2802. void IncrementCharacterCount(int by) {
  2803. if (character_count_ > String::kMaxLength - by) {
  2804. V8::FatalProcessOutOfMemory("String.replace result too large.");
  2805. }
  2806. character_count_ += by;
  2807. }
  2808. private:
  2809. Handle<SeqOneByteString> NewRawOneByteString(int length) {
  2810. return heap_->isolate()->factory()->NewRawOneByteString(length);
  2811. }
  2812. Handle<SeqTwoByteString> NewRawTwoByteString(int length) {
  2813. return heap_->isolate()->factory()->NewRawTwoByteString(length);
  2814. }
  2815. void AddElement(Object* element) {
  2816. ASSERT(element->IsSmi() || element->IsString());
  2817. ASSERT(array_builder_.capacity() > array_builder_.length());
  2818. array_builder_.Add(element);
  2819. }
  2820. Heap* heap_;
  2821. FixedArrayBuilder array_builder_;
  2822. Handle<String> subject_;
  2823. int character_count_;
  2824. bool is_ascii_;
  2825. };
  2826. class CompiledReplacement {
  2827. public:
  2828. explicit CompiledReplacement(Zone* zone)
  2829. : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {}
  2830. // Return whether the replacement is simple.
  2831. bool Compile(Handle<String> replacement,
  2832. int capture_count,
  2833. int subject_length);
  2834. // Use Apply only if Compile returned false.
  2835. void Apply(ReplacementStringBuilder* builder,
  2836. int match_from,
  2837. int match_to,
  2838. int32_t* match);
  2839. // Number of distinct parts of the replacement pattern.
  2840. int parts() {
  2841. return parts_.length();
  2842. }
  2843. Zone* zone() const { return zone_; }
  2844. private:
  2845. enum PartType {
  2846. SUBJECT_PREFIX = 1,
  2847. SUBJECT_SUFFIX,
  2848. SUBJECT_CAPTURE,
  2849. REPLACEMENT_SUBSTRING,
  2850. REPLACEMENT_STRING,
  2851. NUMBER_OF_PART_TYPES
  2852. };
  2853. struct ReplacementPart {
  2854. static inline ReplacementPart SubjectMatch() {
  2855. return ReplacementPart(SUBJECT_CAPTURE, 0);
  2856. }
  2857. static inline ReplacementPart SubjectCapture(int capture_index) {
  2858. return ReplacementPart(SUBJECT_CAPTURE, capture_index);
  2859. }
  2860. static inline ReplacementPart SubjectPrefix() {
  2861. return ReplacementPart(SUBJECT_PREFIX, 0);
  2862. }
  2863. static inline ReplacementPart SubjectSuffix(int subject_length) {
  2864. return ReplacementPart(SUBJECT_SUFFIX, subject_length);
  2865. }
  2866. static inline ReplacementPart ReplacementString() {
  2867. return ReplacementPart(REPLACEMENT_STRING, 0);
  2868. }
  2869. static inline ReplacementPart ReplacementSubString(int from, int to) {
  2870. ASSERT(from >= 0);
  2871. ASSERT(to > from);
  2872. return ReplacementPart(-from, to);
  2873. }
  2874. // If tag <= 0 then it is the negation of a start index of a substring of
  2875. // the replacement pattern, otherwise it's a value from PartType.
  2876. ReplacementPart(int tag, int data)
  2877. : tag(tag), data(data) {
  2878. // Must be non-positive or a PartType value.
  2879. ASSERT(tag < NUMBER_OF_PART_TYPES);
  2880. }
  2881. // Either a value of PartType or a non-positive number that is
  2882. // the negation of an index into the replacement string.
  2883. int tag;
  2884. // The data value's interpretation depends on the value of tag:
  2885. // tag == SUBJECT_PREFIX ||
  2886. // tag == SUBJECT_SUFFIX: data is unused.
  2887. // tag == SUBJECT_CAPTURE: data is the number of the capture.
  2888. // tag == REPLACEMENT_SUBSTRING ||
  2889. // tag == REPLACEMENT_STRING: data is index into array of substrings
  2890. // of the replacement string.
  2891. // tag <= 0: Temporary representation of the substring of the replacement
  2892. // string ranging over -tag .. data.
  2893. // Is replaced by REPLACEMENT_{SUB,}STRING when we create the
  2894. // substring objects.
  2895. int data;
  2896. };
  2897. template<typename Char>
  2898. bool ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
  2899. Vector<Char> characters,
  2900. int capture_count,
  2901. int subject_length,
  2902. Zone* zone) {
  2903. int length = characters.length();
  2904. int last = 0;
  2905. for (int i = 0; i < length; i++) {
  2906. Char c = characters[i];
  2907. if (c == '$') {
  2908. int next_index = i + 1;
  2909. if (next_index == length) { // No next character!
  2910. break;
  2911. }
  2912. Char c2 = characters[next_index];
  2913. switch (c2) {
  2914. case '$':
  2915. if (i > last) {
  2916. // There is a substring before. Include the first "$".
  2917. parts->Add(ReplacementPart::ReplacementSubString(last, next_index),
  2918. zone);
  2919. last = next_index + 1; // Continue after the second "$".
  2920. } else {
  2921. // Let the next substring start with the second "$".
  2922. last = next_index;
  2923. }
  2924. i = next_index;
  2925. break;
  2926. case '`':
  2927. if (i > last) {
  2928. parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
  2929. }
  2930. parts->Add(ReplacementPart::SubjectPrefix(), zone);
  2931. i = next_index;
  2932. last = i + 1;
  2933. break;
  2934. case '\'':
  2935. if (i > last) {
  2936. parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
  2937. }
  2938. parts->Add(ReplacementPart::SubjectSuffix(subject_length), zone);
  2939. i = next_index;
  2940. last = i + 1;
  2941. break;
  2942. case '&':
  2943. if (i > last) {
  2944. parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
  2945. }
  2946. parts->Add(ReplacementPart::SubjectMatch(), zone);
  2947. i = next_index;
  2948. last = i + 1;
  2949. break;
  2950. case '0':
  2951. case '1':
  2952. case '2':
  2953. case '3':
  2954. case '4':
  2955. case '5':
  2956. case '6':
  2957. case '7':
  2958. case '8':
  2959. case '9': {
  2960. int capture_ref = c2 - '0';
  2961. if (capture_ref > capture_count) {
  2962. i = next_index;
  2963. continue;
  2964. }
  2965. int second_digit_index = next_index + 1;
  2966. if (second_digit_index < length) {
  2967. // Peek ahead to see if we have two digits.
  2968. Char c3 = characters[second_digit_index];
  2969. if ('0' <= c3 && c3 <= '9') { // Double digits.
  2970. int double_digit_ref = capture_ref * 10 + c3 - '0';
  2971. if (double_digit_ref <= capture_count) {
  2972. next_index = second_digit_index;
  2973. capture_ref = double_digit_ref;
  2974. }
  2975. }
  2976. }
  2977. if (capture_ref > 0) {
  2978. if (i > last) {
  2979. parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
  2980. }
  2981. ASSERT(capture_ref <= capture_count);
  2982. parts->Add(ReplacementPart::SubjectCapture(capture_ref), zone);
  2983. last = next_index + 1;
  2984. }
  2985. i = next_index;
  2986. break;
  2987. }
  2988. default:
  2989. i = next_index;
  2990. break;
  2991. }
  2992. }
  2993. }
  2994. if (length > last) {
  2995. if (last == 0) {
  2996. // Replacement is simple. Do not use Apply to do the replacement.
  2997. return true;
  2998. } else {
  2999. parts->Add(ReplacementPart::ReplacementSubString(last, length), zone);
  3000. }
  3001. }
  3002. return false;
  3003. }
  3004. ZoneList<ReplacementPart> parts_;
  3005. ZoneList<Handle<String> > replacement_substrings_;
  3006. Zone* zone_;
  3007. };
  3008. bool CompiledReplacement::Compile(Handle<String> replacement,
  3009. int capture_count,
  3010. int subject_length) {
  3011. {
  3012. DisallowHeapAllocation no_gc;
  3013. String::FlatContent content = replacement->GetFlatContent();
  3014. ASSERT(content.IsFlat());
  3015. bool simple = false;
  3016. if (content.IsAscii()) {
  3017. simple = ParseReplacementPattern(&parts_,
  3018. content.ToOneByteVector(),
  3019. capture_count,
  3020. subject_length,
  3021. zone());
  3022. } else {
  3023. ASSERT(content.IsTwoByte());
  3024. simple = ParseReplacementPattern(&parts_,
  3025. content.ToUC16Vector(),
  3026. capture_count,
  3027. subject_length,
  3028. zone());
  3029. }
  3030. if (simple) return true;
  3031. }
  3032. Isolate* isolate = replacement->GetIsolate();
  3033. // Find substrings of replacement string and create them as String objects.
  3034. int substring_index = 0;
  3035. for (int i = 0, n = parts_.length(); i < n; i++) {
  3036. int tag = parts_[i].tag;
  3037. if (tag <= 0) { // A replacement string slice.
  3038. int from = -tag;
  3039. int to = parts_[i].data;
  3040. replacement_substrings_.Add(
  3041. isolate->factory()->NewSubString(replacement, from, to), zone());
  3042. parts_[i].tag = REPLACEMENT_SUBSTRING;
  3043. parts_[i].data = substring_index;
  3044. substring_index++;
  3045. } else if (tag == REPLACEMENT_STRING) {
  3046. replacement_substrings_.Add(replacement, zone());
  3047. parts_[i].data = substring_index;
  3048. substring_index++;
  3049. }
  3050. }
  3051. return false;
  3052. }
  3053. void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
  3054. int match_from,
  3055. int match_to,
  3056. int32_t* match) {
  3057. ASSERT_LT(0, parts_.length());
  3058. for (int i = 0, n = parts_.length(); i < n; i++) {
  3059. ReplacementPart part = parts_[i];
  3060. switch (part.tag) {
  3061. case SUBJECT_PREFIX:
  3062. if (match_from > 0) builder->AddSubjectSlice(0, match_from);
  3063. break;
  3064. case SUBJECT_SUFFIX: {
  3065. int subject_length = part.data;
  3066. if (match_to < subject_length) {
  3067. builder->AddSubjectSlice(match_to, subject_length);
  3068. }
  3069. break;
  3070. }
  3071. case SUBJECT_CAPTURE: {
  3072. int capture = part.data;
  3073. int from = match[capture * 2];
  3074. int to = match[capture * 2 + 1];
  3075. if (from >= 0 && to > from) {
  3076. builder->AddSubjectSlice(from, to);
  3077. }
  3078. break;
  3079. }
  3080. case REPLACEMENT_SUBSTRING:
  3081. case REPLACEMENT_STRING:
  3082. builder->AddString(replacement_substrings_[part.data]);
  3083. break;
  3084. default:
  3085. UNREACHABLE();
  3086. }
  3087. }
  3088. }
  3089. void FindAsciiStringIndices(Vector<const uint8_t> subject,
  3090. char pattern,
  3091. ZoneList<int>* indices,
  3092. unsigned int limit,
  3093. Zone* zone) {
  3094. ASSERT(limit > 0);
  3095. // Collect indices of pattern in subject using memchr.
  3096. // Stop after finding at most limit values.
  3097. const uint8_t* subject_start = subject.start();
  3098. const uint8_t* subject_end = subject_start + subject.length();
  3099. const uint8_t* pos = subject_start;
  3100. while (limit > 0) {
  3101. pos = reinterpret_cast<const uint8_t*>(
  3102. memchr(pos, pattern, subject_end - pos));
  3103. if (pos == NULL) return;
  3104. indices->Add(static_cast<int>(pos - subject_start), zone);
  3105. pos++;
  3106. limit--;
  3107. }
  3108. }
  3109. void FindTwoByteStringIndices(const Vector<const uc16> subject,
  3110. uc16 pattern,
  3111. ZoneList<int>* indices,
  3112. unsigned int limit,
  3113. Zone* zone) {
  3114. ASSERT(limit > 0);
  3115. const uc16* subject_start = subject.start();
  3116. const uc16* subject_end = subject_start + subject.length();
  3117. for (const uc16* pos = subject_start; pos < subject_end && limit > 0; pos++) {
  3118. if (*pos == pattern) {
  3119. indices->Add(static_cast<int>(pos - subject_start), zone);
  3120. limit--;
  3121. }
  3122. }
  3123. }
  3124. template <typename SubjectChar, typename PatternChar>
  3125. void FindStringIndices(Isolate* isolate,
  3126. Vector<const SubjectChar> subject,
  3127. Vector<const PatternChar> pattern,
  3128. ZoneList<int>* indices,
  3129. unsigned int limit,
  3130. Zone* zone) {
  3131. ASSERT(limit > 0);
  3132. // Collect indices of pattern in subject.
  3133. // Stop after finding at most limit values.
  3134. int pattern_length = pattern.length();
  3135. int index = 0;
  3136. StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
  3137. while (limit > 0) {
  3138. index = search.Search(subject, index);
  3139. if (index < 0) return;
  3140. indices->Add(index, zone);
  3141. index += pattern_length;
  3142. limit--;
  3143. }
  3144. }
  3145. void FindStringIndicesDispatch(Isolate* isolate,
  3146. String* subject,
  3147. String* pattern,
  3148. ZoneList<int>* indices,
  3149. unsigned int limit,
  3150. Zone* zone) {
  3151. {
  3152. DisallowHeapAllocation no_gc;
  3153. String::FlatContent subject_content = subject->GetFlatContent();
  3154. String::FlatContent pattern_content = pattern->GetFlatContent();
  3155. ASSERT(subject_content.IsFlat());
  3156. ASSERT(pattern_content.IsFlat());
  3157. if (subject_content.IsAscii()) {
  3158. Vector<const uint8_t> subject_vector = subject_content.ToOneByteVector();
  3159. if (pattern_content.IsAscii()) {
  3160. Vector<const uint8_t> pattern_vector =
  3161. pattern_content.ToOneByteVector();
  3162. if (pattern_vector.length() == 1) {
  3163. FindAsciiStringIndices(subject_vector,
  3164. pattern_vector[0],
  3165. indices,
  3166. limit,
  3167. zone);
  3168. } else {
  3169. FindStringIndices(isolate,
  3170. subject_vector,
  3171. pattern_vector,
  3172. indices,
  3173. limit,
  3174. zone);
  3175. }
  3176. } else {
  3177. FindStringIndices(isolate,
  3178. subject_vector,
  3179. pattern_content.ToUC16Vector(),
  3180. indices,
  3181. limit,
  3182. zone);
  3183. }
  3184. } else {
  3185. Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
  3186. if (pattern_content.IsAscii()) {
  3187. Vector<const uint8_t> pattern_vector =
  3188. pattern_content.ToOneByteVector();
  3189. if (pattern_vector.length() == 1) {
  3190. FindTwoByteStringIndices(subject_vector,
  3191. pattern_vector[0],
  3192. indices,
  3193. limit,
  3194. zone);
  3195. } else {
  3196. FindStringIndices(isolate,
  3197. subject_vector,
  3198. pattern_vector,
  3199. indices,
  3200. limit,
  3201. zone);
  3202. }
  3203. } else {
  3204. Vector<const uc16> pattern_vector = pattern_content.ToUC16Vector();
  3205. if (pattern_vector.length() == 1) {
  3206. FindTwoByteStringIndices(subject_vector,
  3207. pattern_vector[0],
  3208. indices,
  3209. limit,
  3210. zone);
  3211. } else {
  3212. FindStringIndices(isolate,
  3213. subject_vector,
  3214. pattern_vector,
  3215. indices,
  3216. limit,
  3217. zone);
  3218. }
  3219. }
  3220. }
  3221. }
  3222. }
  3223. template<typename ResultSeqString>
  3224. MUST_USE_RESULT static MaybeObject* StringReplaceGlobalAtomRegExpWithString(
  3225. Isolate* isolate,
  3226. Handle<String> subject,
  3227. Handle<JSRegExp> pattern_regexp,
  3228. Handle<String> replacement,
  3229. Handle<JSArray> last_match_info) {
  3230. ASSERT(subject->IsFlat());
  3231. ASSERT(replacement->IsFlat());
  3232. ZoneScope zone_scope(isolate->runtime_zone());
  3233. ZoneList<int> indices(8, zone_scope.zone());
  3234. ASSERT_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag());
  3235. String* pattern =
  3236. String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex));
  3237. int subject_len = subject->length();
  3238. int pattern_len = pattern->length();
  3239. int replacement_len = replacement->length();
  3240. FindStringIndicesDispatch(
  3241. isolate, *subject, pattern, &indices, 0xffffffff, zone_scope.zone());
  3242. int matches = indices.length();
  3243. if (matches == 0) return *subject;
  3244. // Detect integer overflow.
  3245. int64_t result_len_64 =
  3246. (static_cast<int64_t>(replacement_len) -
  3247. static_cast<int64_t>(pattern_len)) *
  3248. static_cast<int64_t>(matches) +
  3249. static_cast<int64_t>(subject_len);
  3250. if (result_len_64 > INT_MAX) return Failure::OutOfMemoryException(0x11);
  3251. int result_len = static_cast<int>(result_len_64);
  3252. int subject_pos = 0;
  3253. int result_pos = 0;
  3254. Handle<ResultSeqString> result;
  3255. if (ResultSeqString::kHasAsciiEncoding) {
  3256. result = Handle<ResultSeqString>::cast(
  3257. isolate->factory()->NewRawOneByteString(result_len));
  3258. } else {
  3259. result = Handle<ResultSeqString>::cast(
  3260. isolate->factory()->NewRawTwoByteString(result_len));
  3261. }
  3262. for (int i = 0; i < matches; i++) {
  3263. // Copy non-matched subject content.
  3264. if (subject_pos < indices.at(i)) {
  3265. String::WriteToFlat(*subject,
  3266. result->GetChars() + result_pos,
  3267. subject_pos,
  3268. indices.at(i));
  3269. result_pos += indices.at(i) - subject_pos;
  3270. }
  3271. // Replace match.
  3272. if (replacement_len > 0) {
  3273. String::WriteToFlat(*replacement,
  3274. result->GetChars() + result_pos,
  3275. 0,
  3276. replacement_len);
  3277. result_pos += replacement_len;
  3278. }
  3279. subject_pos = indices.at(i) + pattern_len;
  3280. }
  3281. // Add remaining subject content at the end.
  3282. if (subject_pos < subject_len) {
  3283. String::WriteToFlat(*subject,
  3284. result->GetChars() + result_pos,
  3285. subject_pos,
  3286. subject_len);
  3287. }
  3288. int32_t match_indices[] = { indices.at(matches - 1),
  3289. indices.at(matches - 1) + pattern_len };
  3290. RegExpImpl::SetLastMatchInfo(last_match_info, subject, 0, match_indices);
  3291. return *result;
  3292. }
  3293. MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithString(
  3294. Isolate* isolate,
  3295. Handle<String> subject,
  3296. Handle<JSRegExp> regexp,
  3297. Handle<String> replacement,
  3298. Handle<JSArray> last_match_info) {
  3299. ASSERT(subject->IsFlat());
  3300. ASSERT(replacement->IsFlat());
  3301. int capture_count = regexp->CaptureCount();
  3302. int subject_length = subject->length();
  3303. // CompiledReplacement uses zone allocation.
  3304. ZoneScope zone_scope(isolate->runtime_zone());
  3305. CompiledReplacement compiled_replacement(zone_scope.zone());
  3306. bool simple_replace = compiled_replacement.Compile(replacement,
  3307. capture_count,
  3308. subject_length);
  3309. // Shortcut for simple non-regexp global replacements
  3310. if (regexp->TypeTag() == JSRegExp::ATOM && simple_replace) {
  3311. if (subject->HasOnlyOneByteChars() &&
  3312. replacement->HasOnlyOneByteChars()) {
  3313. return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
  3314. isolate, subject, regexp, replacement, last_match_info);
  3315. } else {
  3316. return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>(
  3317. isolate, subject, regexp, replacement, last_match_info);
  3318. }
  3319. }
  3320. RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
  3321. if (global_cache.HasException()) return Failure::Exception();
  3322. int32_t* current_match = global_cache.FetchNext();
  3323. if (current_match == NULL) {
  3324. if (global_cache.HasException()) return Failure::Exception();
  3325. return *subject;
  3326. }
  3327. // Guessing the number of parts that the final result string is built
  3328. // from. Global regexps can match any number of times, so we guess
  3329. // conservatively.
  3330. int expected_parts = (compiled_replacement.parts() + 1) * 4 + 1;
  3331. ReplacementStringBuilder builder(isolate->heap(),
  3332. subject,
  3333. expected_parts);
  3334. // Number of parts added by compiled replacement plus preceeding
  3335. // string and possibly suffix after last match. It is possible for
  3336. // all components to use two elements when encoded as two smis.
  3337. const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2);
  3338. int prev = 0;
  3339. do {
  3340. builder.EnsureCapacity(parts_added_per_loop);
  3341. int start = current_match[0];
  3342. int end = current_match[1];
  3343. if (prev < start) {
  3344. builder.AddSubjectSlice(prev, start);
  3345. }
  3346. if (simple_replace) {
  3347. builder.AddString(replacement);
  3348. } else {
  3349. compiled_replacement.Apply(&builder,
  3350. start,
  3351. end,
  3352. current_match);
  3353. }
  3354. prev = end;
  3355. current_match = global_cache.FetchNext();
  3356. } while (current_match != NULL);
  3357. if (global_cache.HasException()) return Failure::Exception();
  3358. if (prev < subject_length) {
  3359. builder.EnsureCapacity(2);
  3360. builder.AddSubjectSlice(prev, subject_length);
  3361. }
  3362. RegExpImpl::SetLastMatchInfo(last_match_info,
  3363. subject,
  3364. capture_count,
  3365. global_cache.LastSuccessfulMatch());
  3366. return *(builder.ToString());
  3367. }
  3368. template <typename ResultSeqString>
  3369. MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithEmptyString(
  3370. Isolate* isolate,
  3371. Handle<String> subject,
  3372. Handle<JSRegExp> regexp,
  3373. Handle<JSArray> last_match_info) {
  3374. ASSERT(subject->IsFlat());
  3375. // Shortcut for simple non-regexp global replacements
  3376. if (regexp->TypeTag() == JSRegExp::ATOM) {
  3377. Handle<String> empty_string = isolate->factory()->empty_string();
  3378. if (subject->IsOneByteRepresentation()) {
  3379. return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
  3380. isolate, subject, regexp, empty_string, last_match_info);
  3381. } else {
  3382. return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>(
  3383. isolate, subject, regexp, empty_string, last_match_info);
  3384. }
  3385. }
  3386. RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
  3387. if (global_cache.HasException()) return Failure::Exception();
  3388. int32_t* current_match = global_cache.FetchNext();
  3389. if (current_match == NULL) {
  3390. if (global_cache.HasException()) return Failure::Exception();
  3391. return *subject;
  3392. }
  3393. int start = current_match[0];
  3394. int end = current_match[1];
  3395. int capture_count = regexp->CaptureCount();
  3396. int subject_length = subject->length();
  3397. int new_length = subject_length - (end - start);
  3398. if (new_length == 0) return isolate->heap()->empty_string();
  3399. Handle<ResultSeqString> answer;
  3400. if (ResultSeqString::kHasAsciiEncoding) {
  3401. answer = Handle<ResultSeqString>::cast(
  3402. isolate->factory()->NewRawOneByteString(new_length));
  3403. } else {
  3404. answer = Handle<ResultSeqString>::cast(
  3405. isolate->factory()->NewRawTwoByteString(new_length));
  3406. }
  3407. int prev = 0;
  3408. int position = 0;
  3409. do {
  3410. start = current_match[0];
  3411. end = current_match[1];
  3412. if (prev < start) {
  3413. // Add substring subject[prev;start] to answer string.
  3414. String::WriteToFlat(*subject, answer->GetChars() + position, prev, start);
  3415. position += start - prev;
  3416. }
  3417. prev = end;
  3418. current_match = global_cache.FetchNext();
  3419. } while (current_match != NULL);
  3420. if (global_cache.HasException()) return Failure::Exception();
  3421. RegExpImpl::SetLastMatchInfo(last_match_info,
  3422. subject,
  3423. capture_count,
  3424. global_cache.LastSuccessfulMatch());
  3425. if (prev < subject_length) {
  3426. // Add substring subject[prev;length] to answer string.
  3427. String::WriteToFlat(
  3428. *subject, answer->GetChars() + position, prev, subject_length);
  3429. position += subject_length - prev;
  3430. }
  3431. if (position == 0) return isolate->heap()->empty_string();
  3432. // Shorten string and fill
  3433. int string_size = ResultSeqString::SizeFor(position);
  3434. int allocated_string_size = ResultSeqString::SizeFor(new_length);
  3435. int delta = allocated_string_size - string_size;
  3436. answer->set_length(position);
  3437. if (delta == 0) return *answer;
  3438. Address end_of_string = answer->address() + string_size;
  3439. isolate->heap()->CreateFillerObjectAt(end_of_string, delta);
  3440. if (Marking::IsBlack(Marking::MarkBitFrom(*answer))) {
  3441. MemoryChunk::IncrementLiveBytesFromMutator(answer->address(), -delta);
  3442. }
  3443. return *answer;
  3444. }
  3445. RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceGlobalRegExpWithString) {
  3446. HandleScope scope(isolate);
  3447. ASSERT(args.length() == 4);
  3448. CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
  3449. CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2);
  3450. CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
  3451. CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
  3452. ASSERT(regexp->GetFlags().is_global());
  3453. if (!subject->IsFlat()) subject = FlattenGetString(subject);
  3454. if (replacement->length() == 0) {
  3455. if (subject->HasOnlyOneByteChars()) {
  3456. return StringReplaceGlobalRegExpWithEmptyString<SeqOneByteString>(
  3457. isolate, subject, regexp, last_match_info);
  3458. } else {
  3459. return StringReplaceGlobalRegExpWithEmptyString<SeqTwoByteString>(
  3460. isolate, subject, regexp, last_match_info);
  3461. }
  3462. }
  3463. if (!replacement->IsFlat()) replacement = FlattenGetString(replacement);
  3464. return StringReplaceGlobalRegExpWithString(
  3465. isolate, subject, regexp, replacement, last_match_info);
  3466. }
  3467. Handle<String> StringReplaceOneCharWithString(Isolate* isolate,
  3468. Handle<String> subject,
  3469. Handle<String> search,
  3470. Handle<String> replace,
  3471. bool* found,
  3472. int recursion_limit) {
  3473. if (recursion_limit == 0) return Handle<String>::null();
  3474. if (subject->IsConsString()) {
  3475. ConsString* cons = ConsString::cast(*subject);
  3476. Handle<String> first = Handle<String>(cons->first());
  3477. Handle<String> second = Handle<String>(cons->second());
  3478. Handle<String> new_first =
  3479. StringReplaceOneCharWithString(isolate,
  3480. first,
  3481. search,
  3482. replace,
  3483. found,
  3484. recursion_limit - 1);
  3485. if (*found) return isolate->factory()->NewConsString(new_first, second);
  3486. if (new_first.is_null()) return new_first;
  3487. Handle<String> new_second =
  3488. StringReplaceOneCharWithString(isolate,
  3489. second,
  3490. search,
  3491. replace,
  3492. found,
  3493. recursion_limit - 1);
  3494. if (*found) return isolate->factory()->NewConsString(first, new_second);
  3495. if (new_second.is_null()) return new_second;
  3496. return subject;
  3497. } else {
  3498. int index = Runtime::StringMatch(isolate, subject, search, 0);
  3499. if (index == -1) return subject;
  3500. *found = true;
  3501. Handle<String> first = isolate->factory()->NewSubString(subject, 0, index);
  3502. Handle<String> cons1 = isolate->factory()->NewConsString(first, replace);
  3503. Handle<String> second =
  3504. isolate->factory()->NewSubString(subject, index + 1, subject->length());
  3505. return isolate->factory()->NewConsString(cons1, second);
  3506. }
  3507. }
  3508. RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) {
  3509. HandleScope scope(isolate);
  3510. ASSERT(args.length() == 3);
  3511. CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
  3512. CONVERT_ARG_HANDLE_CHECKED(String, search, 1);
  3513. CONVERT_ARG_HANDLE_CHECKED(String, replace, 2);
  3514. // If the cons string tree is too deep, we simply abort the recursion and
  3515. // retry with a flattened subject string.
  3516. const int kRecursionLimit = 0x1000;
  3517. bool found = false;
  3518. Handle<String> result = StringReplaceOneCharWithString(isolate,
  3519. subject,
  3520. search,
  3521. replace,
  3522. &found,
  3523. kRecursionLimit);
  3524. if (!result.is_null()) return *result;
  3525. return *StringReplaceOneCharWithString(isolate,
  3526. FlattenGetString(subject),
  3527. search,
  3528. replace,
  3529. &found,
  3530. kRecursionLimit);
  3531. }
  3532. // Perform string match of pattern on subject, starting at start index.
  3533. // Caller must ensure that 0 <= start_index <= sub->length(),
  3534. // and should check that pat->length() + start_index <= sub->length().
  3535. int Runtime::StringMatch(Isolate* isolate,
  3536. Handle<String> sub,
  3537. Handle<String> pat,
  3538. int start_index) {
  3539. ASSERT(0 <= start_index);
  3540. ASSERT(start_index <= sub->length());
  3541. int pattern_length = pat->length();
  3542. if (pattern_length == 0) return start_index;
  3543. int subject_length = sub->length();
  3544. if (start_index + pattern_length > subject_length) return -1;
  3545. if (!sub->IsFlat()) FlattenString(sub);
  3546. if (!pat->IsFlat()) FlattenString(pat);
  3547. DisallowHeapAllocation no_gc; // ensure vectors stay valid
  3548. // Extract flattened substrings of cons strings before determining asciiness.
  3549. String::FlatContent seq_sub = sub->GetFlatContent();
  3550. String::FlatContent seq_pat = pat->GetFlatContent();
  3551. // dispatch on type of strings
  3552. if (seq_pat.IsAscii()) {
  3553. Vector<const uint8_t> pat_vector = seq_pat.ToOneByteVector();
  3554. if (seq_sub.IsAscii()) {
  3555. return SearchString(isolate,
  3556. seq_sub.ToOneByteVector(),
  3557. pat_vector,
  3558. start_index);
  3559. }
  3560. return SearchString(isolate,
  3561. seq_sub.ToUC16Vector(),
  3562. pat_vector,
  3563. start_index);
  3564. }
  3565. Vector<const uc16> pat_vector = seq_pat.ToUC16Vector();
  3566. if (seq_sub.IsAscii()) {
  3567. return SearchString(isolate,
  3568. seq_sub.ToOneByteVector(),
  3569. pat_vector,
  3570. start_index);
  3571. }
  3572. return SearchString(isolate,
  3573. seq_sub.ToUC16Vector(),
  3574. pat_vector,
  3575. start_index);
  3576. }
  3577. RUNTIME_FUNCTION(MaybeObject*, Runtime_StringIndexOf) {
  3578. HandleScope scope(isolate);
  3579. ASSERT(args.length() == 3);
  3580. CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
  3581. CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
  3582. Object* index = args[2];
  3583. uint32_t start_index;
  3584. if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
  3585. RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
  3586. int position =
  3587. Runtime::StringMatch(isolate, sub, pat, start_index);
  3588. return Smi::FromInt(position);
  3589. }
  3590. template <typename schar, typename pchar>
  3591. static int StringMatchBackwards(Vector<const schar> subject,
  3592. Vector<const pchar> pattern,
  3593. int idx) {
  3594. int pattern_length = pattern.length();
  3595. ASSERT(pattern_length >= 1);
  3596. ASSERT(idx + pattern_length <= subject.length());
  3597. if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
  3598. for (int i = 0; i < pattern_length; i++) {
  3599. uc16 c = pattern[i];
  3600. if (c > String::kMaxOneByteCharCode) {
  3601. return -1;
  3602. }
  3603. }
  3604. }
  3605. pchar pattern_first_char = pattern[0];
  3606. for (int i = idx; i >= 0; i--) {
  3607. if (subject[i] != pattern_first_char) continue;
  3608. int j = 1;
  3609. while (j < pattern_length) {
  3610. if (pattern[j] != subject[i+j]) {
  3611. break;
  3612. }
  3613. j++;
  3614. }
  3615. if (j == pattern_length) {
  3616. return i;
  3617. }
  3618. }
  3619. return -1;
  3620. }
  3621. RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
  3622. HandleScope scope(isolate);
  3623. ASSERT(args.length() == 3);
  3624. CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
  3625. CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
  3626. Object* index = args[2];
  3627. uint32_t start_index;
  3628. if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
  3629. uint32_t pat_length = pat->length();
  3630. uint32_t sub_length = sub->length();
  3631. if (start_index + pat_length > sub_length) {
  3632. start_index = sub_length - pat_length;
  3633. }
  3634. if (pat_length == 0) {
  3635. return Smi::FromInt(start_index);
  3636. }
  3637. if (!sub->IsFlat()) FlattenString(sub);
  3638. if (!pat->IsFlat()) FlattenString(pat);
  3639. int position = -1;
  3640. DisallowHeapAllocation no_gc; // ensure vectors stay valid
  3641. String::FlatContent sub_content = sub->GetFlatContent();
  3642. String::FlatContent pat_content = pat->GetFlatContent();
  3643. if (pat_content.IsAscii()) {
  3644. Vector<const uint8_t> pat_vector = pat_content.ToOneByteVector();
  3645. if (sub_content.IsAscii()) {
  3646. position = StringMatchBackwards(sub_content.ToOneByteVector(),
  3647. pat_vector,
  3648. start_index);
  3649. } else {
  3650. position = StringMatchBackwards(sub_content.ToUC16Vector(),
  3651. pat_vector,
  3652. start_index);
  3653. }
  3654. } else {
  3655. Vector<const uc16> pat_vector = pat_content.ToUC16Vector();
  3656. if (sub_content.IsAscii()) {
  3657. position = StringMatchBackwards(sub_content.ToOneByteVector(),
  3658. pat_vector,
  3659. start_index);
  3660. } else {
  3661. position = StringMatchBackwards(sub_content.ToUC16Vector(),
  3662. pat_vector,
  3663. start_index);
  3664. }
  3665. }
  3666. return Smi::FromInt(position);
  3667. }
  3668. RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
  3669. SealHandleScope shs(isolate);
  3670. ASSERT(args.length() == 2);
  3671. CONVERT_ARG_CHECKED(String, str1, 0);
  3672. CONVERT_ARG_CHECKED(String, str2, 1);
  3673. if (str1 == str2) return Smi::FromInt(0); // Equal.
  3674. int str1_length = str1->length();
  3675. int str2_length = str2->length();
  3676. // Decide trivial cases without flattening.
  3677. if (str1_length == 0) {
  3678. if (str2_length == 0) return Smi::FromInt(0); // Equal.
  3679. return Smi::FromInt(-str2_length);
  3680. } else {
  3681. if (str2_length == 0) return Smi::FromInt(str1_length);
  3682. }
  3683. int end = str1_length < str2_length ? str1_length : str2_length;
  3684. // No need to flatten if we are going to find the answer on the first
  3685. // character. At this point we know there is at least one character
  3686. // in each string, due to the trivial case handling above.
  3687. int d = str1->Get(0) - str2->Get(0);
  3688. if (d != 0) return Smi::FromInt(d);
  3689. str1->TryFlatten();
  3690. str2->TryFlatten();
  3691. ConsStringIteratorOp* op1 =
  3692. isolate->runtime_state()->string_locale_compare_it1();
  3693. ConsStringIteratorOp* op2 =
  3694. isolate->runtime_state()->string_locale_compare_it2();
  3695. // TODO(dcarney) Can do array compares here more efficiently.
  3696. StringCharacterStream stream1(str1, op1);
  3697. StringCharacterStream stream2(str2, op2);
  3698. for (int i = 0; i < end; i++) {
  3699. uint16_t char1 = stream1.GetNext();
  3700. uint16_t char2 = stream2.GetNext();
  3701. if (char1 != char2) return Smi::FromInt(char1 - char2);
  3702. }
  3703. return Smi::FromInt(str1_length - str2_length);
  3704. }
  3705. RUNTIME_FUNCTION(MaybeObject*, Runtime_SubString) {
  3706. SealHandleScope shs(isolate);
  3707. ASSERT(args.length() == 3);
  3708. CONVERT_ARG_CHECKED(String, value, 0);
  3709. int start, end;
  3710. // We have a fast integer-only case here to avoid a conversion to double in
  3711. // the common case where from and to are Smis.
  3712. if (args[1]->IsSmi() && args[2]->IsSmi()) {
  3713. CONVERT_SMI_ARG_CHECKED(from_number, 1);
  3714. CONVERT_SMI_ARG_CHECKED(to_number, 2);
  3715. start = from_number;
  3716. end = to_number;
  3717. } else {
  3718. CONVERT_DOUBLE_ARG_CHECKED(from_number, 1);
  3719. CONVERT_DOUBLE_ARG_CHECKED(to_number, 2);
  3720. start = FastD2IChecked(from_number);
  3721. end = FastD2IChecked(to_number);
  3722. }
  3723. RUNTIME_ASSERT(end >= start);
  3724. RUNTIME_ASSERT(start >= 0);
  3725. RUNTIME_ASSERT(end <= value->length());
  3726. isolate->counters()->sub_string_runtime()->Increment();
  3727. if (end - start == 1) {
  3728. return isolate->heap()->LookupSingleCharacterStringFromCode(
  3729. value->Get(start));
  3730. }
  3731. return value->SubString(start, end);
  3732. }
  3733. RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) {
  3734. HandleScope handles(isolate);
  3735. ASSERT_EQ(3, args.length());
  3736. CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
  3737. CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
  3738. CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2);
  3739. RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
  3740. if (global_cache.HasException()) return Failure::Exception();
  3741. int capture_count = regexp->CaptureCount();
  3742. ZoneScope zone_scope(isolate->runtime_zone());
  3743. ZoneList<int> offsets(8, zone_scope.zone());
  3744. while (true) {
  3745. int32_t* match = global_cache.FetchNext();
  3746. if (match == NULL) break;
  3747. offsets.Add(match[0], zone_scope.zone()); // start
  3748. offsets.Add(match[1], zone_scope.zone()); // end
  3749. }
  3750. if (global_cache.HasException()) return Failure::Exception();
  3751. if (offsets.length() == 0) {
  3752. // Not a single match.
  3753. return isolate->heap()->null_value();
  3754. }
  3755. RegExpImpl::SetLastMatchInfo(regexp_info,
  3756. subject,
  3757. capture_count,
  3758. global_cache.LastSuccessfulMatch());
  3759. int matches = offsets.length() / 2;
  3760. Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches);
  3761. Handle<String> substring =
  3762. isolate->factory()->NewSubString(subject, offsets.at(0), offsets.at(1));
  3763. elements->set(0, *substring);
  3764. for (int i = 1; i < matches; i++) {
  3765. HandleScope temp_scope(isolate);
  3766. int from = offsets.at(i * 2);
  3767. int to = offsets.at(i * 2 + 1);
  3768. Handle<String> substring =
  3769. isolate->factory()->NewProperSubString(subject, from, to);
  3770. elements->set(i, *substring);
  3771. }
  3772. Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements);
  3773. result->set_length(Smi::FromInt(matches));
  3774. return *result;
  3775. }
  3776. // Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain
  3777. // separate last match info. See comment on that function.
  3778. template<bool has_capture>
  3779. static MaybeObject* SearchRegExpMultiple(
  3780. Isolate* isolate,
  3781. Handle<String> subject,
  3782. Handle<JSRegExp> regexp,
  3783. Handle<JSArray> last_match_array,
  3784. Handle<JSArray> result_array) {
  3785. ASSERT(subject->IsFlat());
  3786. ASSERT_NE(has_capture, regexp->CaptureCount() == 0);
  3787. int capture_count = regexp->CaptureCount();
  3788. int subject_length = subject->length();
  3789. static const int kMinLengthToCache = 0x1000;
  3790. if (subject_length > kMinLengthToCache) {
  3791. Handle<Object> cached_answer(RegExpResultsCache::Lookup(
  3792. isolate->heap(),
  3793. *subject,
  3794. regexp->data(),
  3795. RegExpResultsCache::REGEXP_MULTIPLE_INDICES), isolate);
  3796. if (*cached_answer != Smi::FromInt(0)) {
  3797. Handle<FixedArray> cached_fixed_array =
  3798. Handle<FixedArray>(FixedArray::cast(*cached_answer));
  3799. // The cache FixedArray is a COW-array and can therefore be reused.
  3800. isolate->factory()->SetContent(result_array, cached_fixed_array);
  3801. // The actual length of the result array is stored in the last element of
  3802. // the backing store (the backing FixedArray may have a larger capacity).
  3803. Object* cached_fixed_array_last_element =
  3804. cached_fixed_array->get(cached_fixed_array->length() - 1);
  3805. Smi* js_array_length = Smi::cast(cached_fixed_array_last_element);
  3806. result_array->set_length(js_array_length);
  3807. RegExpImpl::SetLastMatchInfo(
  3808. last_match_array, subject, capture_count, NULL);
  3809. return *result_array;
  3810. }
  3811. }
  3812. RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
  3813. if (global_cache.HasException()) return Failure::Exception();
  3814. Handle<FixedArray> result_elements;
  3815. if (result_array->HasFastObjectElements()) {
  3816. result_elements =
  3817. Handle<FixedArray>(FixedArray::cast(result_array->elements()));
  3818. }
  3819. if (result_elements.is_null() || result_elements->length() < 16) {
  3820. result_elements = isolate->factory()->NewFixedArrayWithHoles(16);
  3821. }
  3822. FixedArrayBuilder builder(result_elements);
  3823. // Position to search from.
  3824. int match_start = -1;
  3825. int match_end = 0;
  3826. bool first = true;
  3827. // Two smis before and after the match, for very long strings.
  3828. static const int kMaxBuilderEntriesPerRegExpMatch = 5;
  3829. while (true) {
  3830. int32_t* current_match = global_cache.FetchNext();
  3831. if (current_match == NULL) break;
  3832. match_start = current_match[0];
  3833. builder.EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
  3834. if (match_end < match_start) {
  3835. ReplacementStringBuilder::AddSubjectSlice(&builder,
  3836. match_end,
  3837. match_start);
  3838. }
  3839. match_end = current_match[1];
  3840. {
  3841. // Avoid accumulating new handles inside loop.
  3842. HandleScope temp_scope(isolate);
  3843. Handle<String> match;
  3844. if (!first) {
  3845. match = isolate->factory()->NewProperSubString(subject,
  3846. match_start,
  3847. match_end);
  3848. } else {
  3849. match = isolate->factory()->NewSubString(subject,
  3850. match_start,
  3851. match_end);
  3852. first = false;
  3853. }
  3854. if (has_capture) {
  3855. // Arguments array to replace function is match, captures, index and
  3856. // subject, i.e., 3 + capture count in total.
  3857. Handle<FixedArray> elements =
  3858. isolate->factory()->NewFixedArray(3 + capture_count);
  3859. elements->set(0, *match);
  3860. for (int i = 1; i <= capture_count; i++) {
  3861. int start = current_match[i * 2];
  3862. if (start >= 0) {
  3863. int end = current_match[i * 2 + 1];
  3864. ASSERT(start <= end);
  3865. Handle<String> substring =
  3866. isolate->factory()->NewSubString(subject, start, end);
  3867. elements->set(i, *substring);
  3868. } else {
  3869. ASSERT(current_match[i * 2 + 1] < 0);
  3870. elements->set(i, isolate->heap()->undefined_value());
  3871. }
  3872. }
  3873. elements->set(capture_count + 1, Smi::FromInt(match_start));
  3874. elements->set(capture_count + 2, *subject);
  3875. builder.Add(*isolate->factory()->NewJSArrayWithElements(elements));
  3876. } else {
  3877. builder.Add(*match);
  3878. }
  3879. }
  3880. }
  3881. if (global_cache.HasException()) return Failure::Exception();
  3882. if (match_start >= 0) {
  3883. // Finished matching, with at least one match.
  3884. if (match_end < subject_length) {
  3885. ReplacementStringBuilder::AddSubjectSlice(&builder,
  3886. match_end,
  3887. subject_length);
  3888. }
  3889. RegExpImpl::SetLastMatchInfo(
  3890. last_match_array, subject, capture_count, NULL);
  3891. if (subject_length > kMinLengthToCache) {
  3892. // Store the length of the result array into the last element of the
  3893. // backing FixedArray.
  3894. builder.EnsureCapacity(1);
  3895. Handle<FixedArray> fixed_array = builder.array();
  3896. fixed_array->set(fixed_array->length() - 1,
  3897. Smi::FromInt(builder.length()));
  3898. // Cache the result and turn the FixedArray into a COW array.
  3899. RegExpResultsCache::Enter(isolate->heap(),
  3900. *subject,
  3901. regexp->data(),
  3902. *fixed_array,
  3903. RegExpResultsCache::REGEXP_MULTIPLE_INDICES);
  3904. }
  3905. return *builder.ToJSArray(result_array);
  3906. } else {
  3907. return isolate->heap()->null_value(); // No matches at all.
  3908. }
  3909. }
  3910. // This is only called for StringReplaceGlobalRegExpWithFunction. This sets
  3911. // lastMatchInfoOverride to maintain the last match info, so we don't need to
  3912. // set any other last match array info.
  3913. RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) {
  3914. HandleScope handles(isolate);
  3915. ASSERT(args.length() == 4);
  3916. CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
  3917. if (!subject->IsFlat()) FlattenString(subject);
  3918. CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
  3919. CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2);
  3920. CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3);
  3921. ASSERT(regexp->GetFlags().is_global());
  3922. if (regexp->CaptureCount() == 0) {
  3923. return SearchRegExpMultiple<false>(
  3924. isolate, subject, regexp, last_match_info, result_array);
  3925. } else {
  3926. return SearchRegExpMultiple<true>(
  3927. isolate, subject, regexp, last_match_info, result_array);
  3928. }
  3929. }
  3930. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) {
  3931. SealHandleScope shs(isolate);
  3932. ASSERT(args.length() == 2);
  3933. CONVERT_SMI_ARG_CHECKED(radix, 1);
  3934. RUNTIME_ASSERT(2 <= radix && radix <= 36);
  3935. // Fast case where the result is a one character string.
  3936. if (args[0]->IsSmi()) {
  3937. int value = args.smi_at(0);
  3938. if (value >= 0 && value < radix) {
  3939. // Character array used for conversion.
  3940. static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
  3941. return isolate->heap()->
  3942. LookupSingleCharacterStringFromCode(kCharTable[value]);
  3943. }
  3944. }
  3945. // Slow case.
  3946. CONVERT_DOUBLE_ARG_CHECKED(value, 0);
  3947. if (std::isnan(value)) {
  3948. return *isolate->factory()->nan_string();
  3949. }
  3950. if (std::isinf(value)) {
  3951. if (value < 0) {
  3952. return *isolate->factory()->minus_infinity_string();
  3953. }
  3954. return *isolate->factory()->infinity_string();
  3955. }
  3956. char* str = DoubleToRadixCString(value, radix);
  3957. MaybeObject* result =
  3958. isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
  3959. DeleteArray(str);
  3960. return result;
  3961. }
  3962. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) {
  3963. SealHandleScope shs(isolate);
  3964. ASSERT(args.length() == 2);
  3965. CONVERT_DOUBLE_ARG_CHECKED(value, 0);
  3966. CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
  3967. int f = FastD2IChecked(f_number);
  3968. RUNTIME_ASSERT(f >= 0);
  3969. char* str = DoubleToFixedCString(value, f);
  3970. MaybeObject* res =
  3971. isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
  3972. DeleteArray(str);
  3973. return res;
  3974. }
  3975. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) {
  3976. SealHandleScope shs(isolate);
  3977. ASSERT(args.length() == 2);
  3978. CONVERT_DOUBLE_ARG_CHECKED(value, 0);
  3979. CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
  3980. int f = FastD2IChecked(f_number);
  3981. RUNTIME_ASSERT(f >= -1 && f <= 20);
  3982. char* str = DoubleToExponentialCString(value, f);
  3983. MaybeObject* res =
  3984. isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
  3985. DeleteArray(str);
  3986. return res;
  3987. }
  3988. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) {
  3989. SealHandleScope shs(isolate);
  3990. ASSERT(args.length() == 2);
  3991. CONVERT_DOUBLE_ARG_CHECKED(value, 0);
  3992. CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
  3993. int f = FastD2IChecked(f_number);
  3994. RUNTIME_ASSERT(f >= 1 && f <= 21);
  3995. char* str = DoubleToPrecisionCString(value, f);
  3996. MaybeObject* res =
  3997. isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
  3998. DeleteArray(str);
  3999. return res;
  4000. }
  4001. // Returns a single character string where first character equals
  4002. // string->Get(index).
  4003. static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
  4004. if (index < static_cast<uint32_t>(string->length())) {
  4005. string->TryFlatten();
  4006. return LookupSingleCharacterStringFromCode(
  4007. string->GetIsolate(),
  4008. string->Get(index));
  4009. }
  4010. return Execution::CharAt(string, index);
  4011. }
  4012. MaybeObject* Runtime::GetElementOrCharAtOrFail(Isolate* isolate,
  4013. Handle<Object> object,
  4014. uint32_t index) {
  4015. CALL_HEAP_FUNCTION_PASS_EXCEPTION(isolate,
  4016. GetElementOrCharAt(isolate, object, index));
  4017. }
  4018. MaybeObject* Runtime::GetElementOrCharAt(Isolate* isolate,
  4019. Handle<Object> object,
  4020. uint32_t index) {
  4021. // Handle [] indexing on Strings
  4022. if (object->IsString()) {
  4023. Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
  4024. if (!result->IsUndefined()) return *result;
  4025. }
  4026. // Handle [] indexing on String objects
  4027. if (object->IsStringObjectWithCharacterAt(index)) {
  4028. Handle<JSValue> js_value = Handle<JSValue>::cast(object);
  4029. Handle<Object> result =
  4030. GetCharAt(Handle<String>(String::cast(js_value->value())), index);
  4031. if (!result->IsUndefined()) return *result;
  4032. }
  4033. if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
  4034. return object->GetPrototype(isolate)->GetElement(index);
  4035. }
  4036. return object->GetElement(index);
  4037. }
  4038. MaybeObject* Runtime::HasObjectProperty(Isolate* isolate,
  4039. Handle<JSReceiver> object,
  4040. Handle<Object> key) {
  4041. HandleScope scope(isolate);
  4042. // Check if the given key is an array index.
  4043. uint32_t index;
  4044. if (key->ToArrayIndex(&index)) {
  4045. return isolate->heap()->ToBoolean(object->HasElement(index));
  4046. }
  4047. // Convert the key to a name - possibly by calling back into JavaScript.
  4048. Handle<Name> name;
  4049. if (key->IsName()) {
  4050. name = Handle<Name>::cast(key);
  4051. } else {
  4052. bool has_pending_exception = false;
  4053. Handle<Object> converted =
  4054. Execution::ToString(key, &has_pending_exception);
  4055. if (has_pending_exception) return Failure::Exception();
  4056. name = Handle<Name>::cast(converted);
  4057. }
  4058. return isolate->heap()->ToBoolean(object->HasProperty(*name));
  4059. }
  4060. MaybeObject* Runtime::GetObjectPropertyOrFail(
  4061. Isolate* isolate,
  4062. Handle<Object> object,
  4063. Handle<Object> key) {
  4064. CALL_HEAP_FUNCTION_PASS_EXCEPTION(isolate,
  4065. GetObjectProperty(isolate, object, key));
  4066. }
  4067. MaybeObject* Runtime::GetObjectProperty(Isolate* isolate,
  4068. Handle<Object> object,
  4069. Handle<Object> key) {
  4070. HandleScope scope(isolate);
  4071. if (object->IsUndefined() || object->IsNull()) {
  4072. Handle<Object> args[2] = { key, object };
  4073. Handle<Object> error =
  4074. isolate->factory()->NewTypeError("non_object_property_load",
  4075. HandleVector(args, 2));
  4076. return isolate->Throw(*error);
  4077. }
  4078. // Check if the given key is an array index.
  4079. uint32_t index;
  4080. if (key->ToArrayIndex(&index)) {
  4081. return GetElementOrCharAt(isolate, object, index);
  4082. }
  4083. // Convert the key to a name - possibly by calling back into JavaScript.
  4084. Handle<Name> name;
  4085. if (key->IsName()) {
  4086. name = Handle<Name>::cast(key);
  4087. } else {
  4088. bool has_pending_exception = false;
  4089. Handle<Object> converted =
  4090. Execution::ToString(key, &has_pending_exception);
  4091. if (has_pending_exception) return Failure::Exception();
  4092. name = Handle<Name>::cast(converted);
  4093. }
  4094. // Check if the name is trivially convertible to an index and get
  4095. // the element if so.
  4096. if (name->AsArrayIndex(&index)) {
  4097. return GetElementOrCharAt(isolate, object, index);
  4098. } else {
  4099. return object->GetProperty(*name);
  4100. }
  4101. }
  4102. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetProperty) {
  4103. SealHandleScope shs(isolate);
  4104. ASSERT(args.length() == 2);
  4105. Handle<Object> object = args.at<Object>(0);
  4106. Handle<Object> key = args.at<Object>(1);
  4107. return Runtime::GetObjectProperty(isolate, object, key);
  4108. }
  4109. // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
  4110. RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
  4111. SealHandleScope shs(isolate);
  4112. ASSERT(args.length() == 2);
  4113. // Fast cases for getting named properties of the receiver JSObject
  4114. // itself.
  4115. //
  4116. // The global proxy objects has to be excluded since LocalLookup on
  4117. // the global proxy object can return a valid result even though the
  4118. // global proxy object never has properties. This is the case
  4119. // because the global proxy object forwards everything to its hidden
  4120. // prototype including local lookups.
  4121. //
  4122. // Additionally, we need to make sure that we do not cache results
  4123. // for objects that require access checks.
  4124. if (args[0]->IsJSObject()) {
  4125. if (!args[0]->IsJSGlobalProxy() &&
  4126. !args[0]->IsAccessCheckNeeded() &&
  4127. args[1]->IsName()) {
  4128. JSObject* receiver = JSObject::cast(args[0]);
  4129. Name* key = Name::cast(args[1]);
  4130. if (receiver->HasFastProperties()) {
  4131. // Attempt to use lookup cache.
  4132. Map* receiver_map = receiver->map();
  4133. KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache();
  4134. int offset = keyed_lookup_cache->Lookup(receiver_map, key);
  4135. if (offset != -1) {
  4136. // Doubles are not cached, so raw read the value.
  4137. Object* value = receiver->RawFastPropertyAt(offset);
  4138. return value->IsTheHole()
  4139. ? isolate->heap()->undefined_value()
  4140. : value;
  4141. }
  4142. // Lookup cache miss. Perform lookup and update the cache if
  4143. // appropriate.
  4144. LookupResult result(isolate);
  4145. receiver->LocalLookup(key, &result);
  4146. if (result.IsField()) {
  4147. int offset = result.GetFieldIndex().field_index();
  4148. // Do not track double fields in the keyed lookup cache. Reading
  4149. // double values requires boxing.
  4150. if (!FLAG_track_double_fields ||
  4151. !result.representation().IsDouble()) {
  4152. keyed_lookup_cache->Update(receiver_map, key, offset);
  4153. }
  4154. return receiver->FastPropertyAt(result.representation(), offset);
  4155. }
  4156. } else {
  4157. // Attempt dictionary lookup.
  4158. NameDictionary* dictionary = receiver->property_dictionary();
  4159. int entry = dictionary->FindEntry(key);
  4160. if ((entry != NameDictionary::kNotFound) &&
  4161. (dictionary->DetailsAt(entry).type() == NORMAL)) {
  4162. Object* value = dictionary->ValueAt(entry);
  4163. if (!receiver->IsGlobalObject()) return value;
  4164. value = PropertyCell::cast(value)->value();
  4165. if (!value->IsTheHole()) return value;
  4166. // If value is the hole do the general lookup.
  4167. }
  4168. }
  4169. } else if (FLAG_smi_only_arrays && args.at<Object>(1)->IsSmi()) {
  4170. // JSObject without a name key. If the key is a Smi, check for a
  4171. // definite out-of-bounds access to elements, which is a strong indicator
  4172. // that subsequent accesses will also call the runtime. Proactively
  4173. // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
  4174. // doubles for those future calls in the case that the elements would
  4175. // become FAST_DOUBLE_ELEMENTS.
  4176. Handle<JSObject> js_object(args.at<JSObject>(0));
  4177. ElementsKind elements_kind = js_object->GetElementsKind();
  4178. if (IsFastDoubleElementsKind(elements_kind)) {
  4179. FixedArrayBase* elements = js_object->elements();
  4180. if (args.at<Smi>(1)->value() >= elements->length()) {
  4181. if (IsFastHoleyElementsKind(elements_kind)) {
  4182. elements_kind = FAST_HOLEY_ELEMENTS;
  4183. } else {
  4184. elements_kind = FAST_ELEMENTS;
  4185. }
  4186. MaybeObject* maybe_object = TransitionElements(js_object,
  4187. elements_kind,
  4188. isolate);
  4189. if (maybe_object->IsFailure()) return maybe_object;
  4190. }
  4191. } else {
  4192. ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) ||
  4193. !IsFastElementsKind(elements_kind));
  4194. }
  4195. }
  4196. } else if (args[0]->IsString() && args[1]->IsSmi()) {
  4197. // Fast case for string indexing using [] with a smi index.
  4198. HandleScope scope(isolate);
  4199. Handle<String> str = args.at<String>(0);
  4200. int index = args.smi_at(1);
  4201. if (index >= 0 && index < str->length()) {
  4202. Handle<Object> result = GetCharAt(str, index);
  4203. return *result;
  4204. }
  4205. }
  4206. // Fall back to GetObjectProperty.
  4207. return Runtime::GetObjectProperty(isolate,
  4208. args.at<Object>(0),
  4209. args.at<Object>(1));
  4210. }
  4211. static bool IsValidAccessor(Handle<Object> obj) {
  4212. return obj->IsUndefined() || obj->IsSpecFunction() || obj->IsNull();
  4213. }
  4214. // Implements part of 8.12.9 DefineOwnProperty.
  4215. // There are 3 cases that lead here:
  4216. // Step 4b - define a new accessor property.
  4217. // Steps 9c & 12 - replace an existing data property with an accessor property.
  4218. // Step 12 - update an existing accessor property with an accessor or generic
  4219. // descriptor.
  4220. RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) {
  4221. HandleScope scope(isolate);
  4222. ASSERT(args.length() == 5);
  4223. CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
  4224. RUNTIME_ASSERT(!obj->IsNull());
  4225. CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
  4226. CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
  4227. RUNTIME_ASSERT(IsValidAccessor(getter));
  4228. CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
  4229. RUNTIME_ASSERT(IsValidAccessor(setter));
  4230. CONVERT_SMI_ARG_CHECKED(unchecked, 4);
  4231. RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
  4232. PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
  4233. bool fast = obj->HasFastProperties();
  4234. JSObject::DefineAccessor(obj, name, getter, setter, attr);
  4235. RETURN_IF_SCHEDULED_EXCEPTION(isolate);
  4236. if (fast) JSObject::TransformToFastProperties(obj, 0);
  4237. return isolate->heap()->undefined_value();
  4238. }
  4239. // Implements part of 8.12.9 DefineOwnProperty.
  4240. // There are 3 cases that lead here:
  4241. // Step 4a - define a new data property.
  4242. // Steps 9b & 12 - replace an existing accessor property with a data property.
  4243. // Step 12 - update an existing data property with a data or generic
  4244. // descriptor.
  4245. RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
  4246. HandleScope scope(isolate);
  4247. ASSERT(args.length() == 4);
  4248. CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
  4249. CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
  4250. CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2);
  4251. CONVERT_SMI_ARG_CHECKED(unchecked, 3);
  4252. RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
  4253. PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
  4254. LookupResult result(isolate);
  4255. js_object->LocalLookupRealNamedProperty(*name, &result);
  4256. // Special case for callback properties.
  4257. if (result.IsPropertyCallbacks()) {
  4258. Object* callback = result.GetCallbackObject();
  4259. // To be compatible with Safari we do not change the value on API objects
  4260. // in Object.defineProperty(). Firefox disagrees here, and actually changes
  4261. // the value.
  4262. if (callback->IsAccessorInfo()) {
  4263. return isolate->heap()->undefined_value();
  4264. }
  4265. // Avoid redefining foreign callback as data property, just use the stored
  4266. // setter to update the value instead.
  4267. // TODO(mstarzinger): So far this only works if property attributes don't
  4268. // change, this should be fixed once we cleanup the underlying code.
  4269. if (callback->IsForeign() && result.GetAttributes() == attr) {
  4270. return js_object->SetPropertyWithCallback(callback,
  4271. *name,
  4272. *obj_value,
  4273. result.holder(),
  4274. kStrictMode);
  4275. }
  4276. }
  4277. // Take special care when attributes are different and there is already
  4278. // a property. For simplicity we normalize the property which enables us
  4279. // to not worry about changing the instance_descriptor and creating a new
  4280. // map. The current version of SetObjectProperty does not handle attributes
  4281. // correctly in the case where a property is a field and is reset with
  4282. // new attributes.
  4283. if (result.IsFound() &&
  4284. (attr != result.GetAttributes() || result.IsPropertyCallbacks())) {
  4285. // New attributes - normalize to avoid writing to instance descriptor
  4286. if (js_object->IsJSGlobalProxy()) {
  4287. // Since the result is a property, the prototype will exist so
  4288. // we don't have to check for null.
  4289. js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype()));
  4290. }
  4291. JSObject::NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
  4292. // Use IgnoreAttributes version since a readonly property may be
  4293. // overridden and SetProperty does not allow this.
  4294. return js_object->SetLocalPropertyIgnoreAttributes(*name,
  4295. *obj_value,
  4296. attr);
  4297. }
  4298. return Runtime::ForceSetObjectProperty(isolate,
  4299. js_object,
  4300. name,
  4301. obj_value,
  4302. attr);
  4303. }
  4304. // Return property without being observable by accessors or interceptors.
  4305. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDataProperty) {
  4306. SealHandleScope shs(isolate);
  4307. ASSERT(args.length() == 2);
  4308. CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
  4309. CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
  4310. LookupResult lookup(isolate);
  4311. object->LookupRealNamedProperty(*key, &lookup);
  4312. if (!lookup.IsFound()) return isolate->heap()->undefined_value();
  4313. switch (lookup.type()) {
  4314. case NORMAL:
  4315. return lookup.holder()->GetNormalizedProperty(&lookup);
  4316. case FIELD:
  4317. return lookup.holder()->FastPropertyAt(
  4318. lookup.representation(),
  4319. lookup.GetFieldIndex().field_index());
  4320. case CONSTANT:
  4321. return lookup.GetConstant();
  4322. case CALLBACKS:
  4323. case HANDLER:
  4324. case INTERCEPTOR:
  4325. case TRANSITION:
  4326. return isolate->heap()->undefined_value();
  4327. case NONEXISTENT:
  4328. UNREACHABLE();
  4329. }
  4330. return isolate->heap()->undefined_value();
  4331. }
  4332. MaybeObject* Runtime::SetObjectPropertyOrFail(
  4333. Isolate* isolate,
  4334. Handle<Object> object,
  4335. Handle<Object> key,
  4336. Handle<Object> value,
  4337. PropertyAttributes attr,
  4338. StrictModeFlag strict_mode) {
  4339. CALL_HEAP_FUNCTION_PASS_EXCEPTION(isolate,
  4340. SetObjectProperty(isolate, object, key, value, attr, strict_mode));
  4341. }
  4342. MaybeObject* Runtime::SetObjectProperty(Isolate* isolate,
  4343. Handle<Object> object,
  4344. Handle<Object> key,
  4345. Handle<Object> value,
  4346. PropertyAttributes attr,
  4347. StrictModeFlag strict_mode) {
  4348. SetPropertyMode set_mode = attr == NONE ? SET_PROPERTY : DEFINE_PROPERTY;
  4349. HandleScope scope(isolate);
  4350. if (object->IsUndefined() || object->IsNull()) {
  4351. Handle<Object> args[2] = { key, object };
  4352. Handle<Object> error =
  4353. isolate->factory()->NewTypeError("non_object_property_store",
  4354. HandleVector(args, 2));
  4355. return isolate->Throw(*error);
  4356. }
  4357. if (object->IsJSProxy()) {
  4358. bool has_pending_exception = false;
  4359. Handle<Object> name = key->IsSymbol()
  4360. ? key : Execution::ToString(key, &has_pending_exception);
  4361. if (has_pending_exception) return Failure::Exception();
  4362. return JSProxy::cast(*object)->SetProperty(
  4363. Name::cast(*name), *value, attr, strict_mode);
  4364. }
  4365. // If the object isn't a JavaScript object, we ignore the store.
  4366. if (!object->IsJSObject()) return *value;
  4367. Handle<JSObject> js_object = Handle<JSObject>::cast(object);
  4368. // Check if the given key is an array index.
  4369. uint32_t index;
  4370. if (key->ToArrayIndex(&index)) {
  4371. // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
  4372. // of a string using [] notation. We need to support this too in
  4373. // JavaScript.
  4374. // In the case of a String object we just need to redirect the assignment to
  4375. // the underlying string if the index is in range. Since the underlying
  4376. // string does nothing with the assignment then we can ignore such
  4377. // assignments.
  4378. if (js_object->IsStringObjectWithCharacterAt(index)) {
  4379. return *value;
  4380. }
  4381. js_object->ValidateElements();
  4382. if (js_object->HasExternalArrayElements()) {
  4383. if (!value->IsNumber() && !value->IsUndefined()) {
  4384. bool has_exception;
  4385. Handle<Object> number = Execution::ToNumber(value, &has_exception);
  4386. if (has_exception) return Failure::Exception();
  4387. value = number;
  4388. }
  4389. }
  4390. MaybeObject* result = js_object->SetElement(
  4391. index, *value, attr, strict_mode, true, set_mode);
  4392. js_object->ValidateElements();
  4393. if (result->IsFailure()) return result;
  4394. return *value;
  4395. }
  4396. if (key->IsName()) {
  4397. MaybeObject* result;
  4398. Handle<Name> name = Handle<Name>::cast(key);
  4399. if (name->AsArrayIndex(&index)) {
  4400. if (js_object->HasExternalArrayElements()) {
  4401. if (!value->IsNumber() && !value->IsUndefined()) {
  4402. bool has_exception;
  4403. Handle<Object> number = Execution::ToNumber(value, &has_exception);
  4404. if (has_exception) return Failure::Exception();
  4405. value = number;
  4406. }
  4407. }
  4408. result = js_object->SetElement(
  4409. index, *value, attr, strict_mode, true, set_mode);
  4410. } else {
  4411. if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
  4412. result = js_object->SetProperty(*name, *value, attr, strict_mode);
  4413. }
  4414. if (result->IsFailure()) return result;
  4415. return *value;
  4416. }
  4417. // Call-back into JavaScript to convert the key to a string.
  4418. bool has_pending_exception = false;
  4419. Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
  4420. if (has_pending_exception) return Failure::Exception();
  4421. Handle<String> name = Handle<String>::cast(converted);
  4422. if (name->AsArrayIndex(&index)) {
  4423. return js_object->SetElement(
  4424. index, *value, attr, strict_mode, true, set_mode);
  4425. } else {
  4426. return js_object->SetProperty(*name, *value, attr, strict_mode);
  4427. }
  4428. }
  4429. MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate,
  4430. Handle<JSObject> js_object,
  4431. Handle<Object> key,
  4432. Handle<Object> value,
  4433. PropertyAttributes attr) {
  4434. HandleScope scope(isolate);
  4435. // Check if the given key is an array index.
  4436. uint32_t index;
  4437. if (key->ToArrayIndex(&index)) {
  4438. // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
  4439. // of a string using [] notation. We need to support this too in
  4440. // JavaScript.
  4441. // In the case of a String object we just need to redirect the assignment to
  4442. // the underlying string if the index is in range. Since the underlying
  4443. // string does nothing with the assignment then we can ignore such
  4444. // assignments.
  4445. if (js_object->IsStringObjectWithCharacterAt(index)) {
  4446. return *value;
  4447. }
  4448. return js_object->SetElement(
  4449. index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
  4450. }
  4451. if (key->IsName()) {
  4452. Handle<Name> name = Handle<Name>::cast(key);
  4453. if (name->AsArrayIndex(&index)) {
  4454. return js_object->SetElement(
  4455. index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
  4456. } else {
  4457. if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
  4458. return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr);
  4459. }
  4460. }
  4461. // Call-back into JavaScript to convert the key to a string.
  4462. bool has_pending_exception = false;
  4463. Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
  4464. if (has_pending_exception) return Failure::Exception();
  4465. Handle<String> name = Handle<String>::cast(converted);
  4466. if (name->AsArrayIndex(&index)) {
  4467. return js_object->SetElement(
  4468. index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
  4469. } else {
  4470. return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr);
  4471. }
  4472. }
  4473. MaybeObject* Runtime::DeleteObjectProperty(Isolate* isolate,
  4474. Handle<JSReceiver> receiver,
  4475. Handle<Object> key,
  4476. JSReceiver::DeleteMode mode) {
  4477. HandleScope scope(isolate);
  4478. // Check if the given key is an array index.
  4479. uint32_t index;
  4480. if (key->ToArrayIndex(&index)) {
  4481. // In Firefox/SpiderMonkey, Safari and Opera you can access the
  4482. // characters of a string using [] notation. In the case of a
  4483. // String object we just need to redirect the deletion to the
  4484. // underlying string if the index is in range. Since the
  4485. // underlying string does nothing with the deletion, we can ignore
  4486. // such deletions.
  4487. if (receiver->IsStringObjectWithCharacterAt(index)) {
  4488. return isolate->heap()->true_value();
  4489. }
  4490. Handle<Object> result = JSReceiver::DeleteElement(receiver, index, mode);
  4491. RETURN_IF_EMPTY_HANDLE(isolate, result);
  4492. return *result;
  4493. }
  4494. Handle<Name> name;
  4495. if (key->IsName()) {
  4496. name = Handle<Name>::cast(key);
  4497. } else {
  4498. // Call-back into JavaScript to convert the key to a string.
  4499. bool has_pending_exception = false;
  4500. Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
  4501. if (has_pending_exception) return Failure::Exception();
  4502. name = Handle<String>::cast(converted);
  4503. }
  4504. if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
  4505. Handle<Object> result = JSReceiver::DeleteProperty(receiver, name, mode);
  4506. RETURN_IF_EMPTY_HANDLE(isolate, result);
  4507. return *result;
  4508. }
  4509. RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) {
  4510. SealHandleScope shs(isolate);
  4511. RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
  4512. Handle<Object> object = args.at<Object>(0);
  4513. Handle<Object> key = args.at<Object>(1);
  4514. Handle<Object> value = args.at<Object>(2);
  4515. CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3);
  4516. RUNTIME_ASSERT(
  4517. (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
  4518. // Compute attributes.
  4519. PropertyAttributes attributes =
  4520. static_cast<PropertyAttributes>(unchecked_attributes);
  4521. StrictModeFlag strict_mode = kNonStrictMode;
  4522. if (args.length() == 5) {
  4523. CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode_flag, 4);
  4524. strict_mode = strict_mode_flag;
  4525. }
  4526. return Runtime::SetObjectProperty(isolate,
  4527. object,
  4528. key,
  4529. value,
  4530. attributes,
  4531. strict_mode);
  4532. }
  4533. RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsKind) {
  4534. HandleScope scope(isolate);
  4535. RUNTIME_ASSERT(args.length() == 2);
  4536. CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
  4537. CONVERT_ARG_HANDLE_CHECKED(Map, map, 1);
  4538. JSObject::TransitionElementsKind(array, map->elements_kind());
  4539. return *array;
  4540. }
  4541. // Set the native flag on the function.
  4542. // This is used to decide if we should transform null and undefined
  4543. // into the global object when doing call and apply.
  4544. RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) {
  4545. SealHandleScope shs(isolate);
  4546. RUNTIME_ASSERT(args.length() == 1);
  4547. Handle<Object> object = args.at<Object>(0);
  4548. if (object->IsJSFunction()) {
  4549. JSFunction* func = JSFunction::cast(*object);
  4550. func->shared()->set_native(true);
  4551. }
  4552. return isolate->heap()->undefined_value();
  4553. }
  4554. RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) {
  4555. HandleScope scope(isolate);
  4556. RUNTIME_ASSERT(args.length() == 5);
  4557. CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
  4558. CONVERT_SMI_ARG_CHECKED(store_index, 1);
  4559. Handle<Object> value = args.at<Object>(2);
  4560. CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 3);
  4561. CONVERT_SMI_ARG_CHECKED(literal_index, 4);
  4562. Object* raw_literal_cell = literals->get(literal_index);
  4563. JSArray* boilerplate = NULL;
  4564. if (raw_literal_cell->IsAllocationSite()) {
  4565. AllocationSite* site = AllocationSite::cast(raw_literal_cell);
  4566. boilerplate = JSArray::cast(site->transition_info());
  4567. } else {
  4568. boilerplate = JSArray::cast(raw_literal_cell);
  4569. }
  4570. Handle<JSArray> boilerplate_object(boilerplate);
  4571. ElementsKind elements_kind = object->GetElementsKind();
  4572. ASSERT(IsFastElementsKind(elements_kind));
  4573. // Smis should never trigger transitions.
  4574. ASSERT(!value->IsSmi());
  4575. if (value->IsNumber()) {
  4576. ASSERT(IsFastSmiElementsKind(elements_kind));
  4577. ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
  4578. ? FAST_HOLEY_DOUBLE_ELEMENTS
  4579. : FAST_DOUBLE_ELEMENTS;
  4580. if (IsMoreGeneralElementsKindTransition(
  4581. boilerplate_object->GetElementsKind(),
  4582. transitioned_kind)) {
  4583. JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
  4584. }
  4585. JSObject::TransitionElementsKind(object, transitioned_kind);
  4586. ASSERT(IsFastDoubleElementsKind(object->GetElementsKind()));
  4587. FixedDoubleArray* double_array = FixedDoubleArray::cast(object->elements());
  4588. HeapNumber* number = HeapNumber::cast(*value);
  4589. double_array->set(store_index, number->Number());
  4590. } else {
  4591. ASSERT(IsFastSmiElementsKind(elements_kind) ||
  4592. IsFastDoubleElementsKind(elements_kind));
  4593. ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
  4594. ? FAST_HOLEY_ELEMENTS
  4595. : FAST_ELEMENTS;
  4596. JSObject::TransitionElementsKind(object, transitioned_kind);
  4597. if (IsMoreGeneralElementsKindTransition(
  4598. boilerplate_object->GetElementsKind(),
  4599. transitioned_kind)) {
  4600. JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
  4601. }
  4602. FixedArray* object_array = FixedArray::cast(object->elements());
  4603. object_array->set(store_index, *value);
  4604. }
  4605. return *object;
  4606. }
  4607. // Check whether debugger and is about to step into the callback that is passed
  4608. // to a built-in function such as Array.forEach.
  4609. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugCallbackSupportsStepping) {
  4610. SealHandleScope shs(isolate);
  4611. #ifdef ENABLE_DEBUGGER_SUPPORT
  4612. if (!isolate->IsDebuggerActive() || !isolate->debug()->StepInActive()) {
  4613. return isolate->heap()->false_value();
  4614. }
  4615. CONVERT_ARG_CHECKED(Object, callback, 0);
  4616. // We do not step into the callback if it's a builtin or not even a function.
  4617. if (!callback->IsJSFunction() || JSFunction::cast(callback)->IsBuiltin()) {
  4618. return isolate->heap()->false_value();
  4619. }
  4620. return isolate->heap()->true_value();
  4621. #else
  4622. return isolate->heap()->false_value();
  4623. #endif // ENABLE_DEBUGGER_SUPPORT
  4624. }
  4625. // Set one shot breakpoints for the callback function that is passed to a
  4626. // built-in function such as Array.forEach to enable stepping into the callback.
  4627. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrepareStepInIfStepping) {
  4628. SealHandleScope shs(isolate);
  4629. #ifdef ENABLE_DEBUGGER_SUPPORT
  4630. Debug* debug = isolate->debug();
  4631. if (!debug->IsStepping()) return isolate->heap()->undefined_value();
  4632. CONVERT_ARG_HANDLE_CHECKED(JSFunction, callback, 0);
  4633. HandleScope scope(isolate);
  4634. // When leaving the callback, step out has been activated, but not performed
  4635. // if we do not leave the builtin. To be able to step into the callback
  4636. // again, we need to clear the step out at this point.
  4637. debug->ClearStepOut();
  4638. debug->FloodWithOneShot(callback);
  4639. #endif // ENABLE_DEBUGGER_SUPPORT
  4640. return isolate->heap()->undefined_value();
  4641. }
  4642. // Set a local property, even if it is READ_ONLY. If the property does not
  4643. // exist, it will be added with attributes NONE.
  4644. RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) {
  4645. SealHandleScope shs(isolate);
  4646. RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
  4647. CONVERT_ARG_CHECKED(JSObject, object, 0);
  4648. CONVERT_ARG_CHECKED(Name, name, 1);
  4649. // Compute attributes.
  4650. PropertyAttributes attributes = NONE;
  4651. if (args.length() == 4) {
  4652. CONVERT_SMI_ARG_CHECKED(unchecked_value, 3);
  4653. // Only attribute bits should be set.
  4654. RUNTIME_ASSERT(
  4655. (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
  4656. attributes = static_cast<PropertyAttributes>(unchecked_value);
  4657. }
  4658. return object->
  4659. SetLocalPropertyIgnoreAttributes(name, args[2], attributes);
  4660. }
  4661. RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteProperty) {
  4662. HandleScope scope(isolate);
  4663. ASSERT(args.length() == 3);
  4664. CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
  4665. CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
  4666. CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2);
  4667. JSReceiver::DeleteMode delete_mode = (strict_mode == kStrictMode)
  4668. ? JSReceiver::STRICT_DELETION : JSReceiver::NORMAL_DELETION;
  4669. Handle<Object> result = JSReceiver::DeleteProperty(object, key, delete_mode);
  4670. RETURN_IF_EMPTY_HANDLE(isolate, result);
  4671. return *result;
  4672. }
  4673. static MaybeObject* HasLocalPropertyImplementation(Isolate* isolate,
  4674. Handle<JSObject> object,
  4675. Handle<Name> key) {
  4676. if (object->HasLocalProperty(*key)) return isolate->heap()->true_value();
  4677. // Handle hidden prototypes. If there's a hidden prototype above this thing
  4678. // then we have to check it for properties, because they are supposed to
  4679. // look like they are on this object.
  4680. Handle<Object> proto(object->GetPrototype(), isolate);
  4681. if (proto->IsJSObject() &&
  4682. Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) {
  4683. return HasLocalPropertyImplementation(isolate,
  4684. Handle<JSObject>::cast(proto),
  4685. key);
  4686. }
  4687. RETURN_IF_SCHEDULED_EXCEPTION(isolate);
  4688. return isolate->heap()->false_value();
  4689. }
  4690. RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) {
  4691. SealHandleScope shs(isolate);
  4692. ASSERT(args.length() == 2);
  4693. CONVERT_ARG_CHECKED(Name, key, 1);
  4694. uint32_t index;
  4695. const bool key_is_array_index = key->AsArrayIndex(&index);
  4696. Object* obj = args[0];
  4697. // Only JS objects can have properties.
  4698. if (obj->IsJSObject()) {
  4699. JSObject* object = JSObject::cast(obj);
  4700. // Fast case: either the key is a real named property or it is not
  4701. // an array index and there are no interceptors or hidden
  4702. // prototypes.
  4703. if (object->HasRealNamedProperty(isolate, key)) {
  4704. ASSERT(!isolate->has_scheduled_exception());
  4705. return isolate->heap()->true_value();
  4706. } else {
  4707. RETURN_IF_SCHEDULED_EXCEPTION(isolate);
  4708. }
  4709. Map* map = object->map();
  4710. if (!key_is_array_index &&
  4711. !map->has_named_interceptor() &&
  4712. !HeapObject::cast(map->prototype())->map()->is_hidden_prototype()) {
  4713. return isolate->heap()->false_value();
  4714. }
  4715. // Slow case.
  4716. HandleScope scope(isolate);
  4717. return HasLocalPropertyImplementation(isolate,
  4718. Handle<JSObject>(object),
  4719. Handle<Name>(key));
  4720. } else if (obj->IsString() && key_is_array_index) {
  4721. // Well, there is one exception: Handle [] on strings.
  4722. String* string = String::cast(obj);
  4723. if (index < static_cast<uint32_t>(string->length())) {
  4724. return isolate->heap()->true_value();
  4725. }
  4726. }
  4727. return isolate->heap()->false_value();
  4728. }
  4729. RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) {
  4730. SealHandleScope shs(isolate);
  4731. ASSERT(args.length() == 2);
  4732. CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
  4733. CONVERT_ARG_CHECKED(Name, key, 1);
  4734. bool result = receiver->HasProperty(key);
  4735. RETURN_IF_SCHEDULED_EXCEPTION(isolate);
  4736. if (isolate->has_pending_exception()) return Failure::Exception();
  4737. return isolate->heap()->ToBoolean(result);
  4738. }
  4739. RUNTIME_FUNCTION(MaybeObject*, Runtime_HasElement) {
  4740. SealHandleScope shs(isolate);
  4741. ASSERT(args.length() == 2);
  4742. CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
  4743. CONVERT_SMI_ARG_CHECKED(index, 1);
  4744. bool result = receiver->HasElement(index);
  4745. RETURN_IF_SCHEDULED_EXCEPTION(isolate);
  4746. if (isolate->has_pending_exception()) return Failure::Exception();
  4747. return isolate->heap()->ToBoolean(result);
  4748. }
  4749. RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) {
  4750. SealHandleScope shs(isolate);
  4751. ASSERT(args.length() == 2);
  4752. CONVERT_ARG_CHECKED(JSObject, object, 0);
  4753. CONVERT_ARG_CHECKED(Name, key, 1);
  4754. PropertyAttributes att = object->GetLocalPropertyAttribute(key);
  4755. if (att == ABSENT || (att & DONT_ENUM) != 0) {
  4756. RETURN_IF_SCHEDULED_EXCEPTION(isolate);
  4757. return isolate->heap()->false_value();
  4758. }
  4759. ASSERT(!isolate->has_scheduled_exception());
  4760. return isolate->heap()->true_value();
  4761. }
  4762. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNames) {
  4763. HandleScope scope(isolate);
  4764. ASSERT(args.length() == 1);
  4765. CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
  4766. bool threw = false;
  4767. Handle<JSArray> result = GetKeysFor(object, &threw);
  4768. if (threw) return Failure::Exception();
  4769. return *result;
  4770. }
  4771. // Returns either a FixedArray as Runtime_GetPropertyNames,
  4772. // or, if the given object has an enum cache that contains
  4773. // all enumerable properties of the object and its prototypes
  4774. // have none, the map of the object. This is used to speed up
  4775. // the check for deletions during a for-in.
  4776. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNamesFast) {
  4777. SealHandleScope shs(isolate);
  4778. ASSERT(args.length() == 1);
  4779. CONVERT_ARG_CHECKED(JSReceiver, raw_object, 0);
  4780. if (raw_object->IsSimpleEnum()) return raw_object->map();
  4781. HandleScope scope(isolate);
  4782. Handle<JSReceiver> object(raw_object);
  4783. bool threw = false;
  4784. Handle<FixedArray> content =
  4785. GetKeysInFixedArrayFor(object, INCLUDE_PROTOS, &threw);
  4786. if (threw) return Failure::Exception();
  4787. // Test again, since cache may have been built by preceding call.
  4788. if (object->IsSimpleEnum()) return object->map();
  4789. return *content;
  4790. }
  4791. // Find the length of the prototype chain that is to to handled as one. If a
  4792. // prototype object is hidden it is to be viewed as part of the the object it
  4793. // is prototype for.
  4794. static int LocalPrototypeChainLength(JSObject* obj) {
  4795. int count = 1;
  4796. Object* proto = obj->GetPrototype();
  4797. while (proto->IsJSObject() &&
  4798. JSObject::cast(proto)->map()->is_hidden_prototype()) {
  4799. count++;
  4800. proto = JSObject::cast(proto)->GetPrototype();
  4801. }
  4802. return count;
  4803. }
  4804. // Return the names of the local named properties.
  4805. // args[0]: object
  4806. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) {
  4807. HandleScope scope(isolate);
  4808. ASSERT(args.length() == 2);
  4809. if (!args[0]->IsJSObject()) {
  4810. return isolate->heap()->undefined_value();
  4811. }
  4812. CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
  4813. CONVERT_BOOLEAN_ARG_CHECKED(include_symbols, 1);
  4814. PropertyAttributes filter = include_symbols ? NONE : SYMBOLIC;
  4815. // Skip the global proxy as it has no properties and always delegates to the
  4816. // real global object.
  4817. if (obj->IsJSGlobalProxy()) {
  4818. // Only collect names if access is permitted.
  4819. if (obj->IsAccessCheckNeeded() &&
  4820. !isolate->MayNamedAccess(*obj,
  4821. isolate->heap()->undefined_value(),
  4822. v8::ACCESS_KEYS)) {
  4823. isolate->ReportFailedAccessCheck(*obj, v8::ACCESS_KEYS);
  4824. RETURN_IF_SCHEDULED_EXCEPTION(isolate);
  4825. return *isolate->factory()->NewJSArray(0);
  4826. }
  4827. obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
  4828. }
  4829. // Find the number of objects making up this.
  4830. int length = LocalPrototypeChainLength(*obj);
  4831. // Find the number of local properties for each of the objects.
  4832. ScopedVector<int> local_property_count(length);
  4833. int total_property_count = 0;
  4834. Handle<JSObject> jsproto = obj;
  4835. for (int i = 0; i < length; i++) {
  4836. // Only collect names if access is permitted.
  4837. if (jsproto->IsAccessCheckNeeded() &&
  4838. !isolate->MayNamedAccess(*jsproto,
  4839. isolate->heap()->undefined_value(),
  4840. v8::ACCESS_KEYS)) {
  4841. isolate->ReportFailedAccessCheck(*jsproto, v8::ACCESS_KEYS);
  4842. RETURN_IF_SCHEDULED_EXCEPTION(isolate);
  4843. return *isolate->factory()->NewJSArray(0);
  4844. }
  4845. int n;
  4846. n = jsproto->NumberOfLocalProperties(filter);
  4847. local_property_count[i] = n;
  4848. total_property_count += n;
  4849. if (i < length - 1) {
  4850. jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
  4851. }
  4852. }
  4853. // Allocate an array with storage for all the property names.
  4854. Handle<FixedArray> names =
  4855. isolate->factory()->NewFixedArray(total_property_count);
  4856. // Get the property names.
  4857. jsproto = obj;
  4858. int proto_with_hidden_properties = 0;
  4859. int next_copy_index = 0;
  4860. for (int i = 0; i < length; i++) {
  4861. jsproto->GetLocalPropertyNames(*names, next_copy_index, filter);
  4862. next_copy_index += local_property_count[i];
  4863. if (jsproto->HasHiddenProperties()) {
  4864. proto_with_hidden_properties++;
  4865. }
  4866. if (i < length - 1) {
  4867. jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
  4868. }
  4869. }
  4870. // Filter out name of hidden properties object.
  4871. if (proto_with_hidden_properties > 0) {
  4872. Handle<FixedArray> old_names = names;
  4873. names = isolate->factory()->NewFixedArray(
  4874. names->length() - proto_with_hidden_properties);
  4875. int dest_pos = 0;
  4876. for (int i = 0; i < total_property_count; i++) {
  4877. Object* name = old_names->get(i);
  4878. if (name == isolate->heap()->hidden_string()) {
  4879. continue;
  4880. }
  4881. names->set(dest_pos++, name);
  4882. }
  4883. }
  4884. return *isolate->factory()->NewJSArrayWithElements(names);
  4885. }
  4886. // Return the names of the local indexed properties.
  4887. // args[0]: object
  4888. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalElementNames) {
  4889. HandleScope scope(isolate);
  4890. ASSERT(args.length() == 1);
  4891. if (!args[0]->IsJSObject()) {
  4892. return isolate->heap()->undefined_value();
  4893. }
  4894. CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
  4895. int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
  4896. Handle<FixedArray> names = isolate->factory()->NewFixedArray(n);
  4897. obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
  4898. return *isolate->factory()->NewJSArrayWithElements(names);
  4899. }
  4900. // Return information on whether an object has a named or indexed interceptor.
  4901. // args[0]: object
  4902. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetInterceptorInfo) {
  4903. HandleScope scope(isolate);
  4904. ASSERT(args.length() == 1);
  4905. if (!args[0]->IsJSObject()) {
  4906. return Smi::FromInt(0);
  4907. }
  4908. CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
  4909. int result = 0;
  4910. if (obj->HasNamedInterceptor()) result |= 2;
  4911. if (obj->HasIndexedInterceptor()) result |= 1;
  4912. return Smi::FromInt(result);
  4913. }
  4914. // Return property names from named interceptor.
  4915. // args[0]: object
  4916. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetNamedInterceptorPropertyNames) {
  4917. HandleScope scope(isolate);
  4918. ASSERT(args.length() == 1);
  4919. CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
  4920. if (obj->HasNamedInterceptor()) {
  4921. v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
  4922. if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
  4923. }
  4924. return isolate->heap()->undefined_value();
  4925. }
  4926. // Return element names from indexed interceptor.
  4927. // args[0]: object
  4928. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetIndexedInterceptorElementNames) {
  4929. HandleScope scope(isolate);
  4930. ASSERT(args.length() == 1);
  4931. CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
  4932. if (obj->HasIndexedInterceptor()) {
  4933. v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
  4934. if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
  4935. }
  4936. return isolate->heap()->undefined_value();
  4937. }
  4938. RUNTIME_FUNCTION(MaybeObject*, Runtime_LocalKeys) {
  4939. HandleScope scope(isolate);
  4940. ASSERT_EQ(args.length(), 1);
  4941. CONVERT_ARG_CHECKED(JSObject, raw_object, 0);
  4942. Handle<JSObject> object(raw_object);
  4943. if (object->IsJSGlobalProxy()) {
  4944. // Do access checks before going to the global object.
  4945. if (object->IsAccessCheckNeeded() &&
  4946. !isolate->MayNamedAccess(*object, isolate->heap()->undefined_value(),
  4947. v8::ACCESS_KEYS)) {
  4948. isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
  4949. RETURN_IF_SCHEDULED_EXCEPTION(isolate);
  4950. return *isolate->factory()->NewJSArray(0);
  4951. }
  4952. Handle<Object> proto(object->GetPrototype(), isolate);
  4953. // If proxy is detached we simply return an empty array.
  4954. if (proto->IsNull()) return *isolate->factory()->NewJSArray(0);
  4955. object = Handle<JSObject>::cast(proto);
  4956. }
  4957. bool threw = false;
  4958. Handle<FixedArray> contents =
  4959. GetKeysInFixedArrayFor(object, LOCAL_ONLY, &threw);
  4960. if (threw) return Failure::Exception();
  4961. // Some fast paths through GetKeysInFixedArrayFor reuse a cached
  4962. // property array and since the result is mutable we have to create
  4963. // a fresh clone on each invocation.
  4964. int length = contents->length();
  4965. Handle<FixedArray> copy = isolate->factory()->NewFixedArray(length);
  4966. for (int i = 0; i < length; i++) {
  4967. Object* entry = contents->get(i);
  4968. if (entry->IsString()) {
  4969. copy->set(i, entry);
  4970. } else {
  4971. ASSERT(entry->IsNumber());
  4972. HandleScope scope(isolate);
  4973. Handle<Object> entry_handle(entry, isolate);
  4974. Handle<Object> entry_str =
  4975. isolate->factory()->NumberToString(entry_handle);
  4976. copy->set(i, *entry_str);
  4977. }
  4978. }
  4979. return *isolate->factory()->NewJSArrayWithElements(copy);
  4980. }
  4981. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
  4982. SealHandleScope shs(isolate);
  4983. ASSERT(args.length() == 1);
  4984. // Compute the frame holding the arguments.
  4985. JavaScriptFrameIterator it(isolate);
  4986. it.AdvanceToArgumentsFrame();
  4987. JavaScriptFrame* frame = it.frame();
  4988. // Get the actual number of provided arguments.
  4989. const uint32_t n = frame->ComputeParametersCount();
  4990. // Try to convert the key to an index. If successful and within
  4991. // index return the the argument from the frame.
  4992. uint32_t index;
  4993. if (args[0]->ToArrayIndex(&index) && index < n) {
  4994. return frame->GetParameter(index);
  4995. }
  4996. if (args[0]->IsSymbol()) {
  4997. // Lookup in the initial Object.prototype object.
  4998. return isolate->initial_object_prototype()->GetProperty(
  4999. Symbol::cast(args[0]));
  5000. }
  5001. // Convert the key to a string.
  5002. HandleScope scope(isolate);
  5003. bool exception = false;
  5004. Handle<Object> converted =
  5005. Execution::ToString(args.at<Object>(0), &exception);
  5006. if (exception) return Failure::Exception();
  5007. Handle<String> key = Handle<String>::cast(converted);
  5008. // Try to convert the string key into an array index.
  5009. if (key->AsArrayIndex(&index)) {
  5010. if (index < n) {
  5011. return frame->GetParameter(index);
  5012. } else {
  5013. return isolate->initial_object_prototype()->GetElement(index);
  5014. }
  5015. }
  5016. // Handle special arguments properties.
  5017. if (key->Equals(isolate->heap()->length_string())) return Smi::FromInt(n);
  5018. if (key->Equals(isolate->heap()->callee_string())) {
  5019. JSFunction* function = frame->function();
  5020. if (!function->shared()->is_classic_mode()) {
  5021. return isolate->Throw(*isolate->factory()->NewTypeError(
  5022. "strict_arguments_callee", HandleVector<Object>(NULL, 0)));
  5023. }
  5024. return function;
  5025. }
  5026. // Lookup in the initial Object.prototype object.
  5027. return isolate->initial_object_prototype()->GetProperty(*key);
  5028. }
  5029. RUNTIME_FUNCTION(MaybeObject*, Runtime_ToFastProperties) {
  5030. SealHandleScope shs(isolate);
  5031. ASSERT(args.length() == 1);
  5032. Object* object = args[0];
  5033. return (object->IsJSObject() && !object->IsGlobalObject())
  5034. ? JSObject::cast(object)->TransformToFastProperties(0)
  5035. : object;
  5036. }
  5037. RUNTIME_FUNCTION(MaybeObject*, Runtime_ToBool) {
  5038. SealHandleScope shs(isolate);
  5039. ASSERT(args.length() == 1);
  5040. return isolate->heap()->ToBoolean(args[0]->BooleanValue());
  5041. }
  5042. // Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
  5043. // Possible optimizations: put the type string into the oddballs.
  5044. RUNTIME_FUNCTION(MaybeObject*, Runtime_Typeof) {
  5045. SealHandleScope shs(isolate);
  5046. Object* obj = args[0];
  5047. if (obj->IsNumber()) return isolate->heap()->number_string();
  5048. HeapObject* heap_obj = HeapObject::cast(obj);
  5049. // typeof an undetectable object is 'undefined'
  5050. if (heap_obj->map()->is_undetectable()) {
  5051. return isolate->heap()->undefined_string();
  5052. }
  5053. InstanceType instance_type = heap_obj->map()->instance_type();
  5054. if (instance_type < FIRST_NONSTRING_TYPE) {
  5055. return isolate->heap()->string_string();
  5056. }
  5057. switch (instance_type) {
  5058. case ODDBALL_TYPE:
  5059. if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
  5060. return isolate->heap()->boolean_string();
  5061. }
  5062. if (heap_obj->IsNull()) {
  5063. return FLAG_harmony_typeof
  5064. ? isolate->heap()->null_string()
  5065. : isolate->heap()->object_string();
  5066. }
  5067. ASSERT(heap_obj->IsUndefined());
  5068. return isolate->heap()->undefined_string();
  5069. case SYMBOL_TYPE:
  5070. return isolate->heap()->symbol_string();
  5071. case JS_FUNCTION_TYPE:
  5072. case JS_FUNCTION_PROXY_TYPE:
  5073. return isolate->heap()->function_string();
  5074. default:
  5075. // For any kind of object not handled above, the spec rule for
  5076. // host objects gives that it is okay to return "object"
  5077. return isolate->heap()->object_string();
  5078. }
  5079. }
  5080. static bool AreDigits(const uint8_t*s, int from, int to) {
  5081. for (int i = from; i < to; i++) {
  5082. if (s[i] < '0' || s[i] > '9') return false;
  5083. }
  5084. return true;
  5085. }
  5086. static int ParseDecimalInteger(const uint8_t*s, int from, int to) {
  5087. ASSERT(to - from < 10); // Overflow is not possible.
  5088. ASSERT(from < to);
  5089. int d = s[from] - '0';
  5090. for (int i = from + 1; i < to; i++) {
  5091. d = 10 * d + (s[i] - '0');
  5092. }
  5093. return d;
  5094. }
  5095. RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
  5096. SealHandleScope shs(isolate);
  5097. ASSERT(args.length() == 1);
  5098. CONVERT_ARG_CHECKED(String, subject, 0);
  5099. subject->TryFlatten();
  5100. // Fast case: short integer or some sorts of junk values.
  5101. int len = subject->length();
  5102. if (subject->IsSeqOneByteString()) {
  5103. if (len == 0) return Smi::FromInt(0);
  5104. uint8_t const* data = SeqOneByteString::cast(subject)->GetChars();
  5105. bool minus = (data[0] == '-');
  5106. int start_pos = (minus ? 1 : 0);
  5107. if (start_pos == len) {
  5108. return isolate->heap()->nan_value();
  5109. } else if (data[start_pos] > '9') {
  5110. // Fast check for a junk value. A valid string may start from a
  5111. // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit or
  5112. // the 'I' character ('Infinity'). All of that have codes not greater than
  5113. // '9' except 'I' and &nbsp;.
  5114. if (data[start_pos] != 'I' && data[start_pos] != 0xa0) {
  5115. return isolate->heap()->nan_value();
  5116. }
  5117. } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
  5118. // The maximal/minimal smi has 10 digits. If the string has less digits we
  5119. // know it will fit into the smi-data type.
  5120. int d = ParseDecimalInteger(data, start_pos, len);
  5121. if (minus) {
  5122. if (d == 0) return isolate->heap()->minus_zero_value();
  5123. d = -d;
  5124. } else if (!subject->HasHashCode() &&
  5125. len <= String::kMaxArrayIndexSize &&
  5126. (len == 1 || data[0] != '0')) {
  5127. // String hash is not calculated yet but all the data are present.
  5128. // Update the hash field to speed up sequential convertions.
  5129. uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
  5130. #ifdef DEBUG
  5131. subject->Hash(); // Force hash calculation.
  5132. ASSERT_EQ(static_cast<int>(subject->hash_field()),
  5133. static_cast<int>(hash));
  5134. #endif
  5135. subject->set_hash_field(hash);
  5136. }
  5137. return Smi::FromInt(d);
  5138. }
  5139. }
  5140. // Slower case.
  5141. int flags = ALLOW_HEX;
  5142. if (FLAG_harmony_numeric_literals) {
  5143. // The current spec draft has not updated "ToNumber Applied to the String
  5144. // Type", https://bugs.ecmascript.org/show_bug.cgi?id=1584
  5145. flags |= ALLOW_OCTAL | ALLOW_BINARY;
  5146. }
  5147. return isolate->heap()->NumberFromDouble(
  5148. StringToDouble(isolate->unicode_cache(), subject, flags));
  5149. }
  5150. RUNTIME_FUNCTION(MaybeObject*, Runtime_NewString) {
  5151. SealHandleScope shs(isolate);
  5152. CONVERT_SMI_ARG_CHECKED(length, 0);
  5153. CONVERT_BOOLEAN_ARG_CHECKED(is_one_byte, 1);
  5154. if (length == 0) return isolate->heap()->empty_string();
  5155. if (is_one_byte) {
  5156. return isolate->heap()->AllocateRawOneByteString(length);
  5157. } else {
  5158. return isolate->heap()->AllocateRawTwoByteString(length);
  5159. }
  5160. }
  5161. RUNTIME_FUNCTION(MaybeObject*, Runtime_TruncateString) {
  5162. HandleScope scope(isolate);
  5163. CONVERT_ARG_HANDLE_CHECKED(SeqString, string, 0);
  5164. CONVERT_SMI_ARG_CHECKED(new_length, 1);
  5165. return *SeqString::Truncate(string, new_length);
  5166. }
  5167. RUNTIME_FUNCTION(MaybeObject*, Runtime_URIEscape) {
  5168. HandleScope scope(isolate);
  5169. ASSERT(args.length() == 1);
  5170. CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
  5171. Handle<String> string = FlattenGetString(source);
  5172. ASSERT(string->IsFlat());
  5173. Handle<String> result = string->IsOneByteRepresentationUnderneath()
  5174. ? URIEscape::Escape<uint8_t>(isolate, source)
  5175. : URIEscape::Escape<uc16>(isolate, source);
  5176. if (result.is_null()) return Failure::OutOfMemoryException(0x12);
  5177. return *result;
  5178. }
  5179. RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) {
  5180. HandleScope scope(isolate);
  5181. ASSERT(args.length() == 1);
  5182. CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
  5183. Handle<String> string = FlattenGetString(source);
  5184. ASSERT(string->IsFlat());
  5185. return string->IsOneByteRepresentationUnderneath()
  5186. ? *URIUnescape::Unescape<uint8_t>(isolate, source)
  5187. : *URIUnescape::Unescape<uc16>(isolate, source);
  5188. }
  5189. RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONString) {
  5190. HandleScope scope(isolate);
  5191. CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
  5192. ASSERT(args.length() == 1);
  5193. return BasicJsonStringifier::StringifyString(isolate, string);
  5194. }
  5195. RUNTIME_FUNCTION(MaybeObject*, Runtime_BasicJSONStringify) {
  5196. HandleScope scope(isolate);
  5197. ASSERT(args.length() == 1);
  5198. BasicJsonStringifier stringifier(isolate);
  5199. return stringifier.Stringify(Handle<Object>(args[0], isolate));
  5200. }
  5201. RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) {
  5202. SealHandleScope shs(isolate);
  5203. CONVERT_ARG_CHECKED(String, s, 0);
  5204. CONVERT_SMI_ARG_CHECKED(radix, 1);
  5205. s->TryFlatten();
  5206. RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
  5207. double value = StringToInt(isolate->unicode_cache(), s, radix);
  5208. return isolate->heap()->NumberFromDouble(value);
  5209. }
  5210. RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) {
  5211. SealHandleScope shs(isolate);
  5212. CONVERT_ARG_CHECKED(String, str, 0);
  5213. // ECMA-262 section 15.1.2.3, empty string is NaN
  5214. double value = StringToDouble(isolate->unicode_cache(),
  5215. str, ALLOW_TRAILING_JUNK, OS::nan_value());
  5216. // Create a number object from the value.
  5217. return isolate->heap()->NumberFromDouble(value);
  5218. }
  5219. template <class Converter>
  5220. MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
  5221. Isolate* isolate,
  5222. String* s,
  5223. int length,
  5224. int input_string_length,
  5225. unibrow::Mapping<Converter, 128>* mapping) {
  5226. // We try this twice, once with the assumption that the result is no longer
  5227. // than the input and, if that assumption breaks, again with the exact
  5228. // length. This may not be pretty, but it is nicer than what was here before
  5229. // and I hereby claim my vaffel-is.
  5230. //
  5231. // Allocate the resulting string.
  5232. //
  5233. // NOTE: This assumes that the upper/lower case of an ASCII
  5234. // character is also ASCII. This is currently the case, but it
  5235. // might break in the future if we implement more context and locale
  5236. // dependent upper/lower conversions.
  5237. Object* o;
  5238. { MaybeObject* maybe_o = s->IsOneByteRepresentation()
  5239. ? isolate->heap()->AllocateRawOneByteString(length)
  5240. : isolate->heap()->AllocateRawTwoByteString(length);
  5241. if (!maybe_o->ToObject(&o)) return maybe_o;
  5242. }
  5243. String* result = String::cast(o);
  5244. bool has_changed_character = false;
  5245. // Convert all characters to upper case, assuming that they will fit
  5246. // in the buffer
  5247. Access<ConsStringIteratorOp> op(
  5248. isolate->runtime_state()->string_iterator());
  5249. StringCharacterStream stream(s, op.value());
  5250. unibrow::uchar chars[Converter::kMaxWidth];
  5251. // We can assume that the string is not empty
  5252. uc32 current = stream.GetNext();
  5253. for (int i = 0; i < length;) {
  5254. bool has_next = stream.HasMore();
  5255. uc32 next = has_next ? stream.GetNext() : 0;
  5256. int char_length = mapping->get(current, next, chars);
  5257. if (char_length == 0) {
  5258. // The case conversion of this character is the character itself.
  5259. result->Set(i, current);
  5260. i++;
  5261. } else if (char_length == 1) {
  5262. // Common case: converting the letter resulted in one character.
  5263. ASSERT(static_cast<uc32>(chars[0]) != current);
  5264. result->Set(i, chars[0]);
  5265. has_changed_character = true;
  5266. i++;
  5267. } else if (length == input_string_length) {
  5268. // We've assumed that the result would be as long as the
  5269. // input but here is a character that converts to several
  5270. // characters. No matter, we calculate the exact length
  5271. // of the result and try the whole thing again.
  5272. //
  5273. // Note that this leaves room for optimization. We could just
  5274. // memcpy what we already have to the result string. Also,
  5275. // the result string is the last object allocated we could
  5276. // "realloc" it and probably, in the vast majority of cases,
  5277. // extend the existing string to be able to hold the full
  5278. // result.
  5279. int next_length = 0;
  5280. if (has_next) {
  5281. next_length = mapping->get(next, 0, chars);
  5282. if (next_length == 0) next_length = 1;
  5283. }
  5284. int current_length = i + char_length + next_length;
  5285. while (stream.HasMore()) {
  5286. current = stream.GetNext();
  5287. // NOTE: we use 0 as the next character here because, while
  5288. // the next character may affect what a character converts to,
  5289. // it does not in any case affect the length of what it convert
  5290. // to.
  5291. int char_length = mapping->get(current, 0, chars);
  5292. if (char_length == 0) char_length = 1;
  5293. current_length += char_length;
  5294. if (current_length > Smi::kMaxValue) {
  5295. isolate->context()->mark_out_of_memory();
  5296. return Failure::OutOfMemoryException(0x13);
  5297. }
  5298. }
  5299. // Try again with the real length.
  5300. return Smi::FromInt(current_length);
  5301. } else {
  5302. for (int j = 0; j < char_length; j++) {
  5303. result->Set(i, chars[j]);
  5304. i++;
  5305. }
  5306. has_changed_character = true;
  5307. }
  5308. current = next;
  5309. }
  5310. if (has_changed_character) {
  5311. return result;
  5312. } else {
  5313. // If we didn't actually change anything in doing the conversion
  5314. // we simple return the result and let the converted string
  5315. // become garbage; there is no reason to keep two identical strings
  5316. // alive.
  5317. return s;
  5318. }
  5319. }
  5320. namespace {
  5321. static const uintptr_t kOneInEveryByte = kUintptrAllBitsSet / 0xFF;
  5322. static const uintptr_t kAsciiMask = kOneInEveryByte << 7;
  5323. // Given a word and two range boundaries returns a word with high bit
  5324. // set in every byte iff the corresponding input byte was strictly in
  5325. // the range (m, n). All the other bits in the result are cleared.
  5326. // This function is only useful when it can be inlined and the
  5327. // boundaries are statically known.
  5328. // Requires: all bytes in the input word and the boundaries must be
  5329. // ASCII (less than 0x7F).
  5330. static inline uintptr_t AsciiRangeMask(uintptr_t w, char m, char n) {
  5331. // Use strict inequalities since in edge cases the function could be
  5332. // further simplified.
  5333. ASSERT(0 < m && m < n);
  5334. // Has high bit set in every w byte less than n.
  5335. uintptr_t tmp1 = kOneInEveryByte * (0x7F + n) - w;
  5336. // Has high bit set in every w byte greater than m.
  5337. uintptr_t tmp2 = w + kOneInEveryByte * (0x7F - m);
  5338. return (tmp1 & tmp2 & (kOneInEveryByte * 0x80));
  5339. }
  5340. enum AsciiCaseConversion {
  5341. ASCII_TO_LOWER,
  5342. ASCII_TO_UPPER
  5343. };
  5344. template <AsciiCaseConversion dir>
  5345. struct FastAsciiConverter {
  5346. static bool Convert(char* dst, char* src, int length, bool* changed_out) {
  5347. #ifdef DEBUG
  5348. char* saved_dst = dst;
  5349. char* saved_src = src;
  5350. #endif
  5351. // We rely on the distance between upper and lower case letters
  5352. // being a known power of 2.
  5353. ASSERT('a' - 'A' == (1 << 5));
  5354. // Boundaries for the range of input characters than require conversion.
  5355. const char lo = (dir == ASCII_TO_LOWER) ? 'A' - 1 : 'a' - 1;
  5356. const char hi = (dir == ASCII_TO_LOWER) ? 'Z' + 1 : 'z' + 1;
  5357. bool changed = false;
  5358. uintptr_t or_acc = 0;
  5359. char* const limit = src + length;
  5360. #ifdef V8_HOST_CAN_READ_UNALIGNED
  5361. // Process the prefix of the input that requires no conversion one
  5362. // (machine) word at a time.
  5363. while (src <= limit - sizeof(uintptr_t)) {
  5364. uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
  5365. or_acc |= w;
  5366. if (AsciiRangeMask(w, lo, hi) != 0) {
  5367. changed = true;
  5368. break;
  5369. }
  5370. *reinterpret_cast<uintptr_t*>(dst) = w;
  5371. src += sizeof(uintptr_t);
  5372. dst += sizeof(uintptr_t);
  5373. }
  5374. // Process the remainder of the input performing conversion when
  5375. // required one word at a time.
  5376. while (src <= limit - sizeof(uintptr_t)) {
  5377. uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
  5378. or_acc |= w;
  5379. uintptr_t m = AsciiRangeMask(w, lo, hi);
  5380. // The mask has high (7th) bit set in every byte that needs
  5381. // conversion and we know that the distance between cases is
  5382. // 1 << 5.
  5383. *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2);
  5384. src += sizeof(uintptr_t);
  5385. dst += sizeof(uintptr_t);
  5386. }
  5387. #endif
  5388. // Process the last few bytes of the input (or the whole input if
  5389. // unaligned access is not supported).
  5390. while (src < limit) {
  5391. char c = *src;
  5392. or_acc |= c;
  5393. if (lo < c && c < hi) {
  5394. c ^= (1 << 5);
  5395. changed = true;
  5396. }
  5397. *dst = c;
  5398. ++src;
  5399. ++dst;
  5400. }
  5401. if ((or_acc & kAsciiMask) != 0) {
  5402. return false;
  5403. }
  5404. #ifdef DEBUG
  5405. CheckConvert(saved_dst, saved_src, length, changed);
  5406. #endif
  5407. *changed_out = changed;
  5408. return true;
  5409. }
  5410. #ifdef DEBUG
  5411. static void CheckConvert(char* dst, char* src, int length, bool changed) {
  5412. bool expected_changed = false;
  5413. for (int i = 0; i < length; i++) {
  5414. if (dst[i] == src[i]) continue;
  5415. expected_changed = true;
  5416. if (dir == ASCII_TO_LOWER) {
  5417. ASSERT('A' <= src[i] && src[i] <= 'Z');
  5418. ASSERT(dst[i] == src[i] + ('a' - 'A'));
  5419. } else {
  5420. ASSERT(dir == ASCII_TO_UPPER);
  5421. ASSERT('a' <= src[i] && src[i] <= 'z');
  5422. ASSERT(dst[i] == src[i] - ('a' - 'A'));
  5423. }
  5424. }
  5425. ASSERT(expected_changed == changed);
  5426. }
  5427. #endif
  5428. };
  5429. struct ToLowerTraits {
  5430. typedef unibrow::ToLowercase UnibrowConverter;
  5431. typedef FastAsciiConverter<ASCII_TO_LOWER> AsciiConverter;
  5432. };
  5433. struct ToUpperTraits {
  5434. typedef unibrow::ToUppercase UnibrowConverter;
  5435. typedef FastAsciiConverter<ASCII_TO_UPPER> AsciiConverter;
  5436. };
  5437. } // namespace
  5438. template <typename ConvertTraits>
  5439. MUST_USE_RESULT static MaybeObject* ConvertCase(
  5440. Arguments args,
  5441. Isolate* isolate,
  5442. unibrow::Mapping<typename ConvertTraits::UnibrowConverter, 128>* mapping) {
  5443. SealHandleScope shs(isolate);
  5444. CONVERT_ARG_CHECKED(String, s, 0);
  5445. s = s->TryFlattenGetString();
  5446. const int length = s->length();
  5447. // Assume that the string is not empty; we need this assumption later
  5448. if (length == 0) return s;
  5449. // Simpler handling of ASCII strings.
  5450. //
  5451. // NOTE: This assumes that the upper/lower case of an ASCII
  5452. // character is also ASCII. This is currently the case, but it
  5453. // might break in the future if we implement more context and locale
  5454. // dependent upper/lower conversions.
  5455. if (s->IsSeqOneByteString()) {
  5456. Object* o;
  5457. { MaybeObject* maybe_o = isolate->heap()->AllocateRawOneByteString(length);
  5458. if (!maybe_o->ToObject(&o)) return maybe_o;
  5459. }
  5460. SeqOneByteString* result = SeqOneByteString::cast(o);
  5461. bool has_changed_character;
  5462. bool is_ascii = ConvertTraits::AsciiConverter::Convert(
  5463. reinterpret_cast<char*>(result->GetChars()),
  5464. reinterpret_cast<char*>(SeqOneByteString::cast(s)->GetChars()),
  5465. length,
  5466. &has_changed_character);
  5467. // If not ASCII, we discard the result and take the 2 byte path.
  5468. if (is_ascii) {
  5469. return has_changed_character ? result : s;
  5470. }
  5471. }
  5472. Object* answer;
  5473. { MaybeObject* maybe_answer =
  5474. ConvertCaseHelper(isolate, s, length, length, mapping);
  5475. if (!maybe_answer->ToObject(&answer)) return maybe_answer;
  5476. }
  5477. if (answer->IsSmi()) {
  5478. // Retry with correct length.
  5479. { MaybeObject* maybe_answer =
  5480. ConvertCaseHelper(isolate,
  5481. s, Smi::cast(answer)->value(), length, mapping);
  5482. if (!maybe_answer->ToObject(&answer)) return maybe_answer;
  5483. }
  5484. }
  5485. return answer;
  5486. }
  5487. RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) {
  5488. return ConvertCase<ToLowerTraits>(
  5489. args, isolate, isolate->runtime_state()->to_lower_mapping());
  5490. }
  5491. RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToUpperCase) {
  5492. return ConvertCase<ToUpperTraits>(
  5493. args, isolate, isolate->runtime_state()->to_upper_mapping());
  5494. }
  5495. static inline bool IsTrimWhiteSpace(unibrow::uchar c) {
  5496. return unibrow::WhiteSpace::Is(c) || c == 0x200b || c == 0xfeff;
  5497. }
  5498. RUNTIME_FUNCTION(MaybeObject*, Runtime_StringTrim) {
  5499. SealHandleScope shs(isolate);
  5500. ASSERT(args.length() == 3);
  5501. CONVERT_ARG_CHECKED(String, s, 0);
  5502. CONVERT_BOOLEAN_ARG_CHECKED(trimLeft, 1);
  5503. CONVERT_BOOLEAN_ARG_CHECKED(trimRight, 2);
  5504. s->TryFlatten();
  5505. int length = s->length();
  5506. int left = 0;
  5507. if (trimLeft) {
  5508. while (left < length && IsTrimWhiteSpace(s->Get(left))) {
  5509. left++;
  5510. }
  5511. }
  5512. int right = length;
  5513. if (trimRight) {
  5514. while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) {
  5515. right--;
  5516. }
  5517. }
  5518. return s->SubString(left, right);
  5519. }
  5520. RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
  5521. HandleScope handle_scope(isolate);
  5522. ASSERT(args.length() == 3);
  5523. CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
  5524. CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
  5525. CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]);
  5526. int subject_length = subject->length();
  5527. int pattern_length = pattern->length();
  5528. RUNTIME_ASSERT(pattern_length > 0);
  5529. if (limit == 0xffffffffu) {
  5530. Handle<Object> cached_answer(
  5531. RegExpResultsCache::Lookup(isolate->heap(),
  5532. *subject,
  5533. *pattern,
  5534. RegExpResultsCache::STRING_SPLIT_SUBSTRINGS),
  5535. isolate);
  5536. if (*cached_answer != Smi::FromInt(0)) {
  5537. // The cache FixedArray is a COW-array and can therefore be reused.
  5538. Handle<JSArray> result =
  5539. isolate->factory()->NewJSArrayWithElements(
  5540. Handle<FixedArray>::cast(cached_answer));
  5541. return *result;
  5542. }
  5543. }
  5544. // The limit can be very large (0xffffffffu), but since the pattern
  5545. // isn't empty, we can never create more parts than ~half the length
  5546. // of the subject.
  5547. if (!subject->IsFlat()) FlattenString(subject);
  5548. static const int kMaxInitialListCapacity = 16;
  5549. ZoneScope zone_scope(isolate->runtime_zone());
  5550. // Find (up to limit) indices of separator and end-of-string in subject
  5551. int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit);
  5552. ZoneList<int> indices(initial_capacity, zone_scope.zone());
  5553. if (!pattern->IsFlat()) FlattenString(pattern);
  5554. FindStringIndicesDispatch(isolate, *subject, *pattern,
  5555. &indices, limit, zone_scope.zone());
  5556. if (static_cast<uint32_t>(indices.length()) < limit) {
  5557. indices.Add(subject_length, zone_scope.zone());
  5558. }
  5559. // The list indices now contains the end of each part to create.
  5560. // Create JSArray of substrings separated by separator.
  5561. int part_count = indices.length();
  5562. Handle<JSArray> result = isolate->factory()->NewJSArray(part_count);
  5563. MaybeObject* maybe_result = result->EnsureCanContainHeapObjectElements();
  5564. if (maybe_result->IsFailure()) return maybe_result;
  5565. result->set_length(Smi::FromInt(part_count));
  5566. ASSERT(result->HasFastObjectElements());
  5567. if (part_count == 1 && indices.at(0) == subject_length) {
  5568. FixedArray::cast(result->elements())->set(0, *subject);
  5569. return *result;
  5570. }
  5571. Handle<FixedArray> elements(FixedArray::cast(result->elements()));
  5572. int part_start = 0;
  5573. for (int i = 0; i < part_count; i++) {
  5574. HandleScope local_loop_handle(isolate);
  5575. int part_end = indices.at(i);
  5576. Handle<String> substring =
  5577. isolate->factory()->NewProperSubString(subject, part_start, part_end);
  5578. elements->set(i, *substring);
  5579. part_start = part_end + pattern_length;
  5580. }
  5581. if (limit == 0xffffffffu) {
  5582. if (result->HasFastObjectElements()) {
  5583. RegExpResultsCache::Enter(isolate->heap(),
  5584. *subject,
  5585. *pattern,
  5586. *elements,
  5587. RegExpResultsCache::STRING_SPLIT_SUBSTRINGS);
  5588. }
  5589. }
  5590. return *result;
  5591. }
  5592. // Copies ASCII characters to the given fixed array looking up
  5593. // one-char strings in the cache. Gives up on the first char that is
  5594. // not in the cache and fills the remainder with smi zeros. Returns
  5595. // the length of the successfully copied prefix.
  5596. static int CopyCachedAsciiCharsToArray(Heap* heap,
  5597. const uint8_t* chars,
  5598. FixedArray* elements,
  5599. int length) {
  5600. DisallowHeapAllocation no_gc;
  5601. FixedArray* ascii_cache = heap->single_character_string_cache();
  5602. Object* undefined = heap->undefined_value();
  5603. int i;
  5604. WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
  5605. for (i = 0; i < length; ++i) {
  5606. Object* value = ascii_cache->get(chars[i]);
  5607. if (value == undefined) break;
  5608. elements->set(i, value, mode);
  5609. }
  5610. if (i < length) {
  5611. ASSERT(Smi::FromInt(0) == 0);
  5612. memset(elements->data_start() + i, 0, kPointerSize * (length - i));
  5613. }
  5614. #ifdef DEBUG
  5615. for (int j = 0; j < length; ++j) {
  5616. Object* element = elements->get(j);
  5617. ASSERT(element == Smi::FromInt(0) ||
  5618. (element->IsString() && String::cast(element)->LooksValid()));
  5619. }
  5620. #endif
  5621. return i;
  5622. }
  5623. // Converts a String to JSArray.
  5624. // For example, "foo" => ["f", "o", "o"].
  5625. RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToArray) {
  5626. HandleScope scope(isolate);
  5627. ASSERT(args.length() == 2);
  5628. CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
  5629. CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
  5630. s = FlattenGetString(s);
  5631. const int length = static_cast<int>(Min<uint32_t>(s->length(), limit));
  5632. Handle<FixedArray> elements;
  5633. int position = 0;
  5634. if (s->IsFlat() && s->IsOneByteRepresentation()) {
  5635. // Try using cached chars where possible.
  5636. Object* obj;
  5637. { MaybeObject* maybe_obj =
  5638. isolate->heap()->AllocateUninitializedFixedArray(length);
  5639. if (!maybe_obj->ToObject(&obj)) return maybe_obj;
  5640. }
  5641. elements = Handle<FixedArray>(FixedArray::cast(obj), isolate);
  5642. DisallowHeapAllocation no_gc;
  5643. String::FlatContent content = s->GetFlatContent();
  5644. if (content.IsAscii()) {
  5645. Vector<const uint8_t> chars = content.ToOneByteVector();
  5646. // Note, this will initialize all elements (not only the prefix)
  5647. // to prevent GC from seeing partially initialized array.
  5648. position = CopyCachedAsciiCharsToArray(isolate->heap(),
  5649. chars.start(),
  5650. *elements,
  5651. length);
  5652. } else {
  5653. MemsetPointer(elements->data_start(),
  5654. isolate->heap()->undefined_value(),
  5655. length);
  5656. }
  5657. } else {
  5658. elements = isolate->factory()->NewFixedArray(length);
  5659. }
  5660. for (int i = position; i < length; ++i) {
  5661. Handle<Object> str =
  5662. LookupSingleCharacterStringFromCode(isolate, s->Get(i));
  5663. elements->set(i, *str);
  5664. }
  5665. #ifdef DEBUG
  5666. for (int i = 0; i < length; ++i) {
  5667. ASSERT(String::cast(elements->get(i))->length() == 1);
  5668. }
  5669. #endif
  5670. return *isolate->factory()->NewJSArrayWithElements(elements);
  5671. }
  5672. RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStringWrapper) {
  5673. SealHandleScope shs(isolate);
  5674. ASSERT(args.length() == 1);
  5675. CONVERT_ARG_CHECKED(String, value, 0);
  5676. return value->ToObject();
  5677. }
  5678. bool Runtime::IsUpperCaseChar(RuntimeState* runtime_state, uint16_t ch) {
  5679. unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth];
  5680. int char_length = runtime_state->to_upper_mapping()->get(ch, 0, chars);
  5681. return char_length == 0;
  5682. }
  5683. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToString) {
  5684. SealHandleScope shs(isolate);
  5685. ASSERT(args.length() == 1);
  5686. Object* number = args[0];
  5687. RUNTIME_ASSERT(number->IsNumber());
  5688. return isolate->heap()->NumberToString(number);
  5689. }
  5690. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToStringSkipCache) {
  5691. SealHandleScope shs(isolate);
  5692. ASSERT(args.length() == 1);
  5693. Object* number = args[0];
  5694. RUNTIME_ASSERT(number->IsNumber());
  5695. return isolate->heap()->NumberToString(
  5696. number, false, isolate->heap()->GetPretenureMode());
  5697. }
  5698. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToInteger) {
  5699. SealHandleScope shs(isolate);
  5700. ASSERT(args.length() == 1);
  5701. CONVERT_DOUBLE_ARG_CHECKED(number, 0);
  5702. // We do not include 0 so that we don't have to treat +0 / -0 cases.
  5703. if (number > 0 && number <= Smi::kMaxValue) {
  5704. return Smi::FromInt(static_cast<int>(number));
  5705. }
  5706. return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
  5707. }
  5708. // ES6 draft 9.1.11
  5709. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPositiveInteger) {
  5710. SealHandleScope shs(isolate);
  5711. ASSERT(args.length() == 1);
  5712. CONVERT_DOUBLE_ARG_CHECKED(number, 0);
  5713. // We do not include 0 so that we don't have to treat +0 / -0 cases.
  5714. if (number > 0 && number <= Smi::kMaxValue) {
  5715. return Smi::FromInt(static_cast<int>(number));
  5716. }
  5717. if (number <= 0) {
  5718. return Smi::FromInt(0);
  5719. }
  5720. return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
  5721. }
  5722. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToIntegerMapMinusZero) {
  5723. SealHandleScope shs(isolate);
  5724. ASSERT(args.length() == 1);
  5725. CONVERT_DOUBLE_ARG_CHECKED(number, 0);
  5726. // We do not include 0 so that we don't have to treat +0 / -0 cases.
  5727. if (number > 0 && number <= Smi::kMaxValue) {
  5728. return Smi::FromInt(static_cast<int>(number));
  5729. }
  5730. double double_value = DoubleToInteger(number);
  5731. // Map both -0 and +0 to +0.
  5732. if (double_value == 0) double_value = 0;
  5733. return isolate->heap()->NumberFromDouble(double_value);
  5734. }
  5735. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSUint32) {
  5736. SealHandleScope shs(isolate);
  5737. ASSERT(args.length() == 1);
  5738. CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]);
  5739. return isolate->heap()->NumberFromUint32(number);
  5740. }
  5741. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSInt32) {
  5742. SealHandleScope shs(isolate);
  5743. ASSERT(args.length() == 1);
  5744. CONVERT_DOUBLE_ARG_CHECKED(number, 0);
  5745. // We do not include 0 so that we don't have to treat +0 / -0 cases.
  5746. if (number > 0 && number <= Smi::kMaxValue) {
  5747. return Smi::FromInt(static_cast<int>(number));
  5748. }
  5749. return isolate->heap()->NumberFromInt32(DoubleToInt32(number));
  5750. }
  5751. // Converts a Number to a Smi, if possible. Returns NaN if the number is not
  5752. // a small integer.
  5753. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToSmi) {
  5754. SealHandleScope shs(isolate);
  5755. ASSERT(args.length() == 1);
  5756. Object* obj = args[0];
  5757. if (obj->IsSmi()) {
  5758. return obj;
  5759. }
  5760. if (obj->IsHeapNumber()) {
  5761. double value = HeapNumber::cast(obj)->value();
  5762. int int_value = FastD2I(value);
  5763. if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
  5764. return Smi::FromInt(int_value);
  5765. }
  5766. }
  5767. return isolate->heap()->nan_value();
  5768. }
  5769. RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateHeapNumber) {
  5770. SealHandleScope shs(isolate);
  5771. ASSERT(args.length() == 0);
  5772. return isolate->heap()->AllocateHeapNumber(0);
  5773. }
  5774. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAdd) {
  5775. SealHandleScope shs(isolate);
  5776. ASSERT(args.length() == 2);
  5777. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  5778. CONVERT_DOUBLE_ARG_CHECKED(y, 1);
  5779. return isolate->heap()->NumberFromDouble(x + y);
  5780. }
  5781. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSub) {
  5782. SealHandleScope shs(isolate);
  5783. ASSERT(args.length() == 2);
  5784. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  5785. CONVERT_DOUBLE_ARG_CHECKED(y, 1);
  5786. return isolate->heap()->NumberFromDouble(x - y);
  5787. }
  5788. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMul) {
  5789. SealHandleScope shs(isolate);
  5790. ASSERT(args.length() == 2);
  5791. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  5792. CONVERT_DOUBLE_ARG_CHECKED(y, 1);
  5793. return isolate->heap()->NumberFromDouble(x * y);
  5794. }
  5795. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberUnaryMinus) {
  5796. SealHandleScope shs(isolate);
  5797. ASSERT(args.length() == 1);
  5798. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  5799. return isolate->heap()->NumberFromDouble(-x);
  5800. }
  5801. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAlloc) {
  5802. SealHandleScope shs(isolate);
  5803. ASSERT(args.length() == 0);
  5804. return isolate->heap()->NumberFromDouble(9876543210.0);
  5805. }
  5806. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberDiv) {
  5807. SealHandleScope shs(isolate);
  5808. ASSERT(args.length() == 2);
  5809. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  5810. CONVERT_DOUBLE_ARG_CHECKED(y, 1);
  5811. return isolate->heap()->NumberFromDouble(x / y);
  5812. }
  5813. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMod) {
  5814. SealHandleScope shs(isolate);
  5815. ASSERT(args.length() == 2);
  5816. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  5817. CONVERT_DOUBLE_ARG_CHECKED(y, 1);
  5818. x = modulo(x, y);
  5819. // NumberFromDouble may return a Smi instead of a Number object
  5820. return isolate->heap()->NumberFromDouble(x);
  5821. }
  5822. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberImul) {
  5823. SealHandleScope shs(isolate);
  5824. ASSERT(args.length() == 2);
  5825. CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
  5826. CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
  5827. return isolate->heap()->NumberFromInt32(x * y);
  5828. }
  5829. RUNTIME_FUNCTION(MaybeObject*, Runtime_StringAdd) {
  5830. SealHandleScope shs(isolate);
  5831. ASSERT(args.length() == 2);
  5832. CONVERT_ARG_CHECKED(String, str1, 0);
  5833. CONVERT_ARG_CHECKED(String, str2, 1);
  5834. isolate->counters()->string_add_runtime()->Increment();
  5835. return isolate->heap()->AllocateConsString(str1, str2);
  5836. }
  5837. template <typename sinkchar>
  5838. static inline void StringBuilderConcatHelper(String* special,
  5839. sinkchar* sink,
  5840. FixedArray* fixed_array,
  5841. int array_length) {
  5842. int position = 0;
  5843. for (int i = 0; i < array_length; i++) {
  5844. Object* element = fixed_array->get(i);
  5845. if (element->IsSmi()) {
  5846. // Smi encoding of position and length.
  5847. int encoded_slice = Smi::cast(element)->value();
  5848. int pos;
  5849. int len;
  5850. if (encoded_slice > 0) {
  5851. // Position and length encoded in one smi.
  5852. pos = StringBuilderSubstringPosition::decode(encoded_slice);
  5853. len = StringBuilderSubstringLength::decode(encoded_slice);
  5854. } else {
  5855. // Position and length encoded in two smis.
  5856. Object* obj = fixed_array->get(++i);
  5857. ASSERT(obj->IsSmi());
  5858. pos = Smi::cast(obj)->value();
  5859. len = -encoded_slice;
  5860. }
  5861. String::WriteToFlat(special,
  5862. sink + position,
  5863. pos,
  5864. pos + len);
  5865. position += len;
  5866. } else {
  5867. String* string = String::cast(element);
  5868. int element_length = string->length();
  5869. String::WriteToFlat(string, sink + position, 0, element_length);
  5870. position += element_length;
  5871. }
  5872. }
  5873. }
  5874. RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
  5875. SealHandleScope shs(isolate);
  5876. ASSERT(args.length() == 3);
  5877. CONVERT_ARG_CHECKED(JSArray, array, 0);
  5878. if (!args[1]->IsSmi()) {
  5879. isolate->context()->mark_out_of_memory();
  5880. return Failure::OutOfMemoryException(0x14);
  5881. }
  5882. int array_length = args.smi_at(1);
  5883. CONVERT_ARG_CHECKED(String, special, 2);
  5884. // This assumption is used by the slice encoding in one or two smis.
  5885. ASSERT(Smi::kMaxValue >= String::kMaxLength);
  5886. MaybeObject* maybe_result = array->EnsureCanContainHeapObjectElements();
  5887. if (maybe_result->IsFailure()) return maybe_result;
  5888. int special_length = special->length();
  5889. if (!array->HasFastObjectElements()) {
  5890. return isolate->Throw(isolate->heap()->illegal_argument_string());
  5891. }
  5892. FixedArray* fixed_array = FixedArray::cast(array->elements());
  5893. if (fixed_array->length() < array_length) {
  5894. array_length = fixed_array->length();
  5895. }
  5896. if (array_length == 0) {
  5897. return isolate->heap()->empty_string();
  5898. } else if (array_length == 1) {
  5899. Object* first = fixed_array->get(0);
  5900. if (first->IsString()) return first;
  5901. }
  5902. bool one_byte = special->HasOnlyOneByteChars();
  5903. int position = 0;
  5904. for (int i = 0; i < array_length; i++) {
  5905. int increment = 0;
  5906. Object* elt = fixed_array->get(i);
  5907. if (elt->IsSmi()) {
  5908. // Smi encoding of position and length.
  5909. int smi_value = Smi::cast(elt)->value();
  5910. int pos;
  5911. int len;
  5912. if (smi_value > 0) {
  5913. // Position and length encoded in one smi.
  5914. pos = StringBuilderSubstringPosition::decode(smi_value);
  5915. len = StringBuilderSubstringLength::decode(smi_value);
  5916. } else {
  5917. // Position and length encoded in two smis.
  5918. len = -smi_value;
  5919. // Get the position and check that it is a positive smi.
  5920. i++;
  5921. if (i >= array_length) {
  5922. return isolate->Throw(isolate->heap()->illegal_argument_string());
  5923. }
  5924. Object* next_smi = fixed_array->get(i);
  5925. if (!next_smi->IsSmi()) {
  5926. return isolate->Throw(isolate->heap()->illegal_argument_string());
  5927. }
  5928. pos = Smi::cast(next_smi)->value();
  5929. if (pos < 0) {
  5930. return isolate->Throw(isolate->heap()->illegal_argument_string());
  5931. }
  5932. }
  5933. ASSERT(pos >= 0);
  5934. ASSERT(len >= 0);
  5935. if (pos > special_length || len > special_length - pos) {
  5936. return isolate->Throw(isolate->heap()->illegal_argument_string());
  5937. }
  5938. increment = len;
  5939. } else if (elt->IsString()) {
  5940. String* element = String::cast(elt);
  5941. int element_length = element->length();
  5942. increment = element_length;
  5943. if (one_byte && !element->HasOnlyOneByteChars()) {
  5944. one_byte = false;
  5945. }
  5946. } else {
  5947. ASSERT(!elt->IsTheHole());
  5948. return isolate->Throw(isolate->heap()->illegal_argument_string());
  5949. }
  5950. if (increment > String::kMaxLength - position) {
  5951. isolate->context()->mark_out_of_memory();
  5952. return Failure::OutOfMemoryException(0x15);
  5953. }
  5954. position += increment;
  5955. }
  5956. int length = position;
  5957. Object* object;
  5958. if (one_byte) {
  5959. { MaybeObject* maybe_object =
  5960. isolate->heap()->AllocateRawOneByteString(length);
  5961. if (!maybe_object->ToObject(&object)) return maybe_object;
  5962. }
  5963. SeqOneByteString* answer = SeqOneByteString::cast(object);
  5964. StringBuilderConcatHelper(special,
  5965. answer->GetChars(),
  5966. fixed_array,
  5967. array_length);
  5968. return answer;
  5969. } else {
  5970. { MaybeObject* maybe_object =
  5971. isolate->heap()->AllocateRawTwoByteString(length);
  5972. if (!maybe_object->ToObject(&object)) return maybe_object;
  5973. }
  5974. SeqTwoByteString* answer = SeqTwoByteString::cast(object);
  5975. StringBuilderConcatHelper(special,
  5976. answer->GetChars(),
  5977. fixed_array,
  5978. array_length);
  5979. return answer;
  5980. }
  5981. }
  5982. RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
  5983. SealHandleScope shs(isolate);
  5984. ASSERT(args.length() == 3);
  5985. CONVERT_ARG_CHECKED(JSArray, array, 0);
  5986. if (!args[1]->IsSmi()) {
  5987. isolate->context()->mark_out_of_memory();
  5988. return Failure::OutOfMemoryException(0x16);
  5989. }
  5990. int array_length = args.smi_at(1);
  5991. CONVERT_ARG_CHECKED(String, separator, 2);
  5992. if (!array->HasFastObjectElements()) {
  5993. return isolate->Throw(isolate->heap()->illegal_argument_string());
  5994. }
  5995. FixedArray* fixed_array = FixedArray::cast(array->elements());
  5996. if (fixed_array->length() < array_length) {
  5997. array_length = fixed_array->length();
  5998. }
  5999. if (array_length == 0) {
  6000. return isolate->heap()->empty_string();
  6001. } else if (array_length == 1) {
  6002. Object* first = fixed_array->get(0);
  6003. if (first->IsString()) return first;
  6004. }
  6005. int separator_length = separator->length();
  6006. int max_nof_separators =
  6007. (String::kMaxLength + separator_length - 1) / separator_length;
  6008. if (max_nof_separators < (array_length - 1)) {
  6009. isolate->context()->mark_out_of_memory();
  6010. return Failure::OutOfMemoryException(0x17);
  6011. }
  6012. int length = (array_length - 1) * separator_length;
  6013. for (int i = 0; i < array_length; i++) {
  6014. Object* element_obj = fixed_array->get(i);
  6015. if (!element_obj->IsString()) {
  6016. // TODO(1161): handle this case.
  6017. return isolate->Throw(isolate->heap()->illegal_argument_string());
  6018. }
  6019. String* element = String::cast(element_obj);
  6020. int increment = element->length();
  6021. if (increment > String::kMaxLength - length) {
  6022. isolate->context()->mark_out_of_memory();
  6023. return Failure::OutOfMemoryException(0x18);
  6024. }
  6025. length += increment;
  6026. }
  6027. Object* object;
  6028. { MaybeObject* maybe_object =
  6029. isolate->heap()->AllocateRawTwoByteString(length);
  6030. if (!maybe_object->ToObject(&object)) return maybe_object;
  6031. }
  6032. SeqTwoByteString* answer = SeqTwoByteString::cast(object);
  6033. uc16* sink = answer->GetChars();
  6034. #ifdef DEBUG
  6035. uc16* end = sink + length;
  6036. #endif
  6037. String* first = String::cast(fixed_array->get(0));
  6038. int first_length = first->length();
  6039. String::WriteToFlat(first, sink, 0, first_length);
  6040. sink += first_length;
  6041. for (int i = 1; i < array_length; i++) {
  6042. ASSERT(sink + separator_length <= end);
  6043. String::WriteToFlat(separator, sink, 0, separator_length);
  6044. sink += separator_length;
  6045. String* element = String::cast(fixed_array->get(i));
  6046. int element_length = element->length();
  6047. ASSERT(sink + element_length <= end);
  6048. String::WriteToFlat(element, sink, 0, element_length);
  6049. sink += element_length;
  6050. }
  6051. ASSERT(sink == end);
  6052. // Use %_FastAsciiArrayJoin instead.
  6053. ASSERT(!answer->IsOneByteRepresentation());
  6054. return answer;
  6055. }
  6056. template <typename Char>
  6057. static void JoinSparseArrayWithSeparator(FixedArray* elements,
  6058. int elements_length,
  6059. uint32_t array_length,
  6060. String* separator,
  6061. Vector<Char> buffer) {
  6062. int previous_separator_position = 0;
  6063. int separator_length = separator->length();
  6064. int cursor = 0;
  6065. for (int i = 0; i < elements_length; i += 2) {
  6066. int position = NumberToInt32(elements->get(i));
  6067. String* string = String::cast(elements->get(i + 1));
  6068. int string_length = string->length();
  6069. if (string->length() > 0) {
  6070. while (previous_separator_position < position) {
  6071. String::WriteToFlat<Char>(separator, &buffer[cursor],
  6072. 0, separator_length);
  6073. cursor += separator_length;
  6074. previous_separator_position++;
  6075. }
  6076. String::WriteToFlat<Char>(string, &buffer[cursor],
  6077. 0, string_length);
  6078. cursor += string->length();
  6079. }
  6080. }
  6081. if (separator_length > 0) {
  6082. // Array length must be representable as a signed 32-bit number,
  6083. // otherwise the total string length would have been too large.
  6084. ASSERT(array_length <= 0x7fffffff); // Is int32_t.
  6085. int last_array_index = static_cast<int>(array_length - 1);
  6086. while (previous_separator_position < last_array_index) {
  6087. String::WriteToFlat<Char>(separator, &buffer[cursor],
  6088. 0, separator_length);
  6089. cursor += separator_length;
  6090. previous_separator_position++;
  6091. }
  6092. }
  6093. ASSERT(cursor <= buffer.length());
  6094. }
  6095. RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) {
  6096. SealHandleScope shs(isolate);
  6097. ASSERT(args.length() == 3);
  6098. CONVERT_ARG_CHECKED(JSArray, elements_array, 0);
  6099. RUNTIME_ASSERT(elements_array->HasFastSmiOrObjectElements());
  6100. CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]);
  6101. CONVERT_ARG_CHECKED(String, separator, 2);
  6102. // elements_array is fast-mode JSarray of alternating positions
  6103. // (increasing order) and strings.
  6104. // array_length is length of original array (used to add separators);
  6105. // separator is string to put between elements. Assumed to be non-empty.
  6106. // Find total length of join result.
  6107. int string_length = 0;
  6108. bool is_ascii = separator->IsOneByteRepresentation();
  6109. int max_string_length;
  6110. if (is_ascii) {
  6111. max_string_length = SeqOneByteString::kMaxLength;
  6112. } else {
  6113. max_string_length = SeqTwoByteString::kMaxLength;
  6114. }
  6115. bool overflow = false;
  6116. CONVERT_NUMBER_CHECKED(int, elements_length,
  6117. Int32, elements_array->length());
  6118. RUNTIME_ASSERT((elements_length & 1) == 0); // Even length.
  6119. FixedArray* elements = FixedArray::cast(elements_array->elements());
  6120. for (int i = 0; i < elements_length; i += 2) {
  6121. RUNTIME_ASSERT(elements->get(i)->IsNumber());
  6122. RUNTIME_ASSERT(elements->get(i + 1)->IsString());
  6123. String* string = String::cast(elements->get(i + 1));
  6124. int length = string->length();
  6125. if (is_ascii && !string->IsOneByteRepresentation()) {
  6126. is_ascii = false;
  6127. max_string_length = SeqTwoByteString::kMaxLength;
  6128. }
  6129. if (length > max_string_length ||
  6130. max_string_length - length < string_length) {
  6131. overflow = true;
  6132. break;
  6133. }
  6134. string_length += length;
  6135. }
  6136. int separator_length = separator->length();
  6137. if (!overflow && separator_length > 0) {
  6138. if (array_length <= 0x7fffffffu) {
  6139. int separator_count = static_cast<int>(array_length) - 1;
  6140. int remaining_length = max_string_length - string_length;
  6141. if ((remaining_length / separator_length) >= separator_count) {
  6142. string_length += separator_length * (array_length - 1);
  6143. } else {
  6144. // Not room for the separators within the maximal string length.
  6145. overflow = true;
  6146. }
  6147. } else {
  6148. // Nonempty separator and at least 2^31-1 separators necessary
  6149. // means that the string is too large to create.
  6150. STATIC_ASSERT(String::kMaxLength < 0x7fffffff);
  6151. overflow = true;
  6152. }
  6153. }
  6154. if (overflow) {
  6155. // Throw OutOfMemory exception for creating too large a string.
  6156. V8::FatalProcessOutOfMemory("Array join result too large.");
  6157. }
  6158. if (is_ascii) {
  6159. MaybeObject* result_allocation =
  6160. isolate->heap()->AllocateRawOneByteString(string_length);
  6161. if (result_allocation->IsFailure()) return result_allocation;
  6162. SeqOneByteString* result_string =
  6163. SeqOneByteString::cast(result_allocation->ToObjectUnchecked());
  6164. JoinSparseArrayWithSeparator<uint8_t>(elements,
  6165. elements_length,
  6166. array_length,
  6167. separator,
  6168. Vector<uint8_t>(
  6169. result_string->GetChars(),
  6170. string_length));
  6171. return result_string;
  6172. } else {
  6173. MaybeObject* result_allocation =
  6174. isolate->heap()->AllocateRawTwoByteString(string_length);
  6175. if (result_allocation->IsFailure()) return result_allocation;
  6176. SeqTwoByteString* result_string =
  6177. SeqTwoByteString::cast(result_allocation->ToObjectUnchecked());
  6178. JoinSparseArrayWithSeparator<uc16>(elements,
  6179. elements_length,
  6180. array_length,
  6181. separator,
  6182. Vector<uc16>(result_string->GetChars(),
  6183. string_length));
  6184. return result_string;
  6185. }
  6186. }
  6187. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberOr) {
  6188. SealHandleScope shs(isolate);
  6189. ASSERT(args.length() == 2);
  6190. CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
  6191. CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
  6192. return isolate->heap()->NumberFromInt32(x | y);
  6193. }
  6194. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAnd) {
  6195. SealHandleScope shs(isolate);
  6196. ASSERT(args.length() == 2);
  6197. CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
  6198. CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
  6199. return isolate->heap()->NumberFromInt32(x & y);
  6200. }
  6201. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberXor) {
  6202. SealHandleScope shs(isolate);
  6203. ASSERT(args.length() == 2);
  6204. CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
  6205. CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
  6206. return isolate->heap()->NumberFromInt32(x ^ y);
  6207. }
  6208. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShl) {
  6209. SealHandleScope shs(isolate);
  6210. ASSERT(args.length() == 2);
  6211. CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
  6212. CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
  6213. return isolate->heap()->NumberFromInt32(x << (y & 0x1f));
  6214. }
  6215. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShr) {
  6216. SealHandleScope shs(isolate);
  6217. ASSERT(args.length() == 2);
  6218. CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
  6219. CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
  6220. return isolate->heap()->NumberFromUint32(x >> (y & 0x1f));
  6221. }
  6222. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSar) {
  6223. SealHandleScope shs(isolate);
  6224. ASSERT(args.length() == 2);
  6225. CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
  6226. CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
  6227. return isolate->heap()->NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f));
  6228. }
  6229. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberEquals) {
  6230. SealHandleScope shs(isolate);
  6231. ASSERT(args.length() == 2);
  6232. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  6233. CONVERT_DOUBLE_ARG_CHECKED(y, 1);
  6234. if (std::isnan(x)) return Smi::FromInt(NOT_EQUAL);
  6235. if (std::isnan(y)) return Smi::FromInt(NOT_EQUAL);
  6236. if (x == y) return Smi::FromInt(EQUAL);
  6237. Object* result;
  6238. if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
  6239. result = Smi::FromInt(EQUAL);
  6240. } else {
  6241. result = Smi::FromInt(NOT_EQUAL);
  6242. }
  6243. return result;
  6244. }
  6245. RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) {
  6246. SealHandleScope shs(isolate);
  6247. ASSERT(args.length() == 2);
  6248. CONVERT_ARG_CHECKED(String, x, 0);
  6249. CONVERT_ARG_CHECKED(String, y, 1);
  6250. bool not_equal = !x->Equals(y);
  6251. // This is slightly convoluted because the value that signifies
  6252. // equality is 0 and inequality is 1 so we have to negate the result
  6253. // from String::Equals.
  6254. ASSERT(not_equal == 0 || not_equal == 1);
  6255. STATIC_CHECK(EQUAL == 0);
  6256. STATIC_CHECK(NOT_EQUAL == 1);
  6257. return Smi::FromInt(not_equal);
  6258. }
  6259. RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberCompare) {
  6260. SealHandleScope shs(isolate);
  6261. ASSERT(args.length() == 3);
  6262. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  6263. CONVERT_DOUBLE_ARG_CHECKED(y, 1);
  6264. if (std::isnan(x) || std::isnan(y)) return args[2];
  6265. if (x == y) return Smi::FromInt(EQUAL);
  6266. if (isless(x, y)) return Smi::FromInt(LESS);
  6267. return Smi::FromInt(GREATER);
  6268. }
  6269. // Compare two Smis as if they were converted to strings and then
  6270. // compared lexicographically.
  6271. RUNTIME_FUNCTION(MaybeObject*, Runtime_SmiLexicographicCompare) {
  6272. SealHandleScope shs(isolate);
  6273. ASSERT(args.length() == 2);
  6274. CONVERT_SMI_ARG_CHECKED(x_value, 0);
  6275. CONVERT_SMI_ARG_CHECKED(y_value, 1);
  6276. // If the integers are equal so are the string representations.
  6277. if (x_value == y_value) return Smi::FromInt(EQUAL);
  6278. // If one of the integers is zero the normal integer order is the
  6279. // same as the lexicographic order of the string representations.
  6280. if (x_value == 0 || y_value == 0)
  6281. return Smi::FromInt(x_value < y_value ? LESS : GREATER);
  6282. // If only one of the integers is negative the negative number is
  6283. // smallest because the char code of '-' is less than the char code
  6284. // of any digit. Otherwise, we make both values positive.
  6285. // Use unsigned values otherwise the logic is incorrect for -MIN_INT on
  6286. // architectures using 32-bit Smis.
  6287. uint32_t x_scaled = x_value;
  6288. uint32_t y_scaled = y_value;
  6289. if (x_value < 0 || y_value < 0) {
  6290. if (y_value >= 0) return Smi::FromInt(LESS);
  6291. if (x_value >= 0) return Smi::FromInt(GREATER);
  6292. x_scaled = -x_value;
  6293. y_scaled = -y_value;
  6294. }
  6295. static const uint32_t kPowersOf10[] = {
  6296. 1, 10, 100, 1000, 10*1000, 100*1000,
  6297. 1000*1000, 10*1000*1000, 100*1000*1000,
  6298. 1000*1000*1000
  6299. };
  6300. // If the integers have the same number of decimal digits they can be
  6301. // compared directly as the numeric order is the same as the
  6302. // lexicographic order. If one integer has fewer digits, it is scaled
  6303. // by some power of 10 to have the same number of digits as the longer
  6304. // integer. If the scaled integers are equal it means the shorter
  6305. // integer comes first in the lexicographic order.
  6306. // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
  6307. int x_log2 = IntegerLog2(x_scaled);
  6308. int x_log10 = ((x_log2 + 1) * 1233) >> 12;
  6309. x_log10 -= x_scaled < kPowersOf10[x_log10];
  6310. int y_log2 = IntegerLog2(y_scaled);
  6311. int y_log10 = ((y_log2 + 1) * 1233) >> 12;
  6312. y_log10 -= y_scaled < kPowersOf10[y_log10];
  6313. int tie = EQUAL;
  6314. if (x_log10 < y_log10) {
  6315. // X has fewer digits. We would like to simply scale up X but that
  6316. // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would
  6317. // be scaled up to 9_000_000_000. So we scale up by the next
  6318. // smallest power and scale down Y to drop one digit. It is OK to
  6319. // drop one digit from the longer integer since the final digit is
  6320. // past the length of the shorter integer.
  6321. x_scaled *= kPowersOf10[y_log10 - x_log10 - 1];
  6322. y_scaled /= 10;
  6323. tie = LESS;
  6324. } else if (y_log10 < x_log10) {
  6325. y_scaled *= kPowersOf10[x_log10 - y_log10 - 1];
  6326. x_scaled /= 10;
  6327. tie = GREATER;
  6328. }
  6329. if (x_scaled < y_scaled) return Smi::FromInt(LESS);
  6330. if (x_scaled > y_scaled) return Smi::FromInt(GREATER);
  6331. return Smi::FromInt(tie);
  6332. }
  6333. static Object* StringCharacterStreamCompare(RuntimeState* state,
  6334. String* x,
  6335. String* y) {
  6336. StringCharacterStream stream_x(x, state->string_iterator_compare_x());
  6337. StringCharacterStream stream_y(y, state->string_iterator_compare_y());
  6338. while (stream_x.HasMore() && stream_y.HasMore()) {
  6339. int d = stream_x.GetNext() - stream_y.GetNext();
  6340. if (d < 0) return Smi::FromInt(LESS);
  6341. else if (d > 0) return Smi::FromInt(GREATER);
  6342. }
  6343. // x is (non-trivial) prefix of y:
  6344. if (stream_y.HasMore()) return Smi::FromInt(LESS);
  6345. // y is prefix of x:
  6346. return Smi::FromInt(stream_x.HasMore() ? GREATER : EQUAL);
  6347. }
  6348. static Object* FlatStringCompare(String* x, String* y) {
  6349. ASSERT(x->IsFlat());
  6350. ASSERT(y->IsFlat());
  6351. Object* equal_prefix_result = Smi::FromInt(EQUAL);
  6352. int prefix_length = x->length();
  6353. if (y->length() < prefix_length) {
  6354. prefix_length = y->length();
  6355. equal_prefix_result = Smi::FromInt(GREATER);
  6356. } else if (y->length() > prefix_length) {
  6357. equal_prefix_result = Smi::FromInt(LESS);
  6358. }
  6359. int r;
  6360. DisallowHeapAllocation no_gc;
  6361. String::FlatContent x_content = x->GetFlatContent();
  6362. String::FlatContent y_content = y->GetFlatContent();
  6363. if (x_content.IsAscii()) {
  6364. Vector<const uint8_t> x_chars = x_content.ToOneByteVector();
  6365. if (y_content.IsAscii()) {
  6366. Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
  6367. r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
  6368. } else {
  6369. Vector<const uc16> y_chars = y_content.ToUC16Vector();
  6370. r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
  6371. }
  6372. } else {
  6373. Vector<const uc16> x_chars = x_content.ToUC16Vector();
  6374. if (y_content.IsAscii()) {
  6375. Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
  6376. r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
  6377. } else {
  6378. Vector<const uc16> y_chars = y_content.ToUC16Vector();
  6379. r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
  6380. }
  6381. }
  6382. Object* result;
  6383. if (r == 0) {
  6384. result = equal_prefix_result;
  6385. } else {
  6386. result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
  6387. }
  6388. ASSERT(result ==
  6389. StringCharacterStreamCompare(Isolate::Current()->runtime_state(), x, y));
  6390. return result;
  6391. }
  6392. RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCompare) {
  6393. SealHandleScope shs(isolate);
  6394. ASSERT(args.length() == 2);
  6395. CONVERT_ARG_CHECKED(String, x, 0);
  6396. CONVERT_ARG_CHECKED(String, y, 1);
  6397. isolate->counters()->string_compare_runtime()->Increment();
  6398. // A few fast case tests before we flatten.
  6399. if (x == y) return Smi::FromInt(EQUAL);
  6400. if (y->length() == 0) {
  6401. if (x->length() == 0) return Smi::FromInt(EQUAL);
  6402. return Smi::FromInt(GREATER);
  6403. } else if (x->length() == 0) {
  6404. return Smi::FromInt(LESS);
  6405. }
  6406. int d = x->Get(0) - y->Get(0);
  6407. if (d < 0) return Smi::FromInt(LESS);
  6408. else if (d > 0) return Smi::FromInt(GREATER);
  6409. Object* obj;
  6410. { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(x);
  6411. if (!maybe_obj->ToObject(&obj)) return maybe_obj;
  6412. }
  6413. { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(y);
  6414. if (!maybe_obj->ToObject(&obj)) return maybe_obj;
  6415. }
  6416. return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
  6417. : StringCharacterStreamCompare(isolate->runtime_state(), x, y);
  6418. }
  6419. RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_acos) {
  6420. SealHandleScope shs(isolate);
  6421. ASSERT(args.length() == 1);
  6422. isolate->counters()->math_acos()->Increment();
  6423. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  6424. return isolate->transcendental_cache()->Get(TranscendentalCache::ACOS, x);
  6425. }
  6426. RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_asin) {
  6427. SealHandleScope shs(isolate);
  6428. ASSERT(args.length() == 1);
  6429. isolate->counters()->math_asin()->Increment();
  6430. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  6431. return isolate->transcendental_cache()->Get(TranscendentalCache::ASIN, x);
  6432. }
  6433. RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan) {
  6434. SealHandleScope shs(isolate);
  6435. ASSERT(args.length() == 1);
  6436. isolate->counters()->math_atan()->Increment();
  6437. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  6438. return isolate->transcendental_cache()->Get(TranscendentalCache::ATAN, x);
  6439. }
  6440. static const double kPiDividedBy4 = 0.78539816339744830962;
  6441. RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan2) {
  6442. SealHandleScope shs(isolate);
  6443. ASSERT(args.length() == 2);
  6444. isolate->counters()->math_atan2()->Increment();
  6445. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  6446. CONVERT_DOUBLE_ARG_CHECKED(y, 1);
  6447. double result;
  6448. if (std::isinf(x) && std::isinf(y)) {
  6449. // Make sure that the result in case of two infinite arguments
  6450. // is a multiple of Pi / 4. The sign of the result is determined
  6451. // by the first argument (x) and the sign of the second argument
  6452. // determines the multiplier: one or three.
  6453. int multiplier = (x < 0) ? -1 : 1;
  6454. if (y < 0) multiplier *= 3;
  6455. result = multiplier * kPiDividedBy4;
  6456. } else {
  6457. result = atan2(x, y);
  6458. }
  6459. return isolate->heap()->AllocateHeapNumber(result);
  6460. }
  6461. RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_ceil) {
  6462. SealHandleScope shs(isolate);
  6463. ASSERT(args.length() == 1);
  6464. isolate->counters()->math_ceil()->Increment();
  6465. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  6466. return isolate->heap()->NumberFromDouble(ceiling(x));
  6467. }
  6468. RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_cos) {
  6469. SealHandleScope shs(isolate);
  6470. ASSERT(args.length() == 1);
  6471. isolate->counters()->math_cos()->Increment();
  6472. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  6473. return isolate->transcendental_cache()->Get(TranscendentalCache::COS, x);
  6474. }
  6475. RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_exp) {
  6476. SealHandleScope shs(isolate);
  6477. ASSERT(args.length() == 1);
  6478. isolate->counters()->math_exp()->Increment();
  6479. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  6480. lazily_initialize_fast_exp();
  6481. return isolate->heap()->NumberFromDouble(fast_exp(x));
  6482. }
  6483. RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_floor) {
  6484. SealHandleScope shs(isolate);
  6485. ASSERT(args.length() == 1);
  6486. isolate->counters()->math_floor()->Increment();
  6487. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  6488. return isolate->heap()->NumberFromDouble(floor(x));
  6489. }
  6490. RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_log) {
  6491. SealHandleScope shs(isolate);
  6492. ASSERT(args.length() == 1);
  6493. isolate->counters()->math_log()->Increment();
  6494. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  6495. return isolate->transcendental_cache()->Get(TranscendentalCache::LOG, x);
  6496. }
  6497. // Slow version of Math.pow. We check for fast paths for special cases.
  6498. // Used if SSE2/VFP3 is not available.
  6499. RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow) {
  6500. SealHandleScope shs(isolate);
  6501. ASSERT(args.length() == 2);
  6502. isolate->counters()->math_pow()->Increment();
  6503. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  6504. // If the second argument is a smi, it is much faster to call the
  6505. // custom powi() function than the generic pow().
  6506. if (args[1]->IsSmi()) {
  6507. int y = args.smi_at(1);
  6508. return isolate->heap()->NumberFromDouble(power_double_int(x, y));
  6509. }
  6510. CONVERT_DOUBLE_ARG_CHECKED(y, 1);
  6511. double result = power_helper(x, y);
  6512. if (std::isnan(result)) return isolate->heap()->nan_value();
  6513. return isolate->heap()->AllocateHeapNumber(result);
  6514. }
  6515. // Fast version of Math.pow if we know that y is not an integer and y is not
  6516. // -0.5 or 0.5. Used as slow case from full codegen.
  6517. RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow_cfunction) {
  6518. SealHandleScope shs(isolate);
  6519. ASSERT(args.length() == 2);
  6520. isolate->counters()->math_pow()->Increment();
  6521. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  6522. CONVERT_DOUBLE_ARG_CHECKED(y, 1);
  6523. if (y == 0) {
  6524. return Smi::FromInt(1);
  6525. } else {
  6526. double result = power_double_double(x, y);
  6527. if (std::isnan(result)) return isolate->heap()->nan_value();
  6528. return isolate->heap()->AllocateHeapNumber(result);
  6529. }
  6530. }
  6531. RUNTIME_FUNCTION(MaybeObject*, Runtime_RoundNumber) {
  6532. SealHandleScope shs(isolate);
  6533. ASSERT(args.length() == 1);
  6534. isolate->counters()->math_round()->Increment();
  6535. if (!args[0]->IsHeapNumber()) {
  6536. // Must be smi. Return the argument unchanged for all the other types
  6537. // to make fuzz-natives test happy.
  6538. return args[0];
  6539. }
  6540. HeapNumber* number = reinterpret_cast<HeapNumber*>(args[0]);
  6541. double value = number->value();
  6542. int exponent = number->get_exponent();
  6543. int sign = number->get_sign();
  6544. if (exponent < -1) {
  6545. // Number in range ]-0.5..0.5[. These always round to +/-zero.
  6546. if (sign) return isolate->heap()->minus_zero_value();
  6547. return Smi::FromInt(0);
  6548. }
  6549. // We compare with kSmiValueSize - 2 because (2^30 - 0.1) has exponent 29 and
  6550. // should be rounded to 2^30, which is not smi (for 31-bit smis, similar
  6551. // argument holds for 32-bit smis).
  6552. if (!sign && exponent < kSmiValueSize - 2) {
  6553. return Smi::FromInt(static_cast<int>(value + 0.5));
  6554. }
  6555. // If the magnitude is big enough, there's no place for fraction part. If we
  6556. // try to add 0.5 to this number, 1.0 will be added instead.
  6557. if (exponent >= 52) {
  6558. return number;
  6559. }
  6560. if (sign && value >= -0.5) return isolate->heap()->minus_zero_value();
  6561. // Do not call NumberFromDouble() to avoid extra checks.
  6562. return isolate->heap()->AllocateHeapNumber(floor(value + 0.5));
  6563. }
  6564. RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sin) {
  6565. SealHandleScope shs(isolate);
  6566. ASSERT(args.length() == 1);
  6567. isolate->counters()->math_sin()->Increment();
  6568. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  6569. return isolate->transcendental_cache()->Get(TranscendentalCache::SIN, x);
  6570. }
  6571. RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sqrt) {
  6572. SealHandleScope shs(isolate);
  6573. ASSERT(args.length() == 1);
  6574. isolate->counters()->math_sqrt()->Increment();
  6575. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  6576. return isolate->heap()->AllocateHeapNumber(fast_sqrt(x));
  6577. }
  6578. RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_tan) {
  6579. SealHandleScope shs(isolate);
  6580. ASSERT(args.length() == 1);
  6581. isolate->counters()->math_tan()->Increment();
  6582. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  6583. return isolate->transcendental_cache()->Get(TranscendentalCache::TAN, x);
  6584. }
  6585. RUNTIME_FUNCTION(MaybeObject*, Runtime_DateMakeDay) {
  6586. SealHandleScope shs(isolate);
  6587. ASSERT(args.length() == 2);
  6588. CONVERT_SMI_ARG_CHECKED(year, 0);
  6589. CONVERT_SMI_ARG_CHECKED(month, 1);
  6590. return Smi::FromInt(isolate->date_cache()->DaysFromYearMonth(year, month));
  6591. }
  6592. RUNTIME_FUNCTION(MaybeObject*, Runtime_DateSetValue) {
  6593. HandleScope scope(isolate);
  6594. ASSERT(args.length() == 3);
  6595. CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 0);
  6596. CONVERT_DOUBLE_ARG_CHECKED(time, 1);
  6597. CONVERT_SMI_ARG_CHECKED(is_utc, 2);
  6598. DateCache* date_cache = isolate->date_cache();
  6599. Object* value = NULL;
  6600. bool is_value_nan = false;
  6601. if (std::isnan(time)) {
  6602. value = isolate->heap()->nan_value();
  6603. is_value_nan = true;
  6604. } else if (!is_utc &&
  6605. (time < -DateCache::kMaxTimeBeforeUTCInMs ||
  6606. time > DateCache::kMaxTimeBeforeUTCInMs)) {
  6607. value = isolate->heap()->nan_value();
  6608. is_value_nan = true;
  6609. } else {
  6610. time = is_utc ? time : date_cache->ToUTC(static_cast<int64_t>(time));
  6611. if (time < -DateCache::kMaxTimeInMs ||
  6612. time > DateCache::kMaxTimeInMs) {
  6613. value = isolate->heap()->nan_value();
  6614. is_value_nan = true;
  6615. } else {
  6616. MaybeObject* maybe_result =
  6617. isolate->heap()->AllocateHeapNumber(DoubleToInteger(time));
  6618. if (!maybe_result->ToObject(&value)) return maybe_result;
  6619. }
  6620. }
  6621. date->SetValue(value, is_value_nan);
  6622. return value;
  6623. }
  6624. RUNTIME_FUNCTION(MaybeObject*, Runtime_NewArgumentsFast) {
  6625. HandleScope scope(isolate);
  6626. ASSERT(args.length() == 3);
  6627. Handle<JSFunction> callee = args.at<JSFunction>(0);
  6628. Object** parameters = reinterpret_cast<Object**>(args[1]);
  6629. const int argument_count = Smi::cast(args[2])->value();
  6630. Handle<JSObject> result =
  6631. isolate->factory()->NewArgumentsObject(callee, argument_count);
  6632. // Allocate the elements if needed.
  6633. int parameter_count = callee->shared()->formal_parameter_count();
  6634. if (argument_count > 0) {
  6635. if (parameter_count > 0) {
  6636. int mapped_count = Min(argument_count, parameter_count);
  6637. Handle<FixedArray> parameter_map =
  6638. isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
  6639. parameter_map->set_map(
  6640. isolate->heap()->non_strict_arguments_elements_map());
  6641. Handle<Map> old_map(result->map());
  6642. Handle<Map> new_map = isolate->factory()->CopyMap(old_map);
  6643. new_map->set_elements_kind(NON_STRICT_ARGUMENTS_ELEMENTS);
  6644. result->set_map(*new_map);
  6645. result->set_elements(*parameter_map);
  6646. // Store the context and the arguments array at the beginning of the
  6647. // parameter map.
  6648. Handle<Context> context(isolate->context());
  6649. Handle<FixedArray> arguments =
  6650. isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
  6651. parameter_map->set(0, *context);
  6652. parameter_map->set(1, *arguments);
  6653. // Loop over the actual parameters backwards.
  6654. int index = argument_count - 1;
  6655. while (index >= mapped_count) {
  6656. // These go directly in the arguments array and have no
  6657. // corresponding slot in the parameter map.
  6658. arguments->set(index, *(parameters - index - 1));
  6659. --index;
  6660. }
  6661. Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
  6662. while (index >= 0) {
  6663. // Detect duplicate names to the right in the parameter list.
  6664. Handle<String> name(scope_info->ParameterName(index));
  6665. int context_local_count = scope_info->ContextLocalCount();
  6666. bool duplicate = false;
  6667. for (int j = index + 1; j < parameter_count; ++j) {
  6668. if (scope_info->ParameterName(j) == *name) {
  6669. duplicate = true;
  6670. break;
  6671. }
  6672. }
  6673. if (duplicate) {
  6674. // This goes directly in the arguments array with a hole in the
  6675. // parameter map.
  6676. arguments->set(index, *(parameters - index - 1));
  6677. parameter_map->set_the_hole(index + 2);
  6678. } else {
  6679. // The context index goes in the parameter map with a hole in the
  6680. // arguments array.
  6681. int context_index = -1;
  6682. for (int j = 0; j < context_local_count; ++j) {
  6683. if (scope_info->ContextLocalName(j) == *name) {
  6684. context_index = j;
  6685. break;
  6686. }
  6687. }
  6688. ASSERT(context_index >= 0);
  6689. arguments->set_the_hole(index);
  6690. parameter_map->set(index + 2, Smi::FromInt(
  6691. Context::MIN_CONTEXT_SLOTS + context_index));
  6692. }
  6693. --index;
  6694. }
  6695. } else {
  6696. // If there is no aliasing, the arguments object elements are not
  6697. // special in any way.
  6698. Handle<FixedArray> elements =
  6699. isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
  6700. result->set_elements(*elements);
  6701. for (int i = 0; i < argument_count; ++i) {
  6702. elements->set(i, *(parameters - i - 1));
  6703. }
  6704. }
  6705. }
  6706. return *result;
  6707. }
  6708. RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStrictArgumentsFast) {
  6709. SealHandleScope shs(isolate);
  6710. ASSERT(args.length() == 3);
  6711. JSFunction* callee = JSFunction::cast(args[0]);
  6712. Object** parameters = reinterpret_cast<Object**>(args[1]);
  6713. const int length = args.smi_at(2);
  6714. Object* result;
  6715. { MaybeObject* maybe_result =
  6716. isolate->heap()->AllocateArgumentsObject(callee, length);
  6717. if (!maybe_result->ToObject(&result)) return maybe_result;
  6718. }
  6719. // Allocate the elements if needed.
  6720. if (length > 0) {
  6721. // Allocate the fixed array.
  6722. Object* obj;
  6723. { MaybeObject* maybe_obj = isolate->heap()->AllocateRawFixedArray(length);
  6724. if (!maybe_obj->ToObject(&obj)) return maybe_obj;
  6725. }
  6726. DisallowHeapAllocation no_gc;
  6727. FixedArray* array = reinterpret_cast<FixedArray*>(obj);
  6728. array->set_map_no_write_barrier(isolate->heap()->fixed_array_map());
  6729. array->set_length(length);
  6730. WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
  6731. for (int i = 0; i < length; i++) {
  6732. array->set(i, *--parameters, mode);
  6733. }
  6734. JSObject::cast(result)->set_elements(FixedArray::cast(obj));
  6735. }
  6736. return result;
  6737. }
  6738. RUNTIME_FUNCTION(MaybeObject*, Runtime_NewClosure) {
  6739. HandleScope scope(isolate);
  6740. ASSERT(args.length() == 3);
  6741. CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
  6742. CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 1);
  6743. CONVERT_BOOLEAN_ARG_CHECKED(pretenure, 2);
  6744. // The caller ensures that we pretenure closures that are assigned
  6745. // directly to properties.
  6746. PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
  6747. Handle<JSFunction> result =
  6748. isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
  6749. context,
  6750. pretenure_flag);
  6751. return *result;
  6752. }
  6753. // Find the arguments of the JavaScript function invocation that called
  6754. // into C++ code. Collect these in a newly allocated array of handles (possibly
  6755. // prefixed by a number of empty handles).
  6756. static SmartArrayPointer<Handle<Object> > GetCallerArguments(
  6757. Isolate* isolate,
  6758. int prefix_argc,
  6759. int* total_argc) {
  6760. // Find frame containing arguments passed to the caller.
  6761. JavaScriptFrameIterator it(isolate);
  6762. JavaScriptFrame* frame = it.frame();
  6763. List<JSFunction*> functions(2);
  6764. frame->GetFunctions(&functions);
  6765. if (functions.length() > 1) {
  6766. int inlined_jsframe_index = functions.length() - 1;
  6767. JSFunction* inlined_function = functions[inlined_jsframe_index];
  6768. Vector<SlotRef> args_slots =
  6769. SlotRef::ComputeSlotMappingForArguments(
  6770. frame,
  6771. inlined_jsframe_index,
  6772. inlined_function->shared()->formal_parameter_count());
  6773. int args_count = args_slots.length();
  6774. *total_argc = prefix_argc + args_count;
  6775. SmartArrayPointer<Handle<Object> > param_data(
  6776. NewArray<Handle<Object> >(*total_argc));
  6777. for (int i = 0; i < args_count; i++) {
  6778. Handle<Object> val = args_slots[i].GetValue(isolate);
  6779. param_data[prefix_argc + i] = val;
  6780. }
  6781. args_slots.Dispose();
  6782. return param_data;
  6783. } else {
  6784. it.AdvanceToArgumentsFrame();
  6785. frame = it.frame();
  6786. int args_count = frame->ComputeParametersCount();
  6787. *total_argc = prefix_argc + args_count;
  6788. SmartArrayPointer<Handle<Object> > param_data(
  6789. NewArray<Handle<Object> >(*total_argc));
  6790. for (int i = 0; i < args_count; i++) {
  6791. Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate);
  6792. param_data[prefix_argc + i] = val;
  6793. }
  6794. return param_data;
  6795. }
  6796. }
  6797. RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionBindArguments) {
  6798. HandleScope scope(isolate);
  6799. ASSERT(args.length() == 4);
  6800. CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0);
  6801. RUNTIME_ASSERT(args[3]->IsNumber());
  6802. Handle<Object> bindee = args.at<Object>(1);
  6803. // TODO(lrn): Create bound function in C++ code from premade shared info.
  6804. bound_function->shared()->set_bound(true);
  6805. // Get all arguments of calling function (Function.prototype.bind).
  6806. int argc = 0;
  6807. SmartArrayPointer<Handle<Object> > arguments =
  6808. GetCallerArguments(isolate, 0, &argc);
  6809. // Don't count the this-arg.
  6810. if (argc > 0) {
  6811. ASSERT(*arguments[0] == args[2]);
  6812. argc--;
  6813. } else {
  6814. ASSERT(args[2]->IsUndefined());
  6815. }
  6816. // Initialize array of bindings (function, this, and any existing arguments
  6817. // if the function was already bound).
  6818. Handle<FixedArray> new_bindings;
  6819. int i;
  6820. if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) {
  6821. Handle<FixedArray> old_bindings(
  6822. JSFunction::cast(*bindee)->function_bindings());
  6823. new_bindings =
  6824. isolate->factory()->NewFixedArray(old_bindings->length() + argc);
  6825. bindee = Handle<Object>(old_bindings->get(JSFunction::kBoundFunctionIndex),
  6826. isolate);
  6827. i = 0;
  6828. for (int n = old_bindings->length(); i < n; i++) {
  6829. new_bindings->set(i, old_bindings->get(i));
  6830. }
  6831. } else {
  6832. int array_size = JSFunction::kBoundArgumentsStartIndex + argc;
  6833. new_bindings = isolate->factory()->NewFixedArray(array_size);
  6834. new_bindings->set(JSFunction::kBoundFunctionIndex, *bindee);
  6835. new_bindings->set(JSFunction::kBoundThisIndex, args[2]);
  6836. i = 2;
  6837. }
  6838. // Copy arguments, skipping the first which is "this_arg".
  6839. for (int j = 0; j < argc; j++, i++) {
  6840. new_bindings->set(i, *arguments[j + 1]);
  6841. }
  6842. new_bindings->set_map_no_write_barrier(
  6843. isolate->heap()->fixed_cow_array_map());
  6844. bound_function->set_function_bindings(*new_bindings);
  6845. // Update length.
  6846. Handle<String> length_string = isolate->factory()->length_string();
  6847. Handle<Object> new_length(args.at<Object>(3));
  6848. PropertyAttributes attr =
  6849. static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY);
  6850. ForceSetProperty(bound_function, length_string, new_length, attr);
  6851. return *bound_function;
  6852. }
  6853. RUNTIME_FUNCTION(MaybeObject*, Runtime_BoundFunctionGetBindings) {
  6854. HandleScope handles(isolate);
  6855. ASSERT(args.length() == 1);
  6856. CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0);
  6857. if (callable->IsJSFunction()) {
  6858. Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
  6859. if (function->shared()->bound()) {
  6860. Handle<FixedArray> bindings(function->function_bindings());
  6861. ASSERT(bindings->map() == isolate->heap()->fixed_cow_array_map());
  6862. return *isolate->factory()->NewJSArrayWithElements(bindings);
  6863. }
  6864. }
  6865. return isolate->heap()->undefined_value();
  6866. }
  6867. RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObjectFromBound) {
  6868. HandleScope scope(isolate);
  6869. ASSERT(args.length() == 1);
  6870. // First argument is a function to use as a constructor.
  6871. CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
  6872. RUNTIME_ASSERT(function->shared()->bound());
  6873. // The argument is a bound function. Extract its bound arguments
  6874. // and callable.
  6875. Handle<FixedArray> bound_args =
  6876. Handle<FixedArray>(FixedArray::cast(function->function_bindings()));
  6877. int bound_argc = bound_args->length() - JSFunction::kBoundArgumentsStartIndex;
  6878. Handle<Object> bound_function(
  6879. JSReceiver::cast(bound_args->get(JSFunction::kBoundFunctionIndex)),
  6880. isolate);
  6881. ASSERT(!bound_function->IsJSFunction() ||
  6882. !Handle<JSFunction>::cast(bound_function)->shared()->bound());
  6883. int total_argc = 0;
  6884. SmartArrayPointer<Handle<Object> > param_data =
  6885. GetCallerArguments(isolate, bound_argc, &total_argc);
  6886. for (int i = 0; i < bound_argc; i++) {
  6887. param_data[i] = Handle<Object>(bound_args->get(
  6888. JSFunction::kBoundArgumentsStartIndex + i), isolate);
  6889. }
  6890. if (!bound_function->IsJSFunction()) {
  6891. bool exception_thrown;
  6892. bound_function = Execution::TryGetConstructorDelegate(bound_function,
  6893. &exception_thrown);
  6894. if (exception_thrown) return Failure::Exception();
  6895. }
  6896. ASSERT(bound_function->IsJSFunction());
  6897. bool exception = false;
  6898. Handle<Object> result =
  6899. Execution::New(Handle<JSFunction>::cast(bound_function),
  6900. total_argc, *param_data, &exception);
  6901. if (exception) {
  6902. return Failure::Exception();
  6903. }
  6904. ASSERT(!result.is_null());
  6905. return *result;
  6906. }
  6907. RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObject) {
  6908. HandleScope scope(isolate);
  6909. ASSERT(args.length() == 1);
  6910. Handle<Object> constructor = args.at<Object>(0);
  6911. // If the constructor isn't a proper function we throw a type error.
  6912. if (!constructor->IsJSFunction()) {
  6913. Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
  6914. Handle<Object> type_error =
  6915. isolate->factory()->NewTypeError("not_constructor", arguments);
  6916. return isolate->Throw(*type_error);
  6917. }
  6918. Handle<JSFunction> function = Handle<JSFunction>::cast(constructor);
  6919. // If function should not have prototype, construction is not allowed. In this
  6920. // case generated code bailouts here, since function has no initial_map.
  6921. if (!function->should_have_prototype() && !function->shared()->bound()) {
  6922. Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
  6923. Handle<Object> type_error =
  6924. isolate->factory()->NewTypeError("not_constructor", arguments);
  6925. return isolate->Throw(*type_error);
  6926. }
  6927. #ifdef ENABLE_DEBUGGER_SUPPORT
  6928. Debug* debug = isolate->debug();
  6929. // Handle stepping into constructors if step into is active.
  6930. if (debug->StepInActive()) {
  6931. debug->HandleStepIn(function, Handle<Object>::null(), 0, true);
  6932. }
  6933. #endif
  6934. if (function->has_initial_map()) {
  6935. if (function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
  6936. // The 'Function' function ignores the receiver object when
  6937. // called using 'new' and creates a new JSFunction object that
  6938. // is returned. The receiver object is only used for error
  6939. // reporting if an error occurs when constructing the new
  6940. // JSFunction. Factory::NewJSObject() should not be used to
  6941. // allocate JSFunctions since it does not properly initialize
  6942. // the shared part of the function. Since the receiver is
  6943. // ignored anyway, we use the global object as the receiver
  6944. // instead of a new JSFunction object. This way, errors are
  6945. // reported the same way whether or not 'Function' is called
  6946. // using 'new'.
  6947. return isolate->context()->global_object();
  6948. }
  6949. }
  6950. // The function should be compiled for the optimization hints to be
  6951. // available.
  6952. JSFunction::EnsureCompiled(function, CLEAR_EXCEPTION);
  6953. Handle<SharedFunctionInfo> shared(function->shared(), isolate);
  6954. if (!function->has_initial_map() &&
  6955. shared->IsInobjectSlackTrackingInProgress()) {
  6956. // The tracking is already in progress for another function. We can only
  6957. // track one initial_map at a time, so we force the completion before the
  6958. // function is called as a constructor for the first time.
  6959. shared->CompleteInobjectSlackTracking();
  6960. }
  6961. Handle<JSObject> result = isolate->factory()->NewJSObject(function);
  6962. RETURN_IF_EMPTY_HANDLE(isolate, result);
  6963. isolate->counters()->constructed_objects()->Increment();
  6964. isolate->counters()->constructed_objects_runtime()->Increment();
  6965. return *result;
  6966. }
  6967. RUNTIME_FUNCTION(MaybeObject*, Runtime_FinalizeInstanceSize) {
  6968. HandleScope scope(isolate);
  6969. ASSERT(args.length() == 1);
  6970. CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
  6971. function->shared()->CompleteInobjectSlackTracking();
  6972. return isolate->heap()->undefined_value();
  6973. }
  6974. RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyCompile) {
  6975. HandleScope scope(isolate);
  6976. ASSERT(args.length() == 1);
  6977. Handle<JSFunction> function = args.at<JSFunction>(0);
  6978. #ifdef DEBUG
  6979. if (FLAG_trace_lazy && !function->shared()->is_compiled()) {
  6980. PrintF("[lazy: ");
  6981. function->PrintName();
  6982. PrintF("]\n");
  6983. }
  6984. #endif
  6985. // Compile the target function.
  6986. ASSERT(!function->is_compiled());
  6987. if (!JSFunction::CompileLazy(function, KEEP_EXCEPTION)) {
  6988. return Failure::Exception();
  6989. }
  6990. // All done. Return the compiled code.
  6991. ASSERT(function->is_compiled());
  6992. return function->code();
  6993. }
  6994. bool AllowOptimization(Isolate* isolate, Handle<JSFunction> function) {
  6995. // If the function is not compiled ignore the lazy
  6996. // recompilation. This can happen if the debugger is activated and
  6997. // the function is returned to the not compiled state.
  6998. if (!function->shared()->is_compiled()) return false;
  6999. // If the function is not optimizable or debugger is active continue using the
  7000. // code from the full compiler.
  7001. if (!FLAG_crankshaft ||
  7002. function->shared()->optimization_disabled() ||
  7003. isolate->DebuggerHasBreakPoints()) {
  7004. if (FLAG_trace_opt) {
  7005. PrintF("[failed to optimize ");
  7006. function->PrintName();
  7007. PrintF(": is code optimizable: %s, is debugger enabled: %s]\n",
  7008. function->shared()->optimization_disabled() ? "F" : "T",
  7009. isolate->DebuggerHasBreakPoints() ? "T" : "F");
  7010. }
  7011. return false;
  7012. }
  7013. return true;
  7014. }
  7015. RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyRecompile) {
  7016. HandleScope scope(isolate);
  7017. ASSERT(args.length() == 1);
  7018. Handle<JSFunction> function = args.at<JSFunction>(0);
  7019. if (!AllowOptimization(isolate, function)) {
  7020. function->ReplaceCode(function->shared()->code());
  7021. return function->code();
  7022. }
  7023. function->shared()->code()->set_profiler_ticks(0);
  7024. if (JSFunction::CompileOptimized(function,
  7025. BailoutId::None(),
  7026. CLEAR_EXCEPTION)) {
  7027. return function->code();
  7028. }
  7029. if (FLAG_trace_opt) {
  7030. PrintF("[failed to optimize ");
  7031. function->PrintName();
  7032. PrintF(": optimized compilation failed]\n");
  7033. }
  7034. function->ReplaceCode(function->shared()->code());
  7035. return function->code();
  7036. }
  7037. RUNTIME_FUNCTION(MaybeObject*, Runtime_ParallelRecompile) {
  7038. HandleScope handle_scope(isolate);
  7039. ASSERT(args.length() == 1);
  7040. CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
  7041. if (!AllowOptimization(isolate, function)) {
  7042. function->ReplaceCode(function->shared()->code());
  7043. return isolate->heap()->undefined_value();
  7044. }
  7045. function->shared()->code()->set_profiler_ticks(0);
  7046. ASSERT(FLAG_parallel_recompilation);
  7047. Compiler::RecompileParallel(function);
  7048. return isolate->heap()->undefined_value();
  7049. }
  7050. RUNTIME_FUNCTION(MaybeObject*, Runtime_InstallRecompiledCode) {
  7051. HandleScope handle_scope(isolate);
  7052. ASSERT(args.length() == 1);
  7053. CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
  7054. ASSERT(V8::UseCrankshaft() && FLAG_parallel_recompilation);
  7055. isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
  7056. return function->code();
  7057. }
  7058. class ActivationsFinder : public ThreadVisitor {
  7059. public:
  7060. Code* code_;
  7061. bool has_code_activations_;
  7062. explicit ActivationsFinder(Code* code)
  7063. : code_(code),
  7064. has_code_activations_(false) { }
  7065. void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
  7066. JavaScriptFrameIterator it(isolate, top);
  7067. VisitFrames(&it);
  7068. }
  7069. void VisitFrames(JavaScriptFrameIterator* it) {
  7070. for (; !it->done(); it->Advance()) {
  7071. JavaScriptFrame* frame = it->frame();
  7072. if (code_->contains(frame->pc())) has_code_activations_ = true;
  7073. }
  7074. }
  7075. };
  7076. RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyStubFailure) {
  7077. HandleScope scope(isolate);
  7078. ASSERT(args.length() == 0);
  7079. Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
  7080. ASSERT(AllowHeapAllocation::IsAllowed());
  7081. delete deoptimizer;
  7082. return isolate->heap()->undefined_value();
  7083. }
  7084. RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyDeoptimized) {
  7085. HandleScope scope(isolate);
  7086. ASSERT(args.length() == 1);
  7087. RUNTIME_ASSERT(args[0]->IsSmi());
  7088. Deoptimizer::BailoutType type =
  7089. static_cast<Deoptimizer::BailoutType>(args.smi_at(0));
  7090. Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
  7091. ASSERT(AllowHeapAllocation::IsAllowed());
  7092. Handle<JSFunction> function = deoptimizer->function();
  7093. Handle<Code> optimized_code = deoptimizer->compiled_code();
  7094. ASSERT(optimized_code->kind() == Code::OPTIMIZED_FUNCTION);
  7095. ASSERT(type == deoptimizer->bailout_type());
  7096. // Make sure to materialize objects before causing any allocation.
  7097. JavaScriptFrameIterator it(isolate);
  7098. deoptimizer->MaterializeHeapObjects(&it);
  7099. delete deoptimizer;
  7100. JavaScriptFrame* frame = it.frame();
  7101. RUNTIME_ASSERT(frame->function()->IsJSFunction());
  7102. // Avoid doing too much work when running with --always-opt and keep
  7103. // the optimized code around.
  7104. if (FLAG_always_opt || type == Deoptimizer::LAZY) {
  7105. return isolate->heap()->undefined_value();
  7106. }
  7107. // Search for other activations of the same function and code.
  7108. ActivationsFinder activations_finder(*optimized_code);
  7109. activations_finder.VisitFrames(&it);
  7110. isolate->thread_manager()->IterateArchivedThreads(&activations_finder);
  7111. if (!activations_finder.has_code_activations_) {
  7112. if (function->code() == *optimized_code) {
  7113. if (FLAG_trace_deopt) {
  7114. PrintF("[removing optimized code for: ");
  7115. function->PrintName();
  7116. PrintF("]\n");
  7117. }
  7118. function->ReplaceCode(function->shared()->code());
  7119. }
  7120. } else {
  7121. // TODO(titzer): we should probably do DeoptimizeCodeList(code)
  7122. // unconditionally if the code is not already marked for deoptimization.
  7123. // If there is an index by shared function info, all the better.
  7124. Deoptimizer::DeoptimizeFunction(*function);
  7125. }
  7126. // Evict optimized code for this function from the cache so that it doesn't
  7127. // get used for new closures.
  7128. function->shared()->EvictFromOptimizedCodeMap(*optimized_code,
  7129. "notify deoptimized");
  7130. return isolate->heap()->undefined_value();
  7131. }
  7132. RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyOSR) {
  7133. SealHandleScope shs(isolate);
  7134. Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
  7135. delete deoptimizer;
  7136. return isolate->heap()->undefined_value();
  7137. }
  7138. RUNTIME_FUNCTION(MaybeObject*, Runtime_DeoptimizeFunction) {
  7139. HandleScope scope(isolate);
  7140. ASSERT(args.length() == 1);
  7141. CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
  7142. if (!function->IsOptimized()) return isolate->heap()->undefined_value();
  7143. Deoptimizer::DeoptimizeFunction(*function);
  7144. return isolate->heap()->undefined_value();
  7145. }
  7146. RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearFunctionTypeFeedback) {
  7147. HandleScope scope(isolate);
  7148. ASSERT(args.length() == 1);
  7149. CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
  7150. Code* unoptimized = function->shared()->code();
  7151. if (unoptimized->kind() == Code::FUNCTION) {
  7152. unoptimized->ClearInlineCaches();
  7153. unoptimized->ClearTypeFeedbackCells(isolate->heap());
  7154. }
  7155. return isolate->heap()->undefined_value();
  7156. }
  7157. RUNTIME_FUNCTION(MaybeObject*, Runtime_RunningInSimulator) {
  7158. SealHandleScope shs(isolate);
  7159. #if defined(USE_SIMULATOR)
  7160. return isolate->heap()->true_value();
  7161. #else
  7162. return isolate->heap()->false_value();
  7163. #endif
  7164. }
  7165. RUNTIME_FUNCTION(MaybeObject*, Runtime_IsParallelRecompilationSupported) {
  7166. HandleScope scope(isolate);
  7167. return FLAG_parallel_recompilation
  7168. ? isolate->heap()->true_value() : isolate->heap()->false_value();
  7169. }
  7170. RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) {
  7171. HandleScope scope(isolate);
  7172. RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
  7173. CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
  7174. if (!function->IsOptimizable()) return isolate->heap()->undefined_value();
  7175. function->MarkForLazyRecompilation();
  7176. Code* unoptimized = function->shared()->code();
  7177. if (args.length() == 2 &&
  7178. unoptimized->kind() == Code::FUNCTION) {
  7179. CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
  7180. if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("osr"))) {
  7181. for (int i = 0; i <= Code::kMaxLoopNestingMarker; i++) {
  7182. unoptimized->set_allow_osr_at_loop_nesting_level(i);
  7183. isolate->runtime_profiler()->AttemptOnStackReplacement(*function);
  7184. }
  7185. } else if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("parallel"))) {
  7186. function->MarkForParallelRecompilation();
  7187. }
  7188. }
  7189. return isolate->heap()->undefined_value();
  7190. }
  7191. RUNTIME_FUNCTION(MaybeObject*, Runtime_NeverOptimizeFunction) {
  7192. HandleScope scope(isolate);
  7193. ASSERT(args.length() == 1);
  7194. CONVERT_ARG_CHECKED(JSFunction, function, 0);
  7195. ASSERT(!function->IsOptimized());
  7196. function->shared()->set_optimization_disabled(true);
  7197. return isolate->heap()->undefined_value();
  7198. }
  7199. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) {
  7200. HandleScope scope(isolate);
  7201. RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
  7202. if (!V8::UseCrankshaft()) {
  7203. return Smi::FromInt(4); // 4 == "never".
  7204. }
  7205. bool sync_with_compiler_thread = true;
  7206. if (args.length() == 2) {
  7207. CONVERT_ARG_HANDLE_CHECKED(String, sync, 1);
  7208. if (sync->IsOneByteEqualTo(STATIC_ASCII_VECTOR("no sync"))) {
  7209. sync_with_compiler_thread = false;
  7210. }
  7211. }
  7212. CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
  7213. if (FLAG_parallel_recompilation && sync_with_compiler_thread) {
  7214. while (function->IsInRecompileQueue() ||
  7215. function->IsMarkedForInstallingRecompiledCode()) {
  7216. isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
  7217. OS::Sleep(50);
  7218. }
  7219. }
  7220. if (FLAG_always_opt) {
  7221. // We may have always opt, but that is more best-effort than a real
  7222. // promise, so we still say "no" if it is not optimized.
  7223. return function->IsOptimized() ? Smi::FromInt(3) // 3 == "always".
  7224. : Smi::FromInt(2); // 2 == "no".
  7225. }
  7226. if (FLAG_deopt_every_n_times) {
  7227. return Smi::FromInt(6); // 6 == "maybe deopted".
  7228. }
  7229. return function->IsOptimized() ? Smi::FromInt(1) // 1 == "yes".
  7230. : Smi::FromInt(2); // 2 == "no".
  7231. }
  7232. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationCount) {
  7233. HandleScope scope(isolate);
  7234. ASSERT(args.length() == 1);
  7235. CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
  7236. return Smi::FromInt(function->shared()->opt_count());
  7237. }
  7238. RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
  7239. HandleScope scope(isolate);
  7240. ASSERT(args.length() == 1);
  7241. CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
  7242. // We're not prepared to handle a function with arguments object.
  7243. ASSERT(!function->shared()->uses_arguments());
  7244. // We have hit a back edge in an unoptimized frame for a function that was
  7245. // selected for on-stack replacement. Find the unoptimized code object.
  7246. Handle<Code> unoptimized(function->shared()->code(), isolate);
  7247. // Keep track of whether we've succeeded in optimizing.
  7248. bool succeeded = unoptimized->optimizable();
  7249. if (succeeded) {
  7250. // If we are trying to do OSR when there are already optimized
  7251. // activations of the function, it means (a) the function is directly or
  7252. // indirectly recursive and (b) an optimized invocation has been
  7253. // deoptimized so that we are currently in an unoptimized activation.
  7254. // Check for optimized activations of this function.
  7255. JavaScriptFrameIterator it(isolate);
  7256. while (succeeded && !it.done()) {
  7257. JavaScriptFrame* frame = it.frame();
  7258. succeeded = !frame->is_optimized() || frame->function() != *function;
  7259. it.Advance();
  7260. }
  7261. }
  7262. BailoutId ast_id = BailoutId::None();
  7263. if (succeeded) {
  7264. // The top JS function is this one, the PC is somewhere in the
  7265. // unoptimized code.
  7266. JavaScriptFrameIterator it(isolate);
  7267. JavaScriptFrame* frame = it.frame();
  7268. ASSERT(frame->function() == *function);
  7269. ASSERT(frame->LookupCode() == *unoptimized);
  7270. ASSERT(unoptimized->contains(frame->pc()));
  7271. // Use linear search of the unoptimized code's back edge table to find
  7272. // the AST id matching the PC.
  7273. uint32_t target_pc_offset =
  7274. static_cast<uint32_t>(frame->pc() - unoptimized->instruction_start());
  7275. uint32_t loop_depth = 0;
  7276. for (FullCodeGenerator::BackEdgeTableIterator back_edges(*unoptimized);
  7277. !back_edges.Done();
  7278. back_edges.Next()) {
  7279. if (back_edges.pc_offset() == target_pc_offset) {
  7280. ast_id = back_edges.ast_id();
  7281. loop_depth = back_edges.loop_depth();
  7282. break;
  7283. }
  7284. }
  7285. ASSERT(!ast_id.IsNone());
  7286. if (FLAG_trace_osr) {
  7287. PrintF("[replacing on-stack at AST id %d, loop depth %d in ",
  7288. ast_id.ToInt(), loop_depth);
  7289. function->PrintName();
  7290. PrintF("]\n");
  7291. }
  7292. // Try to compile the optimized code. A true return value from
  7293. // CompileOptimized means that compilation succeeded, not necessarily
  7294. // that optimization succeeded.
  7295. if (JSFunction::CompileOptimized(function, ast_id, CLEAR_EXCEPTION) &&
  7296. function->IsOptimized()) {
  7297. DeoptimizationInputData* data = DeoptimizationInputData::cast(
  7298. function->code()->deoptimization_data());
  7299. if (data->OsrPcOffset()->value() >= 0) {
  7300. if (FLAG_trace_osr) {
  7301. PrintF("[on-stack replacement offset %d in optimized code]\n",
  7302. data->OsrPcOffset()->value());
  7303. }
  7304. ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id);
  7305. } else {
  7306. // We may never generate the desired OSR entry if we emit an
  7307. // early deoptimize.
  7308. succeeded = false;
  7309. }
  7310. } else {
  7311. succeeded = false;
  7312. }
  7313. }
  7314. // Revert to the original interrupt calls in the original unoptimized code.
  7315. if (FLAG_trace_osr) {
  7316. PrintF("[restoring original interrupt calls in ");
  7317. function->PrintName();
  7318. PrintF("]\n");
  7319. }
  7320. InterruptStub interrupt_stub;
  7321. Handle<Code> interrupt_code = interrupt_stub.GetCode(isolate);
  7322. Handle<Code> replacement_code = isolate->builtins()->OnStackReplacement();
  7323. Deoptimizer::RevertInterruptCode(*unoptimized,
  7324. *interrupt_code,
  7325. *replacement_code);
  7326. // If the optimization attempt succeeded, return the AST id tagged as a
  7327. // smi. This tells the builtin that we need to translate the unoptimized
  7328. // frame to an optimized one.
  7329. if (succeeded) {
  7330. ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION);
  7331. return Smi::FromInt(ast_id.ToInt());
  7332. } else {
  7333. if (function->IsMarkedForLazyRecompilation()) {
  7334. function->ReplaceCode(function->shared()->code());
  7335. }
  7336. return Smi::FromInt(-1);
  7337. }
  7338. }
  7339. RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAllocationTimeout) {
  7340. SealHandleScope shs(isolate);
  7341. ASSERT(args.length() == 2);
  7342. #ifdef DEBUG
  7343. CONVERT_SMI_ARG_CHECKED(interval, 0);
  7344. CONVERT_SMI_ARG_CHECKED(timeout, 1);
  7345. isolate->heap()->set_allocation_timeout(timeout);
  7346. FLAG_gc_interval = interval;
  7347. #endif
  7348. return isolate->heap()->undefined_value();
  7349. }
  7350. RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckIsBootstrapping) {
  7351. SealHandleScope shs(isolate);
  7352. RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
  7353. return isolate->heap()->undefined_value();
  7354. }
  7355. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetRootNaN) {
  7356. SealHandleScope shs(isolate);
  7357. RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
  7358. return isolate->heap()->nan_value();
  7359. }
  7360. RUNTIME_FUNCTION(MaybeObject*, Runtime_Call) {
  7361. HandleScope scope(isolate);
  7362. ASSERT(args.length() >= 2);
  7363. int argc = args.length() - 2;
  7364. CONVERT_ARG_CHECKED(JSReceiver, fun, argc + 1);
  7365. Object* receiver = args[0];
  7366. // If there are too many arguments, allocate argv via malloc.
  7367. const int argv_small_size = 10;
  7368. Handle<Object> argv_small_buffer[argv_small_size];
  7369. SmartArrayPointer<Handle<Object> > argv_large_buffer;
  7370. Handle<Object>* argv = argv_small_buffer;
  7371. if (argc > argv_small_size) {
  7372. argv = new Handle<Object>[argc];
  7373. if (argv == NULL) return isolate->StackOverflow();
  7374. argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
  7375. }
  7376. for (int i = 0; i < argc; ++i) {
  7377. MaybeObject* maybe = args[1 + i];
  7378. Object* object;
  7379. if (!maybe->To<Object>(&object)) return maybe;
  7380. argv[i] = Handle<Object>(object, isolate);
  7381. }
  7382. bool threw;
  7383. Handle<JSReceiver> hfun(fun);
  7384. Handle<Object> hreceiver(receiver, isolate);
  7385. Handle<Object> result =
  7386. Execution::Call(hfun, hreceiver, argc, argv, &threw, true);
  7387. if (threw) return Failure::Exception();
  7388. return *result;
  7389. }
  7390. RUNTIME_FUNCTION(MaybeObject*, Runtime_Apply) {
  7391. HandleScope scope(isolate);
  7392. ASSERT(args.length() == 5);
  7393. CONVERT_ARG_HANDLE_CHECKED(JSReceiver, fun, 0);
  7394. Handle<Object> receiver = args.at<Object>(1);
  7395. CONVERT_ARG_HANDLE_CHECKED(JSObject, arguments, 2);
  7396. CONVERT_SMI_ARG_CHECKED(offset, 3);
  7397. CONVERT_SMI_ARG_CHECKED(argc, 4);
  7398. RUNTIME_ASSERT(offset >= 0);
  7399. RUNTIME_ASSERT(argc >= 0);
  7400. // If there are too many arguments, allocate argv via malloc.
  7401. const int argv_small_size = 10;
  7402. Handle<Object> argv_small_buffer[argv_small_size];
  7403. SmartArrayPointer<Handle<Object> > argv_large_buffer;
  7404. Handle<Object>* argv = argv_small_buffer;
  7405. if (argc > argv_small_size) {
  7406. argv = new Handle<Object>[argc];
  7407. if (argv == NULL) return isolate->StackOverflow();
  7408. argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
  7409. }
  7410. for (int i = 0; i < argc; ++i) {
  7411. argv[i] = Object::GetElement(arguments, offset + i);
  7412. }
  7413. bool threw;
  7414. Handle<Object> result =
  7415. Execution::Call(fun, receiver, argc, argv, &threw, true);
  7416. if (threw) return Failure::Exception();
  7417. return *result;
  7418. }
  7419. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionDelegate) {
  7420. HandleScope scope(isolate);
  7421. ASSERT(args.length() == 1);
  7422. RUNTIME_ASSERT(!args[0]->IsJSFunction());
  7423. return *Execution::GetFunctionDelegate(args.at<Object>(0));
  7424. }
  7425. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) {
  7426. HandleScope scope(isolate);
  7427. ASSERT(args.length() == 1);
  7428. RUNTIME_ASSERT(!args[0]->IsJSFunction());
  7429. return *Execution::GetConstructorDelegate(args.at<Object>(0));
  7430. }
  7431. RUNTIME_FUNCTION(MaybeObject*, Runtime_NewGlobalContext) {
  7432. SealHandleScope shs(isolate);
  7433. ASSERT(args.length() == 2);
  7434. CONVERT_ARG_CHECKED(JSFunction, function, 0);
  7435. CONVERT_ARG_CHECKED(ScopeInfo, scope_info, 1);
  7436. Context* result;
  7437. MaybeObject* maybe_result =
  7438. isolate->heap()->AllocateGlobalContext(function, scope_info);
  7439. if (!maybe_result->To(&result)) return maybe_result;
  7440. ASSERT(function->context() == isolate->context());
  7441. ASSERT(function->context()->global_object() == result->global_object());
  7442. isolate->set_context(result);
  7443. result->global_object()->set_global_context(result);
  7444. return result; // non-failure
  7445. }
  7446. RUNTIME_FUNCTION(MaybeObject*, Runtime_NewFunctionContext) {
  7447. SealHandleScope shs(isolate);
  7448. ASSERT(args.length() == 1);
  7449. CONVERT_ARG_CHECKED(JSFunction, function, 0);
  7450. int length = function->shared()->scope_info()->ContextLength();
  7451. Context* result;
  7452. MaybeObject* maybe_result =
  7453. isolate->heap()->AllocateFunctionContext(length, function);
  7454. if (!maybe_result->To(&result)) return maybe_result;
  7455. isolate->set_context(result);
  7456. return result; // non-failure
  7457. }
  7458. RUNTIME_FUNCTION(MaybeObject*, Runtime_PushWithContext) {
  7459. SealHandleScope shs(isolate);
  7460. ASSERT(args.length() == 2);
  7461. JSReceiver* extension_object;
  7462. if (args[0]->IsJSReceiver()) {
  7463. extension_object = JSReceiver::cast(args[0]);
  7464. } else {
  7465. // Convert the object to a proper JavaScript object.
  7466. MaybeObject* maybe_js_object = args[0]->ToObject();
  7467. if (!maybe_js_object->To(&extension_object)) {
  7468. if (Failure::cast(maybe_js_object)->IsInternalError()) {
  7469. HandleScope scope(isolate);
  7470. Handle<Object> handle = args.at<Object>(0);
  7471. Handle<Object> result =
  7472. isolate->factory()->NewTypeError("with_expression",
  7473. HandleVector(&handle, 1));
  7474. return isolate->Throw(*result);
  7475. } else {
  7476. return maybe_js_object;
  7477. }
  7478. }
  7479. }
  7480. JSFunction* function;
  7481. if (args[1]->IsSmi()) {
  7482. // A smi sentinel indicates a context nested inside global code rather
  7483. // than some function. There is a canonical empty function that can be
  7484. // gotten from the native context.
  7485. function = isolate->context()->native_context()->closure();
  7486. } else {
  7487. function = JSFunction::cast(args[1]);
  7488. }
  7489. Context* context;
  7490. MaybeObject* maybe_context =
  7491. isolate->heap()->AllocateWithContext(function,
  7492. isolate->context(),
  7493. extension_object);
  7494. if (!maybe_context->To(&context)) return maybe_context;
  7495. isolate->set_context(context);
  7496. return context;
  7497. }
  7498. RUNTIME_FUNCTION(MaybeObject*, Runtime_PushCatchContext) {
  7499. SealHandleScope shs(isolate);
  7500. ASSERT(args.length() == 3);
  7501. String* name = String::cast(args[0]);
  7502. Object* thrown_object = args[1];
  7503. JSFunction* function;
  7504. if (args[2]->IsSmi()) {
  7505. // A smi sentinel indicates a context nested inside global code rather
  7506. // than some function. There is a canonical empty function that can be
  7507. // gotten from the native context.
  7508. function = isolate->context()->native_context()->closure();
  7509. } else {
  7510. function = JSFunction::cast(args[2]);
  7511. }
  7512. Context* context;
  7513. MaybeObject* maybe_context =
  7514. isolate->heap()->AllocateCatchContext(function,
  7515. isolate->context(),
  7516. name,
  7517. thrown_object);
  7518. if (!maybe_context->To(&context)) return maybe_context;
  7519. isolate->set_context(context);
  7520. return context;
  7521. }
  7522. RUNTIME_FUNCTION(MaybeObject*, Runtime_PushBlockContext) {
  7523. SealHandleScope shs(isolate);
  7524. ASSERT(args.length() == 2);
  7525. ScopeInfo* scope_info = ScopeInfo::cast(args[0]);
  7526. JSFunction* function;
  7527. if (args[1]->IsSmi()) {
  7528. // A smi sentinel indicates a context nested inside global code rather
  7529. // than some function. There is a canonical empty function that can be
  7530. // gotten from the native context.
  7531. function = isolate->context()->native_context()->closure();
  7532. } else {
  7533. function = JSFunction::cast(args[1]);
  7534. }
  7535. Context* context;
  7536. MaybeObject* maybe_context =
  7537. isolate->heap()->AllocateBlockContext(function,
  7538. isolate->context(),
  7539. scope_info);
  7540. if (!maybe_context->To(&context)) return maybe_context;
  7541. isolate->set_context(context);
  7542. return context;
  7543. }
  7544. RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSModule) {
  7545. SealHandleScope shs(isolate);
  7546. ASSERT(args.length() == 1);
  7547. Object* obj = args[0];
  7548. return isolate->heap()->ToBoolean(obj->IsJSModule());
  7549. }
  7550. RUNTIME_FUNCTION(MaybeObject*, Runtime_PushModuleContext) {
  7551. SealHandleScope shs(isolate);
  7552. ASSERT(args.length() == 2);
  7553. CONVERT_SMI_ARG_CHECKED(index, 0);
  7554. if (!args[1]->IsScopeInfo()) {
  7555. // Module already initialized. Find hosting context and retrieve context.
  7556. Context* host = Context::cast(isolate->context())->global_context();
  7557. Context* context = Context::cast(host->get(index));
  7558. ASSERT(context->previous() == isolate->context());
  7559. isolate->set_context(context);
  7560. return context;
  7561. }
  7562. CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
  7563. // Allocate module context.
  7564. HandleScope scope(isolate);
  7565. Factory* factory = isolate->factory();
  7566. Handle<Context> context = factory->NewModuleContext(scope_info);
  7567. Handle<JSModule> module = factory->NewJSModule(context, scope_info);
  7568. context->set_module(*module);
  7569. Context* previous = isolate->context();
  7570. context->set_previous(previous);
  7571. context->set_closure(previous->closure());
  7572. context->set_global_object(previous->global_object());
  7573. isolate->set_context(*context);
  7574. // Find hosting scope and initialize internal variable holding module there.
  7575. previous->global_context()->set(index, *context);
  7576. return *context;
  7577. }
  7578. RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareModules) {
  7579. HandleScope scope(isolate);
  7580. ASSERT(args.length() == 1);
  7581. CONVERT_ARG_HANDLE_CHECKED(FixedArray, descriptions, 0);
  7582. Context* host_context = isolate->context();
  7583. for (int i = 0; i < descriptions->length(); ++i) {
  7584. Handle<ModuleInfo> description(ModuleInfo::cast(descriptions->get(i)));
  7585. int host_index = description->host_index();
  7586. Handle<Context> context(Context::cast(host_context->get(host_index)));
  7587. Handle<JSModule> module(context->module());
  7588. for (int j = 0; j < description->length(); ++j) {
  7589. Handle<String> name(description->name(j));
  7590. VariableMode mode = description->mode(j);
  7591. int index = description->index(j);
  7592. switch (mode) {
  7593. case VAR:
  7594. case LET:
  7595. case CONST:
  7596. case CONST_HARMONY: {
  7597. PropertyAttributes attr =
  7598. IsImmutableVariableMode(mode) ? FROZEN : SEALED;
  7599. Handle<AccessorInfo> info =
  7600. Accessors::MakeModuleExport(name, index, attr);
  7601. Handle<Object> result = SetAccessor(module, info);
  7602. ASSERT(!(result.is_null() || result->IsUndefined()));
  7603. USE(result);
  7604. break;
  7605. }
  7606. case MODULE: {
  7607. Object* referenced_context = Context::cast(host_context)->get(index);
  7608. Handle<JSModule> value(Context::cast(referenced_context)->module());
  7609. JSReceiver::SetProperty(module, name, value, FROZEN, kStrictMode);
  7610. break;
  7611. }
  7612. case INTERNAL:
  7613. case TEMPORARY:
  7614. case DYNAMIC:
  7615. case DYNAMIC_GLOBAL:
  7616. case DYNAMIC_LOCAL:
  7617. UNREACHABLE();
  7618. }
  7619. }
  7620. JSObject::PreventExtensions(module);
  7621. }
  7622. ASSERT(!isolate->has_pending_exception());
  7623. return isolate->heap()->undefined_value();
  7624. }
  7625. RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteContextSlot) {
  7626. HandleScope scope(isolate);
  7627. ASSERT(args.length() == 2);
  7628. CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
  7629. CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
  7630. int index;
  7631. PropertyAttributes attributes;
  7632. ContextLookupFlags flags = FOLLOW_CHAINS;
  7633. BindingFlags binding_flags;
  7634. Handle<Object> holder = context->Lookup(name,
  7635. flags,
  7636. &index,
  7637. &attributes,
  7638. &binding_flags);
  7639. // If the slot was not found the result is true.
  7640. if (holder.is_null()) {
  7641. return isolate->heap()->true_value();
  7642. }
  7643. // If the slot was found in a context, it should be DONT_DELETE.
  7644. if (holder->IsContext()) {
  7645. return isolate->heap()->false_value();
  7646. }
  7647. // The slot was found in a JSObject, either a context extension object,
  7648. // the global object, or the subject of a with. Try to delete it
  7649. // (respecting DONT_DELETE).
  7650. Handle<JSObject> object = Handle<JSObject>::cast(holder);
  7651. Handle<Object> result = JSReceiver::DeleteProperty(object, name);
  7652. RETURN_IF_EMPTY_HANDLE(isolate, result);
  7653. return *result;
  7654. }
  7655. // A mechanism to return a pair of Object pointers in registers (if possible).
  7656. // How this is achieved is calling convention-dependent.
  7657. // All currently supported x86 compiles uses calling conventions that are cdecl
  7658. // variants where a 64-bit value is returned in two 32-bit registers
  7659. // (edx:eax on ia32, r1:r0 on ARM).
  7660. // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax.
  7661. // In Win64 calling convention, a struct of two pointers is returned in memory,
  7662. // allocated by the caller, and passed as a pointer in a hidden first parameter.
  7663. #ifdef V8_HOST_ARCH_64_BIT
  7664. struct ObjectPair {
  7665. MaybeObject* x;
  7666. MaybeObject* y;
  7667. };
  7668. static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
  7669. ObjectPair result = {x, y};
  7670. // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
  7671. // In Win64 they are assigned to a hidden first argument.
  7672. return result;
  7673. }
  7674. #else
  7675. typedef uint64_t ObjectPair;
  7676. static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
  7677. return reinterpret_cast<uint32_t>(x) |
  7678. (reinterpret_cast<ObjectPair>(y) << 32);
  7679. }
  7680. #endif
  7681. static inline MaybeObject* Unhole(Heap* heap,
  7682. MaybeObject* x,
  7683. PropertyAttributes attributes) {
  7684. ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
  7685. USE(attributes);
  7686. return x->IsTheHole() ? heap->undefined_value() : x;
  7687. }
  7688. static Object* ComputeReceiverForNonGlobal(Isolate* isolate,
  7689. JSObject* holder) {
  7690. ASSERT(!holder->IsGlobalObject());
  7691. Context* top = isolate->context();
  7692. // Get the context extension function.
  7693. JSFunction* context_extension_function =
  7694. top->native_context()->context_extension_function();
  7695. // If the holder isn't a context extension object, we just return it
  7696. // as the receiver. This allows arguments objects to be used as
  7697. // receivers, but only if they are put in the context scope chain
  7698. // explicitly via a with-statement.
  7699. Object* constructor = holder->map()->constructor();
  7700. if (constructor != context_extension_function) return holder;
  7701. // Fall back to using the global object as the implicit receiver if
  7702. // the property turns out to be a local variable allocated in a
  7703. // context extension object - introduced via eval. Implicit global
  7704. // receivers are indicated with the hole value.
  7705. return isolate->heap()->the_hole_value();
  7706. }
  7707. static ObjectPair LoadContextSlotHelper(Arguments args,
  7708. Isolate* isolate,
  7709. bool throw_error) {
  7710. HandleScope scope(isolate);
  7711. ASSERT_EQ(2, args.length());
  7712. if (!args[0]->IsContext() || !args[1]->IsString()) {
  7713. return MakePair(isolate->ThrowIllegalOperation(), NULL);
  7714. }
  7715. Handle<Context> context = args.at<Context>(0);
  7716. Handle<String> name = args.at<String>(1);
  7717. int index;
  7718. PropertyAttributes attributes;
  7719. ContextLookupFlags flags = FOLLOW_CHAINS;
  7720. BindingFlags binding_flags;
  7721. Handle<Object> holder = context->Lookup(name,
  7722. flags,
  7723. &index,
  7724. &attributes,
  7725. &binding_flags);
  7726. if (isolate->has_pending_exception()) {
  7727. return MakePair(Failure::Exception(), NULL);
  7728. }
  7729. // If the index is non-negative, the slot has been found in a context.
  7730. if (index >= 0) {
  7731. ASSERT(holder->IsContext());
  7732. // If the "property" we were looking for is a local variable, the
  7733. // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
  7734. //
  7735. // Use the hole as the receiver to signal that the receiver is implicit
  7736. // and that the global receiver should be used (as distinguished from an
  7737. // explicit receiver that happens to be a global object).
  7738. Handle<Object> receiver = isolate->factory()->the_hole_value();
  7739. Object* value = Context::cast(*holder)->get(index);
  7740. // Check for uninitialized bindings.
  7741. switch (binding_flags) {
  7742. case MUTABLE_CHECK_INITIALIZED:
  7743. case IMMUTABLE_CHECK_INITIALIZED_HARMONY:
  7744. if (value->IsTheHole()) {
  7745. Handle<Object> reference_error =
  7746. isolate->factory()->NewReferenceError("not_defined",
  7747. HandleVector(&name, 1));
  7748. return MakePair(isolate->Throw(*reference_error), NULL);
  7749. }
  7750. // FALLTHROUGH
  7751. case MUTABLE_IS_INITIALIZED:
  7752. case IMMUTABLE_IS_INITIALIZED:
  7753. case IMMUTABLE_IS_INITIALIZED_HARMONY:
  7754. ASSERT(!value->IsTheHole());
  7755. return MakePair(value, *receiver);
  7756. case IMMUTABLE_CHECK_INITIALIZED:
  7757. return MakePair(Unhole(isolate->heap(), value, attributes), *receiver);
  7758. case MISSING_BINDING:
  7759. UNREACHABLE();
  7760. return MakePair(NULL, NULL);
  7761. }
  7762. }
  7763. // Otherwise, if the slot was found the holder is a context extension
  7764. // object, subject of a with, or a global object. We read the named
  7765. // property from it.
  7766. if (!holder.is_null()) {
  7767. Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
  7768. ASSERT(object->IsJSProxy() || object->HasProperty(*name));
  7769. // GetProperty below can cause GC.
  7770. Handle<Object> receiver_handle(
  7771. object->IsGlobalObject()
  7772. ? GlobalObject::cast(*object)->global_receiver()
  7773. : object->IsJSProxy() ? static_cast<Object*>(*object)
  7774. : ComputeReceiverForNonGlobal(isolate, JSObject::cast(*object)),
  7775. isolate);
  7776. // No need to unhole the value here. This is taken care of by the
  7777. // GetProperty function.
  7778. MaybeObject* value = object->GetProperty(*name);
  7779. return MakePair(value, *receiver_handle);
  7780. }
  7781. if (throw_error) {
  7782. // The property doesn't exist - throw exception.
  7783. Handle<Object> reference_error =
  7784. isolate->factory()->NewReferenceError("not_defined",
  7785. HandleVector(&name, 1));
  7786. return MakePair(isolate->Throw(*reference_error), NULL);
  7787. } else {
  7788. // The property doesn't exist - return undefined.
  7789. return MakePair(isolate->heap()->undefined_value(),
  7790. isolate->heap()->undefined_value());
  7791. }
  7792. }
  7793. RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlot) {
  7794. return LoadContextSlotHelper(args, isolate, true);
  7795. }
  7796. RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlotNoReferenceError) {
  7797. return LoadContextSlotHelper(args, isolate, false);
  7798. }
  7799. RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreContextSlot) {
  7800. HandleScope scope(isolate);
  7801. ASSERT(args.length() == 4);
  7802. Handle<Object> value(args[0], isolate);
  7803. CONVERT_ARG_HANDLE_CHECKED(Context, context, 1);
  7804. CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
  7805. CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
  7806. StrictModeFlag strict_mode = (language_mode == CLASSIC_MODE)
  7807. ? kNonStrictMode : kStrictMode;
  7808. int index;
  7809. PropertyAttributes attributes;
  7810. ContextLookupFlags flags = FOLLOW_CHAINS;
  7811. BindingFlags binding_flags;
  7812. Handle<Object> holder = context->Lookup(name,
  7813. flags,
  7814. &index,
  7815. &attributes,
  7816. &binding_flags);
  7817. if (isolate->has_pending_exception()) return Failure::Exception();
  7818. if (index >= 0) {
  7819. // The property was found in a context slot.
  7820. Handle<Context> context = Handle<Context>::cast(holder);
  7821. if (binding_flags == MUTABLE_CHECK_INITIALIZED &&
  7822. context->get(index)->IsTheHole()) {
  7823. Handle<Object> error =
  7824. isolate->factory()->NewReferenceError("not_defined",
  7825. HandleVector(&name, 1));
  7826. return isolate->Throw(*error);
  7827. }
  7828. // Ignore if read_only variable.
  7829. if ((attributes & READ_ONLY) == 0) {
  7830. // Context is a fixed array and set cannot fail.
  7831. context->set(index, *value);
  7832. } else if (strict_mode == kStrictMode) {
  7833. // Setting read only property in strict mode.
  7834. Handle<Object> error =
  7835. isolate->factory()->NewTypeError("strict_cannot_assign",
  7836. HandleVector(&name, 1));
  7837. return isolate->Throw(*error);
  7838. }
  7839. return *value;
  7840. }
  7841. // Slow case: The property is not in a context slot. It is either in a
  7842. // context extension object, a property of the subject of a with, or a
  7843. // property of the global object.
  7844. Handle<JSReceiver> object;
  7845. if (!holder.is_null()) {
  7846. // The property exists on the holder.
  7847. object = Handle<JSReceiver>::cast(holder);
  7848. } else {
  7849. // The property was not found.
  7850. ASSERT(attributes == ABSENT);
  7851. if (strict_mode == kStrictMode) {
  7852. // Throw in strict mode (assignment to undefined variable).
  7853. Handle<Object> error =
  7854. isolate->factory()->NewReferenceError(
  7855. "not_defined", HandleVector(&name, 1));
  7856. return isolate->Throw(*error);
  7857. }
  7858. // In non-strict mode, the property is added to the global object.
  7859. attributes = NONE;
  7860. object = Handle<JSReceiver>(isolate->context()->global_object());
  7861. }
  7862. // Set the property if it's not read only or doesn't yet exist.
  7863. if ((attributes & READ_ONLY) == 0 ||
  7864. (object->GetLocalPropertyAttribute(*name) == ABSENT)) {
  7865. RETURN_IF_EMPTY_HANDLE(
  7866. isolate,
  7867. JSReceiver::SetProperty(object, name, value, NONE, strict_mode));
  7868. } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) {
  7869. // Setting read only property in strict mode.
  7870. Handle<Object> error =
  7871. isolate->factory()->NewTypeError(
  7872. "strict_cannot_assign", HandleVector(&name, 1));
  7873. return isolate->Throw(*error);
  7874. }
  7875. return *value;
  7876. }
  7877. RUNTIME_FUNCTION(MaybeObject*, Runtime_Throw) {
  7878. HandleScope scope(isolate);
  7879. ASSERT(args.length() == 1);
  7880. return isolate->Throw(args[0]);
  7881. }
  7882. RUNTIME_FUNCTION(MaybeObject*, Runtime_ReThrow) {
  7883. HandleScope scope(isolate);
  7884. ASSERT(args.length() == 1);
  7885. return isolate->ReThrow(args[0]);
  7886. }
  7887. RUNTIME_FUNCTION(MaybeObject*, Runtime_PromoteScheduledException) {
  7888. SealHandleScope shs(isolate);
  7889. ASSERT_EQ(0, args.length());
  7890. return isolate->PromoteScheduledException();
  7891. }
  7892. RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowReferenceError) {
  7893. HandleScope scope(isolate);
  7894. ASSERT(args.length() == 1);
  7895. Handle<Object> name(args[0], isolate);
  7896. Handle<Object> reference_error =
  7897. isolate->factory()->NewReferenceError("not_defined",
  7898. HandleVector(&name, 1));
  7899. return isolate->Throw(*reference_error);
  7900. }
  7901. RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowNotDateError) {
  7902. HandleScope scope(isolate);
  7903. ASSERT(args.length() == 0);
  7904. return isolate->Throw(*isolate->factory()->NewTypeError(
  7905. "not_date_object", HandleVector<Object>(NULL, 0)));
  7906. }
  7907. RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) {
  7908. SealHandleScope shs(isolate);
  7909. ASSERT(args.length() == 0);
  7910. // First check if this is a real stack overflow.
  7911. if (isolate->stack_guard()->IsStackOverflow()) {
  7912. SealHandleScope shs(isolate);
  7913. return isolate->StackOverflow();
  7914. }
  7915. return Execution::HandleStackGuardInterrupt(isolate);
  7916. }
  7917. RUNTIME_FUNCTION(MaybeObject*, Runtime_Interrupt) {
  7918. SealHandleScope shs(isolate);
  7919. ASSERT(args.length() == 0);
  7920. return Execution::HandleStackGuardInterrupt(isolate);
  7921. }
  7922. static int StackSize(Isolate* isolate) {
  7923. int n = 0;
  7924. for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) n++;
  7925. return n;
  7926. }
  7927. static void PrintTransition(Isolate* isolate, Object* result) {
  7928. // indentation
  7929. { const int nmax = 80;
  7930. int n = StackSize(isolate);
  7931. if (n <= nmax)
  7932. PrintF("%4d:%*s", n, n, "");
  7933. else
  7934. PrintF("%4d:%*s", n, nmax, "...");
  7935. }
  7936. if (result == NULL) {
  7937. JavaScriptFrame::PrintTop(isolate, stdout, true, false);
  7938. PrintF(" {\n");
  7939. } else {
  7940. // function result
  7941. PrintF("} -> ");
  7942. result->ShortPrint();
  7943. PrintF("\n");
  7944. }
  7945. }
  7946. RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceEnter) {
  7947. SealHandleScope shs(isolate);
  7948. ASSERT(args.length() == 0);
  7949. PrintTransition(isolate, NULL);
  7950. return isolate->heap()->undefined_value();
  7951. }
  7952. RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceExit) {
  7953. SealHandleScope shs(isolate);
  7954. PrintTransition(isolate, args[0]);
  7955. return args[0]; // return TOS
  7956. }
  7957. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrint) {
  7958. SealHandleScope shs(isolate);
  7959. ASSERT(args.length() == 1);
  7960. #ifdef DEBUG
  7961. if (args[0]->IsString()) {
  7962. // If we have a string, assume it's a code "marker"
  7963. // and print some interesting cpu debugging info.
  7964. JavaScriptFrameIterator it(isolate);
  7965. JavaScriptFrame* frame = it.frame();
  7966. PrintF("fp = %p, sp = %p, caller_sp = %p: ",
  7967. frame->fp(), frame->sp(), frame->caller_sp());
  7968. } else {
  7969. PrintF("DebugPrint: ");
  7970. }
  7971. args[0]->Print();
  7972. if (args[0]->IsHeapObject()) {
  7973. PrintF("\n");
  7974. HeapObject::cast(args[0])->map()->Print();
  7975. }
  7976. #else
  7977. // ShortPrint is available in release mode. Print is not.
  7978. args[0]->ShortPrint();
  7979. #endif
  7980. PrintF("\n");
  7981. Flush();
  7982. return args[0]; // return TOS
  7983. }
  7984. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugTrace) {
  7985. SealHandleScope shs(isolate);
  7986. ASSERT(args.length() == 0);
  7987. isolate->PrintStack(stdout);
  7988. return isolate->heap()->undefined_value();
  7989. }
  7990. RUNTIME_FUNCTION(MaybeObject*, Runtime_DateCurrentTime) {
  7991. SealHandleScope shs(isolate);
  7992. ASSERT(args.length() == 0);
  7993. // According to ECMA-262, section 15.9.1, page 117, the precision of
  7994. // the number in a Date object representing a particular instant in
  7995. // time is milliseconds. Therefore, we floor the result of getting
  7996. // the OS time.
  7997. double millis = floor(OS::TimeCurrentMillis());
  7998. return isolate->heap()->NumberFromDouble(millis);
  7999. }
  8000. RUNTIME_FUNCTION(MaybeObject*, Runtime_DateParseString) {
  8001. HandleScope scope(isolate);
  8002. ASSERT(args.length() == 2);
  8003. CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
  8004. FlattenString(str);
  8005. CONVERT_ARG_HANDLE_CHECKED(JSArray, output, 1);
  8006. MaybeObject* maybe_result_array =
  8007. output->EnsureCanContainHeapObjectElements();
  8008. if (maybe_result_array->IsFailure()) return maybe_result_array;
  8009. RUNTIME_ASSERT(output->HasFastObjectElements());
  8010. DisallowHeapAllocation no_gc;
  8011. FixedArray* output_array = FixedArray::cast(output->elements());
  8012. RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
  8013. bool result;
  8014. String::FlatContent str_content = str->GetFlatContent();
  8015. if (str_content.IsAscii()) {
  8016. result = DateParser::Parse(str_content.ToOneByteVector(),
  8017. output_array,
  8018. isolate->unicode_cache());
  8019. } else {
  8020. ASSERT(str_content.IsTwoByte());
  8021. result = DateParser::Parse(str_content.ToUC16Vector(),
  8022. output_array,
  8023. isolate->unicode_cache());
  8024. }
  8025. if (result) {
  8026. return *output;
  8027. } else {
  8028. return isolate->heap()->null_value();
  8029. }
  8030. }
  8031. RUNTIME_FUNCTION(MaybeObject*, Runtime_DateLocalTimezone) {
  8032. SealHandleScope shs(isolate);
  8033. ASSERT(args.length() == 1);
  8034. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  8035. int64_t time = isolate->date_cache()->EquivalentTime(static_cast<int64_t>(x));
  8036. const char* zone = OS::LocalTimezone(static_cast<double>(time));
  8037. return isolate->heap()->AllocateStringFromUtf8(CStrVector(zone));
  8038. }
  8039. RUNTIME_FUNCTION(MaybeObject*, Runtime_DateToUTC) {
  8040. SealHandleScope shs(isolate);
  8041. ASSERT(args.length() == 1);
  8042. CONVERT_DOUBLE_ARG_CHECKED(x, 0);
  8043. int64_t time = isolate->date_cache()->ToUTC(static_cast<int64_t>(x));
  8044. return isolate->heap()->NumberFromDouble(static_cast<double>(time));
  8045. }
  8046. RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalReceiver) {
  8047. SealHandleScope shs(isolate);
  8048. ASSERT(args.length() == 1);
  8049. Object* global = args[0];
  8050. if (!global->IsJSGlobalObject()) return isolate->heap()->null_value();
  8051. return JSGlobalObject::cast(global)->global_receiver();
  8052. }
  8053. RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) {
  8054. HandleScope scope(isolate);
  8055. ASSERT_EQ(1, args.length());
  8056. CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
  8057. source = Handle<String>(FlattenGetString(source));
  8058. // Optimized fast case where we only have ASCII characters.
  8059. Handle<Object> result;
  8060. if (source->IsSeqOneByteString()) {
  8061. result = JsonParser<true>::Parse(source);
  8062. } else {
  8063. result = JsonParser<false>::Parse(source);
  8064. }
  8065. if (result.is_null()) {
  8066. // Syntax error or stack overflow in scanner.
  8067. ASSERT(isolate->has_pending_exception());
  8068. return Failure::Exception();
  8069. }
  8070. return *result;
  8071. }
  8072. bool CodeGenerationFromStringsAllowed(Isolate* isolate,
  8073. Handle<Context> context) {
  8074. ASSERT(context->allow_code_gen_from_strings()->IsFalse());
  8075. // Check with callback if set.
  8076. AllowCodeGenerationFromStringsCallback callback =
  8077. isolate->allow_code_gen_callback();
  8078. if (callback == NULL) {
  8079. // No callback set and code generation disallowed.
  8080. return false;
  8081. } else {
  8082. // Callback set. Let it decide if code generation is allowed.
  8083. VMState<EXTERNAL> state(isolate);
  8084. return callback(v8::Utils::ToLocal(context));
  8085. }
  8086. }
  8087. RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
  8088. HandleScope scope(isolate);
  8089. ASSERT_EQ(2, args.length());
  8090. CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
  8091. CONVERT_BOOLEAN_ARG_CHECKED(function_literal_only, 1);
  8092. // Extract native context.
  8093. Handle<Context> context(isolate->context()->native_context());
  8094. // Check if native context allows code generation from
  8095. // strings. Throw an exception if it doesn't.
  8096. if (context->allow_code_gen_from_strings()->IsFalse() &&
  8097. !CodeGenerationFromStringsAllowed(isolate, context)) {
  8098. Handle<Object> error_message =
  8099. context->ErrorMessageForCodeGenerationFromStrings();
  8100. return isolate->Throw(*isolate->factory()->NewEvalError(
  8101. "code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
  8102. }
  8103. // Compile source string in the native context.
  8104. ParseRestriction restriction = function_literal_only
  8105. ? ONLY_SINGLE_FUNCTION_LITERAL : NO_PARSE_RESTRICTION;
  8106. Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
  8107. source, context, true, CLASSIC_MODE, restriction, RelocInfo::kNoPosition);
  8108. RETURN_IF_EMPTY_HANDLE(isolate, shared);
  8109. Handle<JSFunction> fun =
  8110. isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
  8111. context,
  8112. NOT_TENURED);
  8113. return *fun;
  8114. }
  8115. static ObjectPair CompileGlobalEval(Isolate* isolate,
  8116. Handle<String> source,
  8117. Handle<Object> receiver,
  8118. LanguageMode language_mode,
  8119. int scope_position) {
  8120. Handle<Context> context = Handle<Context>(isolate->context());
  8121. Handle<Context> native_context = Handle<Context>(context->native_context());
  8122. // Check if native context allows code generation from
  8123. // strings. Throw an exception if it doesn't.
  8124. if (native_context->allow_code_gen_from_strings()->IsFalse() &&
  8125. !CodeGenerationFromStringsAllowed(isolate, native_context)) {
  8126. Handle<Object> error_message =
  8127. native_context->ErrorMessageForCodeGenerationFromStrings();
  8128. isolate->Throw(*isolate->factory()->NewEvalError(
  8129. "code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
  8130. return MakePair(Failure::Exception(), NULL);
  8131. }
  8132. // Deal with a normal eval call with a string argument. Compile it
  8133. // and return the compiled function bound in the local context.
  8134. Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
  8135. source,
  8136. context,
  8137. context->IsNativeContext(),
  8138. language_mode,
  8139. NO_PARSE_RESTRICTION,
  8140. scope_position);
  8141. RETURN_IF_EMPTY_HANDLE_VALUE(isolate, shared,
  8142. MakePair(Failure::Exception(), NULL));
  8143. Handle<JSFunction> compiled =
  8144. isolate->factory()->NewFunctionFromSharedFunctionInfo(
  8145. shared, context, NOT_TENURED);
  8146. return MakePair(*compiled, *receiver);
  8147. }
  8148. RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
  8149. HandleScope scope(isolate);
  8150. ASSERT(args.length() == 5);
  8151. Handle<Object> callee = args.at<Object>(0);
  8152. // If "eval" didn't refer to the original GlobalEval, it's not a
  8153. // direct call to eval.
  8154. // (And even if it is, but the first argument isn't a string, just let
  8155. // execution default to an indirect call to eval, which will also return
  8156. // the first argument without doing anything).
  8157. if (*callee != isolate->native_context()->global_eval_fun() ||
  8158. !args[1]->IsString()) {
  8159. return MakePair(*callee, isolate->heap()->the_hole_value());
  8160. }
  8161. CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
  8162. ASSERT(args[4]->IsSmi());
  8163. return CompileGlobalEval(isolate,
  8164. args.at<String>(1),
  8165. args.at<Object>(2),
  8166. language_mode,
  8167. args.smi_at(4));
  8168. }
  8169. static MaybeObject* Allocate(Isolate* isolate,
  8170. int size,
  8171. AllocationSpace space) {
  8172. // Allocate a block of memory in the given space (filled with a filler).
  8173. // Use as fallback for allocation in generated code when the space
  8174. // is full.
  8175. SealHandleScope shs(isolate);
  8176. RUNTIME_ASSERT(IsAligned(size, kPointerSize));
  8177. RUNTIME_ASSERT(size > 0);
  8178. Heap* heap = isolate->heap();
  8179. RUNTIME_ASSERT(size <= heap->MaxRegularSpaceAllocationSize());
  8180. Object* allocation;
  8181. { MaybeObject* maybe_allocation;
  8182. if (space == NEW_SPACE) {
  8183. maybe_allocation = heap->new_space()->AllocateRaw(size);
  8184. } else {
  8185. ASSERT(space == OLD_POINTER_SPACE || space == OLD_DATA_SPACE);
  8186. maybe_allocation = heap->paged_space(space)->AllocateRaw(size);
  8187. }
  8188. if (maybe_allocation->ToObject(&allocation)) {
  8189. heap->CreateFillerObjectAt(HeapObject::cast(allocation)->address(), size);
  8190. }
  8191. return maybe_allocation;
  8192. }
  8193. }
  8194. RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInNewSpace) {
  8195. SealHandleScope shs(isolate);
  8196. ASSERT(args.length() == 1);
  8197. CONVERT_ARG_HANDLE_CHECKED(Smi, size_smi, 0);
  8198. return Allocate(isolate, size_smi->value(), NEW_SPACE);
  8199. }
  8200. RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInOldPointerSpace) {
  8201. SealHandleScope shs(isolate);
  8202. ASSERT(args.length() == 1);
  8203. CONVERT_ARG_HANDLE_CHECKED(Smi, size_smi, 0);
  8204. return Allocate(isolate, size_smi->value(), OLD_POINTER_SPACE);
  8205. }
  8206. RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInOldDataSpace) {
  8207. SealHandleScope shs(isolate);
  8208. ASSERT(args.length() == 1);
  8209. CONVERT_ARG_HANDLE_CHECKED(Smi, size_smi, 0);
  8210. return Allocate(isolate, size_smi->value(), OLD_DATA_SPACE);
  8211. }
  8212. // Push an object unto an array of objects if it is not already in the
  8213. // array. Returns true if the element was pushed on the stack and
  8214. // false otherwise.
  8215. RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) {
  8216. SealHandleScope shs(isolate);
  8217. ASSERT(args.length() == 2);
  8218. CONVERT_ARG_CHECKED(JSArray, array, 0);
  8219. CONVERT_ARG_CHECKED(JSReceiver, element, 1);
  8220. RUNTIME_ASSERT(array->HasFastSmiOrObjectElements());
  8221. int length = Smi::cast(array->length())->value();
  8222. FixedArray* elements = FixedArray::cast(array->elements());
  8223. for (int i = 0; i < length; i++) {
  8224. if (elements->get(i) == element) return isolate->heap()->false_value();
  8225. }
  8226. Object* obj;
  8227. // Strict not needed. Used for cycle detection in Array join implementation.
  8228. { MaybeObject* maybe_obj =
  8229. array->SetFastElement(length, element, kNonStrictMode, true);
  8230. if (!maybe_obj->ToObject(&obj)) return maybe_obj;
  8231. }
  8232. return isolate->heap()->true_value();
  8233. }
  8234. /**
  8235. * A simple visitor visits every element of Array's.
  8236. * The backend storage can be a fixed array for fast elements case,
  8237. * or a dictionary for sparse array. Since Dictionary is a subtype
  8238. * of FixedArray, the class can be used by both fast and slow cases.
  8239. * The second parameter of the constructor, fast_elements, specifies
  8240. * whether the storage is a FixedArray or Dictionary.
  8241. *
  8242. * An index limit is used to deal with the situation that a result array
  8243. * length overflows 32-bit non-negative integer.
  8244. */
  8245. class ArrayConcatVisitor {
  8246. public:
  8247. ArrayConcatVisitor(Isolate* isolate,
  8248. Handle<FixedArray> storage,
  8249. bool fast_elements) :
  8250. isolate_(isolate),
  8251. storage_(Handle<FixedArray>::cast(
  8252. isolate->global_handles()->Create(*storage))),
  8253. index_offset_(0u),
  8254. fast_elements_(fast_elements),
  8255. exceeds_array_limit_(false) { }
  8256. ~ArrayConcatVisitor() {
  8257. clear_storage();
  8258. }
  8259. void visit(uint32_t i, Handle<Object> elm) {
  8260. if (i > JSObject::kMaxElementCount - index_offset_) {
  8261. exceeds_array_limit_ = true;
  8262. return;
  8263. }
  8264. uint32_t index = index_offset_ + i;
  8265. if (fast_elements_) {
  8266. if (index < static_cast<uint32_t>(storage_->length())) {
  8267. storage_->set(index, *elm);
  8268. return;
  8269. }
  8270. // Our initial estimate of length was foiled, possibly by
  8271. // getters on the arrays increasing the length of later arrays
  8272. // during iteration.
  8273. // This shouldn't happen in anything but pathological cases.
  8274. SetDictionaryMode(index);
  8275. // Fall-through to dictionary mode.
  8276. }
  8277. ASSERT(!fast_elements_);
  8278. Handle<SeededNumberDictionary> dict(
  8279. SeededNumberDictionary::cast(*storage_));
  8280. Handle<SeededNumberDictionary> result =
  8281. isolate_->factory()->DictionaryAtNumberPut(dict, index, elm);
  8282. if (!result.is_identical_to(dict)) {
  8283. // Dictionary needed to grow.
  8284. clear_storage();
  8285. set_storage(*result);
  8286. }
  8287. }
  8288. void increase_index_offset(uint32_t delta) {
  8289. if (JSObject::kMaxElementCount - index_offset_ < delta) {
  8290. index_offset_ = JSObject::kMaxElementCount;
  8291. } else {
  8292. index_offset_ += delta;
  8293. }
  8294. }
  8295. bool exceeds_array_limit() {
  8296. return exceeds_array_limit_;
  8297. }
  8298. Handle<JSArray> ToArray() {
  8299. Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
  8300. Handle<Object> length =
  8301. isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
  8302. Handle<Map> map;
  8303. if (fast_elements_) {
  8304. map = isolate_->factory()->GetElementsTransitionMap(array,
  8305. FAST_HOLEY_ELEMENTS);
  8306. } else {
  8307. map = isolate_->factory()->GetElementsTransitionMap(array,
  8308. DICTIONARY_ELEMENTS);
  8309. }
  8310. array->set_map(*map);
  8311. array->set_length(*length);
  8312. array->set_elements(*storage_);
  8313. return array;
  8314. }
  8315. private:
  8316. // Convert storage to dictionary mode.
  8317. void SetDictionaryMode(uint32_t index) {
  8318. ASSERT(fast_elements_);
  8319. Handle<FixedArray> current_storage(*storage_);
  8320. Handle<SeededNumberDictionary> slow_storage(
  8321. isolate_->factory()->NewSeededNumberDictionary(
  8322. current_storage->length()));
  8323. uint32_t current_length = static_cast<uint32_t>(current_storage->length());
  8324. for (uint32_t i = 0; i < current_length; i++) {
  8325. HandleScope loop_scope(isolate_);
  8326. Handle<Object> element(current_storage->get(i), isolate_);
  8327. if (!element->IsTheHole()) {
  8328. Handle<SeededNumberDictionary> new_storage =
  8329. isolate_->factory()->DictionaryAtNumberPut(slow_storage, i, element);
  8330. if (!new_storage.is_identical_to(slow_storage)) {
  8331. slow_storage = loop_scope.CloseAndEscape(new_storage);
  8332. }
  8333. }
  8334. }
  8335. clear_storage();
  8336. set_storage(*slow_storage);
  8337. fast_elements_ = false;
  8338. }
  8339. inline void clear_storage() {
  8340. isolate_->global_handles()->Destroy(
  8341. Handle<Object>::cast(storage_).location());
  8342. }
  8343. inline void set_storage(FixedArray* storage) {
  8344. storage_ = Handle<FixedArray>::cast(
  8345. isolate_->global_handles()->Create(storage));
  8346. }
  8347. Isolate* isolate_;
  8348. Handle<FixedArray> storage_; // Always a global handle.
  8349. // Index after last seen index. Always less than or equal to
  8350. // JSObject::kMaxElementCount.
  8351. uint32_t index_offset_;
  8352. bool fast_elements_ : 1;
  8353. bool exceeds_array_limit_ : 1;
  8354. };
  8355. static uint32_t EstimateElementCount(Handle<JSArray> array) {
  8356. uint32_t length = static_cast<uint32_t>(array->length()->Number());
  8357. int element_count = 0;
  8358. switch (array->GetElementsKind()) {
  8359. case FAST_SMI_ELEMENTS:
  8360. case FAST_HOLEY_SMI_ELEMENTS:
  8361. case FAST_ELEMENTS:
  8362. case FAST_HOLEY_ELEMENTS: {
  8363. // Fast elements can't have lengths that are not representable by
  8364. // a 32-bit signed integer.
  8365. ASSERT(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
  8366. int fast_length = static_cast<int>(length);
  8367. Handle<FixedArray> elements(FixedArray::cast(array->elements()));
  8368. for (int i = 0; i < fast_length; i++) {
  8369. if (!elements->get(i)->IsTheHole()) element_count++;
  8370. }
  8371. break;
  8372. }
  8373. case FAST_DOUBLE_ELEMENTS:
  8374. case FAST_HOLEY_DOUBLE_ELEMENTS: {
  8375. // Fast elements can't have lengths that are not representable by
  8376. // a 32-bit signed integer.
  8377. ASSERT(static_cast<int32_t>(FixedDoubleArray::kMaxLength) >= 0);
  8378. int fast_length = static_cast<int>(length);
  8379. if (array->elements()->IsFixedArray()) {
  8380. ASSERT(FixedArray::cast(array->elements())->length() == 0);
  8381. break;
  8382. }
  8383. Handle<FixedDoubleArray> elements(
  8384. FixedDoubleArray::cast(array->elements()));
  8385. for (int i = 0; i < fast_length; i++) {
  8386. if (!elements->is_the_hole(i)) element_count++;
  8387. }
  8388. break;
  8389. }
  8390. case DICTIONARY_ELEMENTS: {
  8391. Handle<SeededNumberDictionary> dictionary(
  8392. SeededNumberDictionary::cast(array->elements()));
  8393. int capacity = dictionary->Capacity();
  8394. for (int i = 0; i < capacity; i++) {
  8395. Handle<Object> key(dictionary->KeyAt(i), array->GetIsolate());
  8396. if (dictionary->IsKey(*key)) {
  8397. element_count++;
  8398. }
  8399. }
  8400. break;
  8401. }
  8402. case NON_STRICT_ARGUMENTS_ELEMENTS:
  8403. case EXTERNAL_BYTE_ELEMENTS:
  8404. case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
  8405. case EXTERNAL_SHORT_ELEMENTS:
  8406. case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
  8407. case EXTERNAL_INT_ELEMENTS:
  8408. case EXTERNAL_UNSIGNED_INT_ELEMENTS:
  8409. case EXTERNAL_FLOAT_ELEMENTS:
  8410. case EXTERNAL_DOUBLE_ELEMENTS:
  8411. case EXTERNAL_PIXEL_ELEMENTS:
  8412. // External arrays are always dense.
  8413. return length;
  8414. }
  8415. // As an estimate, we assume that the prototype doesn't contain any
  8416. // inherited elements.
  8417. return element_count;
  8418. }
  8419. template<class ExternalArrayClass, class ElementType>
  8420. static void IterateExternalArrayElements(Isolate* isolate,
  8421. Handle<JSObject> receiver,
  8422. bool elements_are_ints,
  8423. bool elements_are_guaranteed_smis,
  8424. ArrayConcatVisitor* visitor) {
  8425. Handle<ExternalArrayClass> array(
  8426. ExternalArrayClass::cast(receiver->elements()));
  8427. uint32_t len = static_cast<uint32_t>(array->length());
  8428. ASSERT(visitor != NULL);
  8429. if (elements_are_ints) {
  8430. if (elements_are_guaranteed_smis) {
  8431. for (uint32_t j = 0; j < len; j++) {
  8432. HandleScope loop_scope(isolate);
  8433. Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get_scalar(j))),
  8434. isolate);
  8435. visitor->visit(j, e);
  8436. }
  8437. } else {
  8438. for (uint32_t j = 0; j < len; j++) {
  8439. HandleScope loop_scope(isolate);
  8440. int64_t val = static_cast<int64_t>(array->get_scalar(j));
  8441. if (Smi::IsValid(static_cast<intptr_t>(val))) {
  8442. Handle<Smi> e(Smi::FromInt(static_cast<int>(val)), isolate);
  8443. visitor->visit(j, e);
  8444. } else {
  8445. Handle<Object> e =
  8446. isolate->factory()->NewNumber(static_cast<ElementType>(val));
  8447. visitor->visit(j, e);
  8448. }
  8449. }
  8450. }
  8451. } else {
  8452. for (uint32_t j = 0; j < len; j++) {
  8453. HandleScope loop_scope(isolate);
  8454. Handle<Object> e = isolate->factory()->NewNumber(array->get_scalar(j));
  8455. visitor->visit(j, e);
  8456. }
  8457. }
  8458. }
  8459. // Used for sorting indices in a List<uint32_t>.
  8460. static int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
  8461. uint32_t a = *ap;
  8462. uint32_t b = *bp;
  8463. return (a == b) ? 0 : (a < b) ? -1 : 1;
  8464. }
  8465. static void CollectElementIndices(Handle<JSObject> object,
  8466. uint32_t range,
  8467. List<uint32_t>* indices) {
  8468. Isolate* isolate = object->GetIsolate();
  8469. ElementsKind kind = object->GetElementsKind();
  8470. switch (kind) {
  8471. case FAST_SMI_ELEMENTS:
  8472. case FAST_ELEMENTS:
  8473. case FAST_HOLEY_SMI_ELEMENTS:
  8474. case FAST_HOLEY_ELEMENTS: {
  8475. Handle<FixedArray> elements(FixedArray::cast(object->elements()));
  8476. uint32_t length = static_cast<uint32_t>(elements->length());
  8477. if (range < length) length = range;
  8478. for (uint32_t i = 0; i < length; i++) {
  8479. if (!elements->get(i)->IsTheHole()) {
  8480. indices->Add(i);
  8481. }
  8482. }
  8483. break;
  8484. }
  8485. case FAST_HOLEY_DOUBLE_ELEMENTS:
  8486. case FAST_DOUBLE_ELEMENTS: {
  8487. // TODO(1810): Decide if it's worthwhile to implement this.
  8488. UNREACHABLE();
  8489. break;
  8490. }
  8491. case DICTIONARY_ELEMENTS: {
  8492. Handle<SeededNumberDictionary> dict(
  8493. SeededNumberDictionary::cast(object->elements()));
  8494. uint32_t capacity = dict->Capacity();
  8495. for (uint32_t j = 0; j < capacity; j++) {
  8496. HandleScope loop_scope(isolate);
  8497. Handle<Object> k(dict->KeyAt(j), isolate);
  8498. if (dict->IsKey(*k)) {
  8499. ASSERT(k->IsNumber());
  8500. uint32_t index = static_cast<uint32_t>(k->Number());
  8501. if (index < range) {
  8502. indices->Add(index);
  8503. }
  8504. }
  8505. }
  8506. break;
  8507. }
  8508. default: {
  8509. int dense_elements_length;
  8510. switch (kind) {
  8511. case EXTERNAL_PIXEL_ELEMENTS: {
  8512. dense_elements_length =
  8513. ExternalPixelArray::cast(object->elements())->length();
  8514. break;
  8515. }
  8516. case EXTERNAL_BYTE_ELEMENTS: {
  8517. dense_elements_length =
  8518. ExternalByteArray::cast(object->elements())->length();
  8519. break;
  8520. }
  8521. case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
  8522. dense_elements_length =
  8523. ExternalUnsignedByteArray::cast(object->elements())->length();
  8524. break;
  8525. }
  8526. case EXTERNAL_SHORT_ELEMENTS: {
  8527. dense_elements_length =
  8528. ExternalShortArray::cast(object->elements())->length();
  8529. break;
  8530. }
  8531. case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
  8532. dense_elements_length =
  8533. ExternalUnsignedShortArray::cast(object->elements())->length();
  8534. break;
  8535. }
  8536. case EXTERNAL_INT_ELEMENTS: {
  8537. dense_elements_length =
  8538. ExternalIntArray::cast(object->elements())->length();
  8539. break;
  8540. }
  8541. case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
  8542. dense_elements_length =
  8543. ExternalUnsignedIntArray::cast(object->elements())->length();
  8544. break;
  8545. }
  8546. case EXTERNAL_FLOAT_ELEMENTS: {
  8547. dense_elements_length =
  8548. ExternalFloatArray::cast(object->elements())->length();
  8549. break;
  8550. }
  8551. case EXTERNAL_DOUBLE_ELEMENTS: {
  8552. dense_elements_length =
  8553. ExternalDoubleArray::cast(object->elements())->length();
  8554. break;
  8555. }
  8556. default:
  8557. UNREACHABLE();
  8558. dense_elements_length = 0;
  8559. break;
  8560. }
  8561. uint32_t length = static_cast<uint32_t>(dense_elements_length);
  8562. if (range <= length) {
  8563. length = range;
  8564. // We will add all indices, so we might as well clear it first
  8565. // and avoid duplicates.
  8566. indices->Clear();
  8567. }
  8568. for (uint32_t i = 0; i < length; i++) {
  8569. indices->Add(i);
  8570. }
  8571. if (length == range) return; // All indices accounted for already.
  8572. break;
  8573. }
  8574. }
  8575. Handle<Object> prototype(object->GetPrototype(), isolate);
  8576. if (prototype->IsJSObject()) {
  8577. // The prototype will usually have no inherited element indices,
  8578. // but we have to check.
  8579. CollectElementIndices(Handle<JSObject>::cast(prototype), range, indices);
  8580. }
  8581. }
  8582. /**
  8583. * A helper function that visits elements of a JSArray in numerical
  8584. * order.
  8585. *
  8586. * The visitor argument called for each existing element in the array
  8587. * with the element index and the element's value.
  8588. * Afterwards it increments the base-index of the visitor by the array
  8589. * length.
  8590. * Returns false if any access threw an exception, otherwise true.
  8591. */
  8592. static bool IterateElements(Isolate* isolate,
  8593. Handle<JSArray> receiver,
  8594. ArrayConcatVisitor* visitor) {
  8595. uint32_t length = static_cast<uint32_t>(receiver->length()->Number());
  8596. switch (receiver->GetElementsKind()) {
  8597. case FAST_SMI_ELEMENTS:
  8598. case FAST_ELEMENTS:
  8599. case FAST_HOLEY_SMI_ELEMENTS:
  8600. case FAST_HOLEY_ELEMENTS: {
  8601. // Run through the elements FixedArray and use HasElement and GetElement
  8602. // to check the prototype for missing elements.
  8603. Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
  8604. int fast_length = static_cast<int>(length);
  8605. ASSERT(fast_length <= elements->length());
  8606. for (int j = 0; j < fast_length; j++) {
  8607. HandleScope loop_scope(isolate);
  8608. Handle<Object> element_value(elements->get(j), isolate);
  8609. if (!element_value->IsTheHole()) {
  8610. visitor->visit(j, element_value);
  8611. } else if (receiver->HasElement(j)) {
  8612. // Call GetElement on receiver, not its prototype, or getters won't
  8613. // have the correct receiver.
  8614. element_value = Object::GetElement(receiver, j);
  8615. RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
  8616. visitor->visit(j, element_value);
  8617. }
  8618. }
  8619. break;
  8620. }
  8621. case FAST_HOLEY_DOUBLE_ELEMENTS:
  8622. case FAST_DOUBLE_ELEMENTS: {
  8623. // Run through the elements FixedArray and use HasElement and GetElement
  8624. // to check the prototype for missing elements.
  8625. Handle<FixedDoubleArray> elements(
  8626. FixedDoubleArray::cast(receiver->elements()));
  8627. int fast_length = static_cast<int>(length);
  8628. ASSERT(fast_length <= elements->length());
  8629. for (int j = 0; j < fast_length; j++) {
  8630. HandleScope loop_scope(isolate);
  8631. if (!elements->is_the_hole(j)) {
  8632. double double_value = elements->get_scalar(j);
  8633. Handle<Object> element_value =
  8634. isolate->factory()->NewNumber(double_value);
  8635. visitor->visit(j, element_value);
  8636. } else if (receiver->HasElement(j)) {
  8637. // Call GetElement on receiver, not its prototype, or getters won't
  8638. // have the correct receiver.
  8639. Handle<Object> element_value = Object::GetElement(receiver, j);
  8640. RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
  8641. visitor->visit(j, element_value);
  8642. }
  8643. }
  8644. break;
  8645. }
  8646. case DICTIONARY_ELEMENTS: {
  8647. Handle<SeededNumberDictionary> dict(receiver->element_dictionary());
  8648. List<uint32_t> indices(dict->Capacity() / 2);
  8649. // Collect all indices in the object and the prototypes less
  8650. // than length. This might introduce duplicates in the indices list.
  8651. CollectElementIndices(receiver, length, &indices);
  8652. indices.Sort(&compareUInt32);
  8653. int j = 0;
  8654. int n = indices.length();
  8655. while (j < n) {
  8656. HandleScope loop_scope(isolate);
  8657. uint32_t index = indices[j];
  8658. Handle<Object> element = Object::GetElement(receiver, index);
  8659. RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element, false);
  8660. visitor->visit(index, element);
  8661. // Skip to next different index (i.e., omit duplicates).
  8662. do {
  8663. j++;
  8664. } while (j < n && indices[j] == index);
  8665. }
  8666. break;
  8667. }
  8668. case EXTERNAL_PIXEL_ELEMENTS: {
  8669. Handle<ExternalPixelArray> pixels(ExternalPixelArray::cast(
  8670. receiver->elements()));
  8671. for (uint32_t j = 0; j < length; j++) {
  8672. Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate);
  8673. visitor->visit(j, e);
  8674. }
  8675. break;
  8676. }
  8677. case EXTERNAL_BYTE_ELEMENTS: {
  8678. IterateExternalArrayElements<ExternalByteArray, int8_t>(
  8679. isolate, receiver, true, true, visitor);
  8680. break;
  8681. }
  8682. case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
  8683. IterateExternalArrayElements<ExternalUnsignedByteArray, uint8_t>(
  8684. isolate, receiver, true, true, visitor);
  8685. break;
  8686. }
  8687. case EXTERNAL_SHORT_ELEMENTS: {
  8688. IterateExternalArrayElements<ExternalShortArray, int16_t>(
  8689. isolate, receiver, true, true, visitor);
  8690. break;
  8691. }
  8692. case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
  8693. IterateExternalArrayElements<ExternalUnsignedShortArray, uint16_t>(
  8694. isolate, receiver, true, true, visitor);
  8695. break;
  8696. }
  8697. case EXTERNAL_INT_ELEMENTS: {
  8698. IterateExternalArrayElements<ExternalIntArray, int32_t>(
  8699. isolate, receiver, true, false, visitor);
  8700. break;
  8701. }
  8702. case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
  8703. IterateExternalArrayElements<ExternalUnsignedIntArray, uint32_t>(
  8704. isolate, receiver, true, false, visitor);
  8705. break;
  8706. }
  8707. case EXTERNAL_FLOAT_ELEMENTS: {
  8708. IterateExternalArrayElements<ExternalFloatArray, float>(
  8709. isolate, receiver, false, false, visitor);
  8710. break;
  8711. }
  8712. case EXTERNAL_DOUBLE_ELEMENTS: {
  8713. IterateExternalArrayElements<ExternalDoubleArray, double>(
  8714. isolate, receiver, false, false, visitor);
  8715. break;
  8716. }
  8717. default:
  8718. UNREACHABLE();
  8719. break;
  8720. }
  8721. visitor->increase_index_offset(length);
  8722. return true;
  8723. }
  8724. /**
  8725. * Array::concat implementation.
  8726. * See ECMAScript 262, 15.4.4.4.
  8727. * TODO(581): Fix non-compliance for very large concatenations and update to
  8728. * following the ECMAScript 5 specification.
  8729. */
  8730. RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) {
  8731. HandleScope handle_scope(isolate);
  8732. ASSERT(args.length() == 1);
  8733. CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 0);
  8734. int argument_count = static_cast<int>(arguments->length()->Number());
  8735. RUNTIME_ASSERT(arguments->HasFastObjectElements());
  8736. Handle<FixedArray> elements(FixedArray::cast(arguments->elements()));
  8737. // Pass 1: estimate the length and number of elements of the result.
  8738. // The actual length can be larger if any of the arguments have getters
  8739. // that mutate other arguments (but will otherwise be precise).
  8740. // The number of elements is precise if there are no inherited elements.
  8741. ElementsKind kind = FAST_SMI_ELEMENTS;
  8742. uint32_t estimate_result_length = 0;
  8743. uint32_t estimate_nof_elements = 0;
  8744. for (int i = 0; i < argument_count; i++) {
  8745. HandleScope loop_scope(isolate);
  8746. Handle<Object> obj(elements->get(i), isolate);
  8747. uint32_t length_estimate;
  8748. uint32_t element_estimate;
  8749. if (obj->IsJSArray()) {
  8750. Handle<JSArray> array(Handle<JSArray>::cast(obj));
  8751. length_estimate = static_cast<uint32_t>(array->length()->Number());
  8752. if (length_estimate != 0) {
  8753. ElementsKind array_kind =
  8754. GetPackedElementsKind(array->map()->elements_kind());
  8755. if (IsMoreGeneralElementsKindTransition(kind, array_kind)) {
  8756. kind = array_kind;
  8757. }
  8758. }
  8759. element_estimate = EstimateElementCount(array);
  8760. } else {
  8761. if (obj->IsHeapObject()) {
  8762. if (obj->IsNumber()) {
  8763. if (IsMoreGeneralElementsKindTransition(kind, FAST_DOUBLE_ELEMENTS)) {
  8764. kind = FAST_DOUBLE_ELEMENTS;
  8765. }
  8766. } else if (IsMoreGeneralElementsKindTransition(kind, FAST_ELEMENTS)) {
  8767. kind = FAST_ELEMENTS;
  8768. }
  8769. }
  8770. length_estimate = 1;
  8771. element_estimate = 1;
  8772. }
  8773. // Avoid overflows by capping at kMaxElementCount.
  8774. if (JSObject::kMaxElementCount - estimate_result_length <
  8775. length_estimate) {
  8776. estimate_result_length = JSObject::kMaxElementCount;
  8777. } else {
  8778. estimate_result_length += length_estimate;
  8779. }
  8780. if (JSObject::kMaxElementCount - estimate_nof_elements <
  8781. element_estimate) {
  8782. estimate_nof_elements = JSObject::kMaxElementCount;
  8783. } else {
  8784. estimate_nof_elements += element_estimate;
  8785. }
  8786. }
  8787. // If estimated number of elements is more than half of length, a
  8788. // fixed array (fast case) is more time and space-efficient than a
  8789. // dictionary.
  8790. bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length;
  8791. Handle<FixedArray> storage;
  8792. if (fast_case) {
  8793. if (kind == FAST_DOUBLE_ELEMENTS) {
  8794. Handle<FixedDoubleArray> double_storage =
  8795. isolate->factory()->NewFixedDoubleArray(estimate_result_length);
  8796. int j = 0;
  8797. bool failure = false;
  8798. for (int i = 0; i < argument_count; i++) {
  8799. Handle<Object> obj(elements->get(i), isolate);
  8800. if (obj->IsSmi()) {
  8801. double_storage->set(j, Smi::cast(*obj)->value());
  8802. j++;
  8803. } else if (obj->IsNumber()) {
  8804. double_storage->set(j, obj->Number());
  8805. j++;
  8806. } else {
  8807. JSArray* array = JSArray::cast(*obj);
  8808. uint32_t length = static_cast<uint32_t>(array->length()->Number());
  8809. switch (array->map()->elements_kind()) {
  8810. case FAST_HOLEY_DOUBLE_ELEMENTS:
  8811. case FAST_DOUBLE_ELEMENTS: {
  8812. // Empty fixed array indicates that there are no elements.
  8813. if (array->elements()->IsFixedArray()) break;
  8814. FixedDoubleArray* elements =
  8815. FixedDoubleArray::cast(array->elements());
  8816. for (uint32_t i = 0; i < length; i++) {
  8817. if (elements->is_the_hole(i)) {
  8818. failure = true;
  8819. break;
  8820. }
  8821. double double_value = elements->get_scalar(i);
  8822. double_storage->set(j, double_value);
  8823. j++;
  8824. }
  8825. break;
  8826. }
  8827. case FAST_HOLEY_SMI_ELEMENTS:
  8828. case FAST_SMI_ELEMENTS: {
  8829. FixedArray* elements(
  8830. FixedArray::cast(array->elements()));
  8831. for (uint32_t i = 0; i < length; i++) {
  8832. Object* element = elements->get(i);
  8833. if (element->IsTheHole()) {
  8834. failure = true;
  8835. break;
  8836. }
  8837. int32_t int_value = Smi::cast(element)->value();
  8838. double_storage->set(j, int_value);
  8839. j++;
  8840. }
  8841. break;
  8842. }
  8843. case FAST_HOLEY_ELEMENTS:
  8844. ASSERT_EQ(0, length);
  8845. break;
  8846. default:
  8847. UNREACHABLE();
  8848. }
  8849. }
  8850. if (failure) break;
  8851. }
  8852. Handle<JSArray> array = isolate->factory()->NewJSArray(0);
  8853. Smi* length = Smi::FromInt(j);
  8854. Handle<Map> map;
  8855. map = isolate->factory()->GetElementsTransitionMap(array, kind);
  8856. array->set_map(*map);
  8857. array->set_length(length);
  8858. array->set_elements(*double_storage);
  8859. return *array;
  8860. }
  8861. // The backing storage array must have non-existing elements to preserve
  8862. // holes across concat operations.
  8863. storage = isolate->factory()->NewFixedArrayWithHoles(
  8864. estimate_result_length);
  8865. } else {
  8866. // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
  8867. uint32_t at_least_space_for = estimate_nof_elements +
  8868. (estimate_nof_elements >> 2);
  8869. storage = Handle<FixedArray>::cast(
  8870. isolate->factory()->NewSeededNumberDictionary(at_least_space_for));
  8871. }
  8872. ArrayConcatVisitor visitor(isolate, storage, fast_case);
  8873. for (int i = 0; i < argument_count; i++) {
  8874. Handle<Object> obj(elements->get(i), isolate);
  8875. if (obj->IsJSArray()) {
  8876. Handle<JSArray> array = Handle<JSArray>::cast(obj);
  8877. if (!IterateElements(isolate, array, &visitor)) {
  8878. return Failure::Exception();
  8879. }
  8880. } else {
  8881. visitor.visit(0, obj);
  8882. visitor.increase_index_offset(1);
  8883. }
  8884. }
  8885. if (visitor.exceeds_array_limit()) {
  8886. return isolate->Throw(
  8887. *isolate->factory()->NewRangeError("invalid_array_length",
  8888. HandleVector<Object>(NULL, 0)));
  8889. }
  8890. return *visitor.ToArray();
  8891. }
  8892. // This will not allocate (flatten the string), but it may run
  8893. // very slowly for very deeply nested ConsStrings. For debugging use only.
  8894. RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalPrint) {
  8895. SealHandleScope shs(isolate);
  8896. ASSERT(args.length() == 1);
  8897. CONVERT_ARG_CHECKED(String, string, 0);
  8898. ConsStringIteratorOp op;
  8899. StringCharacterStream stream(string, &op);
  8900. while (stream.HasMore()) {
  8901. uint16_t character = stream.GetNext();
  8902. PrintF("%c", character);
  8903. }
  8904. return string;
  8905. }
  8906. // Moves all own elements of an object, that are below a limit, to positions
  8907. // starting at zero. All undefined values are placed after non-undefined values,
  8908. // and are followed by non-existing element. Does not change the length
  8909. // property.
  8910. // Returns the number of non-undefined elements collected.
  8911. RUNTIME_FUNCTION(MaybeObject*, Runtime_RemoveArrayHoles) {
  8912. SealHandleScope shs(isolate);
  8913. ASSERT(args.length() == 2);
  8914. CONVERT_ARG_CHECKED(JSObject, object, 0);
  8915. CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
  8916. return object->PrepareElementsForSort(limit);
  8917. }
  8918. // Move contents of argument 0 (an array) to argument 1 (an array)
  8919. RUNTIME_FUNCTION(MaybeObject*, Runtime_MoveArrayContents) {
  8920. SealHandleScope shs(isolate);
  8921. ASSERT(args.length() == 2);
  8922. CONVERT_ARG_CHECKED(JSArray, from, 0);
  8923. CONVERT_ARG_CHECKED(JSArray, to, 1);
  8924. from->ValidateElements();
  8925. to->ValidateElements();
  8926. FixedArrayBase* new_elements = from->elements();
  8927. ElementsKind from_kind = from->GetElementsKind();
  8928. MaybeObject* maybe_new_map;
  8929. maybe_new_map = to->GetElementsTransitionMap(isolate, from_kind);
  8930. Object* new_map;
  8931. if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
  8932. to->set_map_and_elements(Map::cast(new_map), new_elements);
  8933. to->set_length(from->length());
  8934. Object* obj;
  8935. { MaybeObject* maybe_obj = from->ResetElements();
  8936. if (!maybe_obj->ToObject(&obj)) return maybe_obj;
  8937. }
  8938. from->set_length(Smi::FromInt(0));
  8939. to->ValidateElements();
  8940. return to;
  8941. }
  8942. // How many elements does this object/array have?
  8943. RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) {
  8944. SealHandleScope shs(isolate);
  8945. ASSERT(args.length() == 1);
  8946. CONVERT_ARG_CHECKED(JSObject, object, 0);
  8947. HeapObject* elements = object->elements();
  8948. if (elements->IsDictionary()) {
  8949. int result = SeededNumberDictionary::cast(elements)->NumberOfElements();
  8950. return Smi::FromInt(result);
  8951. } else if (object->IsJSArray()) {
  8952. return JSArray::cast(object)->length();
  8953. } else {
  8954. return Smi::FromInt(FixedArray::cast(elements)->length());
  8955. }
  8956. }
  8957. // Returns an array that tells you where in the [0, length) interval an array
  8958. // might have elements. Can either return an array of keys (positive integers
  8959. // or undefined) or a number representing the positive length of an interval
  8960. // starting at index 0.
  8961. // Intervals can span over some keys that are not in the object.
  8962. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
  8963. HandleScope scope(isolate);
  8964. ASSERT(args.length() == 2);
  8965. CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
  8966. CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
  8967. if (array->elements()->IsDictionary()) {
  8968. Handle<FixedArray> keys = isolate->factory()->empty_fixed_array();
  8969. for (Handle<Object> p = array;
  8970. !p->IsNull();
  8971. p = Handle<Object>(p->GetPrototype(isolate), isolate)) {
  8972. if (p->IsJSProxy() || JSObject::cast(*p)->HasIndexedInterceptor()) {
  8973. // Bail out if we find a proxy or interceptor, likely not worth
  8974. // collecting keys in that case.
  8975. return *isolate->factory()->NewNumberFromUint(length);
  8976. }
  8977. Handle<JSObject> current = Handle<JSObject>::cast(p);
  8978. Handle<FixedArray> current_keys =
  8979. isolate->factory()->NewFixedArray(
  8980. current->NumberOfLocalElements(NONE));
  8981. current->GetLocalElementKeys(*current_keys, NONE);
  8982. keys = UnionOfKeys(keys, current_keys);
  8983. }
  8984. // Erase any keys >= length.
  8985. // TODO(adamk): Remove this step when the contract of %GetArrayKeys
  8986. // is changed to let this happen on the JS side.
  8987. for (int i = 0; i < keys->length(); i++) {
  8988. if (NumberToUint32(keys->get(i)) >= length) keys->set_undefined(i);
  8989. }
  8990. return *isolate->factory()->NewJSArrayWithElements(keys);
  8991. } else {
  8992. ASSERT(array->HasFastSmiOrObjectElements() ||
  8993. array->HasFastDoubleElements());
  8994. uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
  8995. return *isolate->factory()->NewNumberFromUint(Min(actual_length, length));
  8996. }
  8997. }
  8998. RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) {
  8999. SealHandleScope shs(isolate);
  9000. ASSERT(args.length() == 3);
  9001. CONVERT_ARG_CHECKED(JSReceiver, receiver, 0);
  9002. CONVERT_ARG_CHECKED(Name, name, 1);
  9003. CONVERT_SMI_ARG_CHECKED(flag, 2);
  9004. AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
  9005. if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
  9006. return JSObject::cast(receiver)->LookupAccessor(name, component);
  9007. }
  9008. #ifdef ENABLE_DEBUGGER_SUPPORT
  9009. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugBreak) {
  9010. SealHandleScope shs(isolate);
  9011. ASSERT(args.length() == 0);
  9012. return Execution::DebugBreakHelper();
  9013. }
  9014. // Helper functions for wrapping and unwrapping stack frame ids.
  9015. static Smi* WrapFrameId(StackFrame::Id id) {
  9016. ASSERT(IsAligned(OffsetFrom(id), static_cast<intptr_t>(4)));
  9017. return Smi::FromInt(id >> 2);
  9018. }
  9019. static StackFrame::Id UnwrapFrameId(int wrapped) {
  9020. return static_cast<StackFrame::Id>(wrapped << 2);
  9021. }
  9022. // Adds a JavaScript function as a debug event listener.
  9023. // args[0]: debug event listener function to set or null or undefined for
  9024. // clearing the event listener function
  9025. // args[1]: object supplied during callback
  9026. RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDebugEventListener) {
  9027. SealHandleScope shs(isolate);
  9028. ASSERT(args.length() == 2);
  9029. RUNTIME_ASSERT(args[0]->IsJSFunction() ||
  9030. args[0]->IsUndefined() ||
  9031. args[0]->IsNull());
  9032. Handle<Object> callback = args.at<Object>(0);
  9033. Handle<Object> data = args.at<Object>(1);
  9034. isolate->debugger()->SetEventListener(callback, data);
  9035. return isolate->heap()->undefined_value();
  9036. }
  9037. RUNTIME_FUNCTION(MaybeObject*, Runtime_Break) {
  9038. SealHandleScope shs(isolate);
  9039. ASSERT(args.length() == 0);
  9040. isolate->stack_guard()->DebugBreak();
  9041. return isolate->heap()->undefined_value();
  9042. }
  9043. static MaybeObject* DebugLookupResultValue(Heap* heap,
  9044. Object* receiver,
  9045. Name* name,
  9046. LookupResult* result,
  9047. bool* caught_exception) {
  9048. Object* value;
  9049. switch (result->type()) {
  9050. case NORMAL:
  9051. value = result->holder()->GetNormalizedProperty(result);
  9052. if (value->IsTheHole()) {
  9053. return heap->undefined_value();
  9054. }
  9055. return value;
  9056. case FIELD: {
  9057. Object* value;
  9058. MaybeObject* maybe_value =
  9059. JSObject::cast(result->holder())->FastPropertyAt(
  9060. result->representation(),
  9061. result->GetFieldIndex().field_index());
  9062. if (!maybe_value->To(&value)) return maybe_value;
  9063. if (value->IsTheHole()) {
  9064. return heap->undefined_value();
  9065. }
  9066. return value;
  9067. }
  9068. case CONSTANT:
  9069. return result->GetConstant();
  9070. case CALLBACKS: {
  9071. Object* structure = result->GetCallbackObject();
  9072. if (structure->IsForeign() || structure->IsAccessorInfo()) {
  9073. MaybeObject* maybe_value = result->holder()->GetPropertyWithCallback(
  9074. receiver, structure, name);
  9075. if (!maybe_value->ToObject(&value)) {
  9076. if (maybe_value->IsRetryAfterGC()) return maybe_value;
  9077. ASSERT(maybe_value->IsException());
  9078. maybe_value = heap->isolate()->pending_exception();
  9079. heap->isolate()->clear_pending_exception();
  9080. if (caught_exception != NULL) {
  9081. *caught_exception = true;
  9082. }
  9083. return maybe_value;
  9084. }
  9085. return value;
  9086. } else {
  9087. return heap->undefined_value();
  9088. }
  9089. }
  9090. case INTERCEPTOR:
  9091. case TRANSITION:
  9092. return heap->undefined_value();
  9093. case HANDLER:
  9094. case NONEXISTENT:
  9095. UNREACHABLE();
  9096. return heap->undefined_value();
  9097. }
  9098. UNREACHABLE(); // keep the compiler happy
  9099. return heap->undefined_value();
  9100. }
  9101. // Get debugger related details for an object property.
  9102. // args[0]: object holding property
  9103. // args[1]: name of the property
  9104. //
  9105. // The array returned contains the following information:
  9106. // 0: Property value
  9107. // 1: Property details
  9108. // 2: Property value is exception
  9109. // 3: Getter function if defined
  9110. // 4: Setter function if defined
  9111. // Items 2-4 are only filled if the property has either a getter or a setter
  9112. // defined through __defineGetter__ and/or __defineSetter__.
  9113. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) {
  9114. HandleScope scope(isolate);
  9115. ASSERT(args.length() == 2);
  9116. CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
  9117. CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
  9118. // Make sure to set the current context to the context before the debugger was
  9119. // entered (if the debugger is entered). The reason for switching context here
  9120. // is that for some property lookups (accessors and interceptors) callbacks
  9121. // into the embedding application can occour, and the embedding application
  9122. // could have the assumption that its own native context is the current
  9123. // context and not some internal debugger context.
  9124. SaveContext save(isolate);
  9125. if (isolate->debug()->InDebugger()) {
  9126. isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
  9127. }
  9128. // Skip the global proxy as it has no properties and always delegates to the
  9129. // real global object.
  9130. if (obj->IsJSGlobalProxy()) {
  9131. obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
  9132. }
  9133. // Check if the name is trivially convertible to an index and get the element
  9134. // if so.
  9135. uint32_t index;
  9136. if (name->AsArrayIndex(&index)) {
  9137. Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
  9138. Object* element_or_char;
  9139. { MaybeObject* maybe_element_or_char =
  9140. Runtime::GetElementOrCharAt(isolate, obj, index);
  9141. if (!maybe_element_or_char->ToObject(&element_or_char)) {
  9142. return maybe_element_or_char;
  9143. }
  9144. }
  9145. details->set(0, element_or_char);
  9146. details->set(
  9147. 1, PropertyDetails(NONE, NORMAL, Representation::None()).AsSmi());
  9148. return *isolate->factory()->NewJSArrayWithElements(details);
  9149. }
  9150. // Find the number of objects making up this.
  9151. int length = LocalPrototypeChainLength(*obj);
  9152. // Try local lookup on each of the objects.
  9153. Handle<JSObject> jsproto = obj;
  9154. for (int i = 0; i < length; i++) {
  9155. LookupResult result(isolate);
  9156. jsproto->LocalLookup(*name, &result);
  9157. if (result.IsFound()) {
  9158. // LookupResult is not GC safe as it holds raw object pointers.
  9159. // GC can happen later in this code so put the required fields into
  9160. // local variables using handles when required for later use.
  9161. Handle<Object> result_callback_obj;
  9162. if (result.IsPropertyCallbacks()) {
  9163. result_callback_obj = Handle<Object>(result.GetCallbackObject(),
  9164. isolate);
  9165. }
  9166. Smi* property_details = result.GetPropertyDetails().AsSmi();
  9167. // DebugLookupResultValue can cause GC so details from LookupResult needs
  9168. // to be copied to handles before this.
  9169. bool caught_exception = false;
  9170. Object* raw_value;
  9171. { MaybeObject* maybe_raw_value =
  9172. DebugLookupResultValue(isolate->heap(), *obj, *name,
  9173. &result, &caught_exception);
  9174. if (!maybe_raw_value->ToObject(&raw_value)) return maybe_raw_value;
  9175. }
  9176. Handle<Object> value(raw_value, isolate);
  9177. // If the callback object is a fixed array then it contains JavaScript
  9178. // getter and/or setter.
  9179. bool hasJavaScriptAccessors = result.IsPropertyCallbacks() &&
  9180. result_callback_obj->IsAccessorPair();
  9181. Handle<FixedArray> details =
  9182. isolate->factory()->NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
  9183. details->set(0, *value);
  9184. details->set(1, property_details);
  9185. if (hasJavaScriptAccessors) {
  9186. AccessorPair* accessors = AccessorPair::cast(*result_callback_obj);
  9187. details->set(2, isolate->heap()->ToBoolean(caught_exception));
  9188. details->set(3, accessors->GetComponent(ACCESSOR_GETTER));
  9189. details->set(4, accessors->GetComponent(ACCESSOR_SETTER));
  9190. }
  9191. return *isolate->factory()->NewJSArrayWithElements(details);
  9192. }
  9193. if (i < length - 1) {
  9194. jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
  9195. }
  9196. }
  9197. return isolate->heap()->undefined_value();
  9198. }
  9199. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetProperty) {
  9200. HandleScope scope(isolate);
  9201. ASSERT(args.length() == 2);
  9202. CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
  9203. CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
  9204. LookupResult result(isolate);
  9205. obj->Lookup(*name, &result);
  9206. if (result.IsFound()) {
  9207. return DebugLookupResultValue(isolate->heap(), *obj, *name, &result, NULL);
  9208. }
  9209. return isolate->heap()->undefined_value();
  9210. }
  9211. // Return the property type calculated from the property details.
  9212. // args[0]: smi with property details.
  9213. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyTypeFromDetails) {
  9214. SealHandleScope shs(isolate);
  9215. ASSERT(args.length() == 1);
  9216. CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
  9217. return Smi::FromInt(static_cast<int>(details.type()));
  9218. }
  9219. // Return the property attribute calculated from the property details.
  9220. // args[0]: smi with property details.
  9221. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyAttributesFromDetails) {
  9222. SealHandleScope shs(isolate);
  9223. ASSERT(args.length() == 1);
  9224. CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
  9225. return Smi::FromInt(static_cast<int>(details.attributes()));
  9226. }
  9227. // Return the property insertion index calculated from the property details.
  9228. // args[0]: smi with property details.
  9229. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyIndexFromDetails) {
  9230. SealHandleScope shs(isolate);
  9231. ASSERT(args.length() == 1);
  9232. CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
  9233. // TODO(verwaest): Depends on the type of details.
  9234. return Smi::FromInt(details.dictionary_index());
  9235. }
  9236. // Return property value from named interceptor.
  9237. // args[0]: object
  9238. // args[1]: property name
  9239. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugNamedInterceptorPropertyValue) {
  9240. HandleScope scope(isolate);
  9241. ASSERT(args.length() == 2);
  9242. CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
  9243. RUNTIME_ASSERT(obj->HasNamedInterceptor());
  9244. CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
  9245. PropertyAttributes attributes;
  9246. return obj->GetPropertyWithInterceptor(*obj, *name, &attributes);
  9247. }
  9248. // Return element value from indexed interceptor.
  9249. // args[0]: object
  9250. // args[1]: index
  9251. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugIndexedInterceptorElementValue) {
  9252. HandleScope scope(isolate);
  9253. ASSERT(args.length() == 2);
  9254. CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
  9255. RUNTIME_ASSERT(obj->HasIndexedInterceptor());
  9256. CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
  9257. return obj->GetElementWithInterceptor(*obj, index);
  9258. }
  9259. RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckExecutionState) {
  9260. SealHandleScope shs(isolate);
  9261. ASSERT(args.length() >= 1);
  9262. CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
  9263. // Check that the break id is valid.
  9264. if (isolate->debug()->break_id() == 0 ||
  9265. break_id != isolate->debug()->break_id()) {
  9266. return isolate->Throw(
  9267. isolate->heap()->illegal_execution_state_string());
  9268. }
  9269. return isolate->heap()->true_value();
  9270. }
  9271. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) {
  9272. HandleScope scope(isolate);
  9273. ASSERT(args.length() == 1);
  9274. // Check arguments.
  9275. Object* result;
  9276. { MaybeObject* maybe_result = Runtime_CheckExecutionState(
  9277. RUNTIME_ARGUMENTS(isolate, args));
  9278. if (!maybe_result->ToObject(&result)) return maybe_result;
  9279. }
  9280. // Count all frames which are relevant to debugging stack trace.
  9281. int n = 0;
  9282. StackFrame::Id id = isolate->debug()->break_frame_id();
  9283. if (id == StackFrame::NO_ID) {
  9284. // If there is no JavaScript stack frame count is 0.
  9285. return Smi::FromInt(0);
  9286. }
  9287. for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) {
  9288. n += it.frame()->GetInlineCount();
  9289. }
  9290. return Smi::FromInt(n);
  9291. }
  9292. class FrameInspector {
  9293. public:
  9294. FrameInspector(JavaScriptFrame* frame,
  9295. int inlined_jsframe_index,
  9296. Isolate* isolate)
  9297. : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
  9298. // Calculate the deoptimized frame.
  9299. if (frame->is_optimized()) {
  9300. deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
  9301. frame, inlined_jsframe_index, isolate);
  9302. }
  9303. has_adapted_arguments_ = frame_->has_adapted_arguments();
  9304. is_bottommost_ = inlined_jsframe_index == 0;
  9305. is_optimized_ = frame_->is_optimized();
  9306. }
  9307. ~FrameInspector() {
  9308. // Get rid of the calculated deoptimized frame if any.
  9309. if (deoptimized_frame_ != NULL) {
  9310. Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_,
  9311. isolate_);
  9312. }
  9313. }
  9314. int GetParametersCount() {
  9315. return is_optimized_
  9316. ? deoptimized_frame_->parameters_count()
  9317. : frame_->ComputeParametersCount();
  9318. }
  9319. int expression_count() { return deoptimized_frame_->expression_count(); }
  9320. Object* GetFunction() {
  9321. return is_optimized_
  9322. ? deoptimized_frame_->GetFunction()
  9323. : frame_->function();
  9324. }
  9325. Object* GetParameter(int index) {
  9326. return is_optimized_
  9327. ? deoptimized_frame_->GetParameter(index)
  9328. : frame_->GetParameter(index);
  9329. }
  9330. Object* GetExpression(int index) {
  9331. return is_optimized_
  9332. ? deoptimized_frame_->GetExpression(index)
  9333. : frame_->GetExpression(index);
  9334. }
  9335. int GetSourcePosition() {
  9336. return is_optimized_
  9337. ? deoptimized_frame_->GetSourcePosition()
  9338. : frame_->LookupCode()->SourcePosition(frame_->pc());
  9339. }
  9340. bool IsConstructor() {
  9341. return is_optimized_ && !is_bottommost_
  9342. ? deoptimized_frame_->HasConstructStub()
  9343. : frame_->IsConstructor();
  9344. }
  9345. // To inspect all the provided arguments the frame might need to be
  9346. // replaced with the arguments frame.
  9347. void SetArgumentsFrame(JavaScriptFrame* frame) {
  9348. ASSERT(has_adapted_arguments_);
  9349. frame_ = frame;
  9350. is_optimized_ = frame_->is_optimized();
  9351. ASSERT(!is_optimized_);
  9352. }
  9353. private:
  9354. JavaScriptFrame* frame_;
  9355. DeoptimizedFrameInfo* deoptimized_frame_;
  9356. Isolate* isolate_;
  9357. bool is_optimized_;
  9358. bool is_bottommost_;
  9359. bool has_adapted_arguments_;
  9360. DISALLOW_COPY_AND_ASSIGN(FrameInspector);
  9361. };
  9362. static const int kFrameDetailsFrameIdIndex = 0;
  9363. static const int kFrameDetailsReceiverIndex = 1;
  9364. static const int kFrameDetailsFunctionIndex = 2;
  9365. static const int kFrameDetailsArgumentCountIndex = 3;
  9366. static const int kFrameDetailsLocalCountIndex = 4;
  9367. static const int kFrameDetailsSourcePositionIndex = 5;
  9368. static const int kFrameDetailsConstructCallIndex = 6;
  9369. static const int kFrameDetailsAtReturnIndex = 7;
  9370. static const int kFrameDetailsFlagsIndex = 8;
  9371. static const int kFrameDetailsFirstDynamicIndex = 9;
  9372. static SaveContext* FindSavedContextForFrame(Isolate* isolate,
  9373. JavaScriptFrame* frame) {
  9374. SaveContext* save = isolate->save_context();
  9375. while (save != NULL && !save->IsBelowFrame(frame)) {
  9376. save = save->prev();
  9377. }
  9378. ASSERT(save != NULL);
  9379. return save;
  9380. }
  9381. // Return an array with frame details
  9382. // args[0]: number: break id
  9383. // args[1]: number: frame index
  9384. //
  9385. // The array returned contains the following information:
  9386. // 0: Frame id
  9387. // 1: Receiver
  9388. // 2: Function
  9389. // 3: Argument count
  9390. // 4: Local count
  9391. // 5: Source position
  9392. // 6: Constructor call
  9393. // 7: Is at return
  9394. // 8: Flags
  9395. // Arguments name, value
  9396. // Locals name, value
  9397. // Return value if any
  9398. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
  9399. HandleScope scope(isolate);
  9400. ASSERT(args.length() == 2);
  9401. // Check arguments.
  9402. Object* check;
  9403. { MaybeObject* maybe_check = Runtime_CheckExecutionState(
  9404. RUNTIME_ARGUMENTS(isolate, args));
  9405. if (!maybe_check->ToObject(&check)) return maybe_check;
  9406. }
  9407. CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
  9408. Heap* heap = isolate->heap();
  9409. // Find the relevant frame with the requested index.
  9410. StackFrame::Id id = isolate->debug()->break_frame_id();
  9411. if (id == StackFrame::NO_ID) {
  9412. // If there are no JavaScript stack frames return undefined.
  9413. return heap->undefined_value();
  9414. }
  9415. int count = 0;
  9416. JavaScriptFrameIterator it(isolate, id);
  9417. for (; !it.done(); it.Advance()) {
  9418. if (index < count + it.frame()->GetInlineCount()) break;
  9419. count += it.frame()->GetInlineCount();
  9420. }
  9421. if (it.done()) return heap->undefined_value();
  9422. bool is_optimized = it.frame()->is_optimized();
  9423. int inlined_jsframe_index = 0; // Inlined frame index in optimized frame.
  9424. if (is_optimized) {
  9425. inlined_jsframe_index =
  9426. it.frame()->GetInlineCount() - (index - count) - 1;
  9427. }
  9428. FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate);
  9429. // Traverse the saved contexts chain to find the active context for the
  9430. // selected frame.
  9431. SaveContext* save = FindSavedContextForFrame(isolate, it.frame());
  9432. // Get the frame id.
  9433. Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate);
  9434. // Find source position in unoptimized code.
  9435. int position = frame_inspector.GetSourcePosition();
  9436. // Check for constructor frame.
  9437. bool constructor = frame_inspector.IsConstructor();
  9438. // Get scope info and read from it for local variable information.
  9439. Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
  9440. Handle<SharedFunctionInfo> shared(function->shared());
  9441. Handle<ScopeInfo> scope_info(shared->scope_info());
  9442. ASSERT(*scope_info != ScopeInfo::Empty(isolate));
  9443. // Get the locals names and values into a temporary array.
  9444. //
  9445. // TODO(1240907): Hide compiler-introduced stack variables
  9446. // (e.g. .result)? For users of the debugger, they will probably be
  9447. // confusing.
  9448. Handle<FixedArray> locals =
  9449. isolate->factory()->NewFixedArray(scope_info->LocalCount() * 2);
  9450. // Fill in the values of the locals.
  9451. int i = 0;
  9452. for (; i < scope_info->StackLocalCount(); ++i) {
  9453. // Use the value from the stack.
  9454. locals->set(i * 2, scope_info->LocalName(i));
  9455. locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
  9456. }
  9457. if (i < scope_info->LocalCount()) {
  9458. // Get the context containing declarations.
  9459. Handle<Context> context(
  9460. Context::cast(it.frame()->context())->declaration_context());
  9461. for (; i < scope_info->LocalCount(); ++i) {
  9462. Handle<String> name(scope_info->LocalName(i));
  9463. VariableMode mode;
  9464. InitializationFlag init_flag;
  9465. locals->set(i * 2, *name);
  9466. locals->set(i * 2 + 1, context->get(
  9467. scope_info->ContextSlotIndex(*name, &mode, &init_flag)));
  9468. }
  9469. }
  9470. // Check whether this frame is positioned at return. If not top
  9471. // frame or if the frame is optimized it cannot be at a return.
  9472. bool at_return = false;
  9473. if (!is_optimized && index == 0) {
  9474. at_return = isolate->debug()->IsBreakAtReturn(it.frame());
  9475. }
  9476. // If positioned just before return find the value to be returned and add it
  9477. // to the frame information.
  9478. Handle<Object> return_value = isolate->factory()->undefined_value();
  9479. if (at_return) {
  9480. StackFrameIterator it2(isolate);
  9481. Address internal_frame_sp = NULL;
  9482. while (!it2.done()) {
  9483. if (it2.frame()->is_internal()) {
  9484. internal_frame_sp = it2.frame()->sp();
  9485. } else {
  9486. if (it2.frame()->is_java_script()) {
  9487. if (it2.frame()->id() == it.frame()->id()) {
  9488. // The internal frame just before the JavaScript frame contains the
  9489. // value to return on top. A debug break at return will create an
  9490. // internal frame to store the return value (eax/rax/r0) before
  9491. // entering the debug break exit frame.
  9492. if (internal_frame_sp != NULL) {
  9493. return_value =
  9494. Handle<Object>(Memory::Object_at(internal_frame_sp),
  9495. isolate);
  9496. break;
  9497. }
  9498. }
  9499. }
  9500. // Indicate that the previous frame was not an internal frame.
  9501. internal_frame_sp = NULL;
  9502. }
  9503. it2.Advance();
  9504. }
  9505. }
  9506. // Now advance to the arguments adapter frame (if any). It contains all
  9507. // the provided parameters whereas the function frame always have the number
  9508. // of arguments matching the functions parameters. The rest of the
  9509. // information (except for what is collected above) is the same.
  9510. if ((inlined_jsframe_index == 0) && it.frame()->has_adapted_arguments()) {
  9511. it.AdvanceToArgumentsFrame();
  9512. frame_inspector.SetArgumentsFrame(it.frame());
  9513. }
  9514. // Find the number of arguments to fill. At least fill the number of
  9515. // parameters for the function and fill more if more parameters are provided.
  9516. int argument_count = scope_info->ParameterCount();
  9517. if (argument_count < frame_inspector.GetParametersCount()) {
  9518. argument_count = frame_inspector.GetParametersCount();
  9519. }
  9520. // Calculate the size of the result.
  9521. int details_size = kFrameDetailsFirstDynamicIndex +
  9522. 2 * (argument_count + scope_info->LocalCount()) +
  9523. (at_return ? 1 : 0);
  9524. Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
  9525. // Add the frame id.
  9526. details->set(kFrameDetailsFrameIdIndex, *frame_id);
  9527. // Add the function (same as in function frame).
  9528. details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
  9529. // Add the arguments count.
  9530. details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
  9531. // Add the locals count
  9532. details->set(kFrameDetailsLocalCountIndex,
  9533. Smi::FromInt(scope_info->LocalCount()));
  9534. // Add the source position.
  9535. if (position != RelocInfo::kNoPosition) {
  9536. details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
  9537. } else {
  9538. details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
  9539. }
  9540. // Add the constructor information.
  9541. details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
  9542. // Add the at return information.
  9543. details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
  9544. // Add flags to indicate information on whether this frame is
  9545. // bit 0: invoked in the debugger context.
  9546. // bit 1: optimized frame.
  9547. // bit 2: inlined in optimized frame
  9548. int flags = 0;
  9549. if (*save->context() == *isolate->debug()->debug_context()) {
  9550. flags |= 1 << 0;
  9551. }
  9552. if (is_optimized) {
  9553. flags |= 1 << 1;
  9554. flags |= inlined_jsframe_index << 2;
  9555. }
  9556. details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
  9557. // Fill the dynamic part.
  9558. int details_index = kFrameDetailsFirstDynamicIndex;
  9559. // Add arguments name and value.
  9560. for (int i = 0; i < argument_count; i++) {
  9561. // Name of the argument.
  9562. if (i < scope_info->ParameterCount()) {
  9563. details->set(details_index++, scope_info->ParameterName(i));
  9564. } else {
  9565. details->set(details_index++, heap->undefined_value());
  9566. }
  9567. // Parameter value.
  9568. if (i < frame_inspector.GetParametersCount()) {
  9569. // Get the value from the stack.
  9570. details->set(details_index++, frame_inspector.GetParameter(i));
  9571. } else {
  9572. details->set(details_index++, heap->undefined_value());
  9573. }
  9574. }
  9575. // Add locals name and value from the temporary copy from the function frame.
  9576. for (int i = 0; i < scope_info->LocalCount() * 2; i++) {
  9577. details->set(details_index++, locals->get(i));
  9578. }
  9579. // Add the value being returned.
  9580. if (at_return) {
  9581. details->set(details_index++, *return_value);
  9582. }
  9583. // Add the receiver (same as in function frame).
  9584. // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
  9585. // THE FRAME ITERATOR TO WRAP THE RECEIVER.
  9586. Handle<Object> receiver(it.frame()->receiver(), isolate);
  9587. if (!receiver->IsJSObject() &&
  9588. shared->is_classic_mode() &&
  9589. !function->IsBuiltin()) {
  9590. // If the receiver is not a JSObject and the function is not a
  9591. // builtin or strict-mode we have hit an optimization where a
  9592. // value object is not converted into a wrapped JS objects. To
  9593. // hide this optimization from the debugger, we wrap the receiver
  9594. // by creating correct wrapper object based on the calling frame's
  9595. // native context.
  9596. it.Advance();
  9597. Handle<Context> calling_frames_native_context(
  9598. Context::cast(Context::cast(it.frame()->context())->native_context()));
  9599. ASSERT(!receiver->IsUndefined() && !receiver->IsNull());
  9600. receiver =
  9601. isolate->factory()->ToObject(receiver, calling_frames_native_context);
  9602. }
  9603. details->set(kFrameDetailsReceiverIndex, *receiver);
  9604. ASSERT_EQ(details_size, details_index);
  9605. return *isolate->factory()->NewJSArrayWithElements(details);
  9606. }
  9607. // Create a plain JSObject which materializes the local scope for the specified
  9608. // frame.
  9609. static Handle<JSObject> MaterializeStackLocalsWithFrameInspector(
  9610. Isolate* isolate,
  9611. Handle<JSObject> target,
  9612. Handle<JSFunction> function,
  9613. FrameInspector* frame_inspector) {
  9614. Handle<SharedFunctionInfo> shared(function->shared());
  9615. Handle<ScopeInfo> scope_info(shared->scope_info());
  9616. // First fill all parameters.
  9617. for (int i = 0; i < scope_info->ParameterCount(); ++i) {
  9618. Handle<Object> value(i < frame_inspector->GetParametersCount()
  9619. ? frame_inspector->GetParameter(i)
  9620. : isolate->heap()->undefined_value(),
  9621. isolate);
  9622. ASSERT(!value->IsTheHole());
  9623. RETURN_IF_EMPTY_HANDLE_VALUE(
  9624. isolate,
  9625. SetProperty(isolate,
  9626. target,
  9627. Handle<String>(scope_info->ParameterName(i)),
  9628. value,
  9629. NONE,
  9630. kNonStrictMode),
  9631. Handle<JSObject>());
  9632. }
  9633. // Second fill all stack locals.
  9634. for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
  9635. Handle<Object> value(frame_inspector->GetExpression(i), isolate);
  9636. if (value->IsTheHole()) continue;
  9637. RETURN_IF_EMPTY_HANDLE_VALUE(
  9638. isolate,
  9639. SetProperty(isolate,
  9640. target,
  9641. Handle<String>(scope_info->StackLocalName(i)),
  9642. value,
  9643. NONE,
  9644. kNonStrictMode),
  9645. Handle<JSObject>());
  9646. }
  9647. return target;
  9648. }
  9649. static void UpdateStackLocalsFromMaterializedObject(Isolate* isolate,
  9650. Handle<JSObject> target,
  9651. Handle<JSFunction> function,
  9652. JavaScriptFrame* frame,
  9653. int inlined_jsframe_index) {
  9654. if (inlined_jsframe_index != 0 || frame->is_optimized()) {
  9655. // Optimized frames are not supported.
  9656. // TODO(yangguo): make sure all code deoptimized when debugger is active
  9657. // and assert that this cannot happen.
  9658. return;
  9659. }
  9660. Handle<SharedFunctionInfo> shared(function->shared());
  9661. Handle<ScopeInfo> scope_info(shared->scope_info());
  9662. // Parameters.
  9663. for (int i = 0; i < scope_info->ParameterCount(); ++i) {
  9664. ASSERT(!frame->GetParameter(i)->IsTheHole());
  9665. HandleScope scope(isolate);
  9666. Handle<Object> value = GetProperty(
  9667. isolate, target, Handle<String>(scope_info->ParameterName(i)));
  9668. frame->SetParameterValue(i, *value);
  9669. }
  9670. // Stack locals.
  9671. for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
  9672. if (frame->GetExpression(i)->IsTheHole()) continue;
  9673. HandleScope scope(isolate);
  9674. Handle<Object> value = GetProperty(
  9675. isolate, target, Handle<String>(scope_info->StackLocalName(i)));
  9676. frame->SetExpression(i, *value);
  9677. }
  9678. }
  9679. static Handle<JSObject> MaterializeLocalContext(Isolate* isolate,
  9680. Handle<JSObject> target,
  9681. Handle<JSFunction> function,
  9682. JavaScriptFrame* frame) {
  9683. HandleScope scope(isolate);
  9684. Handle<SharedFunctionInfo> shared(function->shared());
  9685. Handle<ScopeInfo> scope_info(shared->scope_info());
  9686. if (!scope_info->HasContext()) return target;
  9687. // Third fill all context locals.
  9688. Handle<Context> frame_context(Context::cast(frame->context()));
  9689. Handle<Context> function_context(frame_context->declaration_context());
  9690. if (!scope_info->CopyContextLocalsToScopeObject(
  9691. isolate, function_context, target)) {
  9692. return Handle<JSObject>();
  9693. }
  9694. // Finally copy any properties from the function context extension.
  9695. // These will be variables introduced by eval.
  9696. if (function_context->closure() == *function) {
  9697. if (function_context->has_extension() &&
  9698. !function_context->IsNativeContext()) {
  9699. Handle<JSObject> ext(JSObject::cast(function_context->extension()));
  9700. bool threw = false;
  9701. Handle<FixedArray> keys =
  9702. GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
  9703. if (threw) return Handle<JSObject>();
  9704. for (int i = 0; i < keys->length(); i++) {
  9705. // Names of variables introduced by eval are strings.
  9706. ASSERT(keys->get(i)->IsString());
  9707. Handle<String> key(String::cast(keys->get(i)));
  9708. RETURN_IF_EMPTY_HANDLE_VALUE(
  9709. isolate,
  9710. SetProperty(isolate,
  9711. target,
  9712. key,
  9713. GetProperty(isolate, ext, key),
  9714. NONE,
  9715. kNonStrictMode),
  9716. Handle<JSObject>());
  9717. }
  9718. }
  9719. }
  9720. return target;
  9721. }
  9722. static Handle<JSObject> MaterializeLocalScope(
  9723. Isolate* isolate,
  9724. JavaScriptFrame* frame,
  9725. int inlined_jsframe_index) {
  9726. FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
  9727. Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
  9728. Handle<JSObject> local_scope =
  9729. isolate->factory()->NewJSObject(isolate->object_function());
  9730. local_scope = MaterializeStackLocalsWithFrameInspector(
  9731. isolate, local_scope, function, &frame_inspector);
  9732. RETURN_IF_EMPTY_HANDLE_VALUE(isolate, local_scope, Handle<JSObject>());
  9733. return MaterializeLocalContext(isolate, local_scope, function, frame);
  9734. }
  9735. // Set the context local variable value.
  9736. static bool SetContextLocalValue(Isolate* isolate,
  9737. Handle<ScopeInfo> scope_info,
  9738. Handle<Context> context,
  9739. Handle<String> variable_name,
  9740. Handle<Object> new_value) {
  9741. for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
  9742. Handle<String> next_name(scope_info->ContextLocalName(i));
  9743. if (variable_name->Equals(*next_name)) {
  9744. VariableMode mode;
  9745. InitializationFlag init_flag;
  9746. int context_index =
  9747. scope_info->ContextSlotIndex(*next_name, &mode, &init_flag);
  9748. context->set(context_index, *new_value);
  9749. return true;
  9750. }
  9751. }
  9752. return false;
  9753. }
  9754. static bool SetLocalVariableValue(Isolate* isolate,
  9755. JavaScriptFrame* frame,
  9756. int inlined_jsframe_index,
  9757. Handle<String> variable_name,
  9758. Handle<Object> new_value) {
  9759. if (inlined_jsframe_index != 0 || frame->is_optimized()) {
  9760. // Optimized frames are not supported.
  9761. return false;
  9762. }
  9763. Handle<JSFunction> function(frame->function());
  9764. Handle<SharedFunctionInfo> shared(function->shared());
  9765. Handle<ScopeInfo> scope_info(shared->scope_info());
  9766. bool default_result = false;
  9767. // Parameters.
  9768. for (int i = 0; i < scope_info->ParameterCount(); ++i) {
  9769. if (scope_info->ParameterName(i)->Equals(*variable_name)) {
  9770. frame->SetParameterValue(i, *new_value);
  9771. // Argument might be shadowed in heap context, don't stop here.
  9772. default_result = true;
  9773. }
  9774. }
  9775. // Stack locals.
  9776. for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
  9777. if (scope_info->StackLocalName(i)->Equals(*variable_name)) {
  9778. frame->SetExpression(i, *new_value);
  9779. return true;
  9780. }
  9781. }
  9782. if (scope_info->HasContext()) {
  9783. // Context locals.
  9784. Handle<Context> frame_context(Context::cast(frame->context()));
  9785. Handle<Context> function_context(frame_context->declaration_context());
  9786. if (SetContextLocalValue(
  9787. isolate, scope_info, function_context, variable_name, new_value)) {
  9788. return true;
  9789. }
  9790. // Function context extension. These are variables introduced by eval.
  9791. if (function_context->closure() == *function) {
  9792. if (function_context->has_extension() &&
  9793. !function_context->IsNativeContext()) {
  9794. Handle<JSObject> ext(JSObject::cast(function_context->extension()));
  9795. if (ext->HasProperty(*variable_name)) {
  9796. // We don't expect this to do anything except replacing
  9797. // property value.
  9798. SetProperty(isolate,
  9799. ext,
  9800. variable_name,
  9801. new_value,
  9802. NONE,
  9803. kNonStrictMode);
  9804. return true;
  9805. }
  9806. }
  9807. }
  9808. }
  9809. return default_result;
  9810. }
  9811. // Create a plain JSObject which materializes the closure content for the
  9812. // context.
  9813. static Handle<JSObject> MaterializeClosure(Isolate* isolate,
  9814. Handle<Context> context) {
  9815. ASSERT(context->IsFunctionContext());
  9816. Handle<SharedFunctionInfo> shared(context->closure()->shared());
  9817. Handle<ScopeInfo> scope_info(shared->scope_info());
  9818. // Allocate and initialize a JSObject with all the content of this function
  9819. // closure.
  9820. Handle<JSObject> closure_scope =
  9821. isolate->factory()->NewJSObject(isolate->object_function());
  9822. // Fill all context locals to the context extension.
  9823. if (!scope_info->CopyContextLocalsToScopeObject(
  9824. isolate, context, closure_scope)) {
  9825. return Handle<JSObject>();
  9826. }
  9827. // Finally copy any properties from the function context extension. This will
  9828. // be variables introduced by eval.
  9829. if (context->has_extension()) {
  9830. Handle<JSObject> ext(JSObject::cast(context->extension()));
  9831. bool threw = false;
  9832. Handle<FixedArray> keys =
  9833. GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
  9834. if (threw) return Handle<JSObject>();
  9835. for (int i = 0; i < keys->length(); i++) {
  9836. // Names of variables introduced by eval are strings.
  9837. ASSERT(keys->get(i)->IsString());
  9838. Handle<String> key(String::cast(keys->get(i)));
  9839. RETURN_IF_EMPTY_HANDLE_VALUE(
  9840. isolate,
  9841. SetProperty(isolate,
  9842. closure_scope,
  9843. key,
  9844. GetProperty(isolate, ext, key),
  9845. NONE,
  9846. kNonStrictMode),
  9847. Handle<JSObject>());
  9848. }
  9849. }
  9850. return closure_scope;
  9851. }
  9852. // This method copies structure of MaterializeClosure method above.
  9853. static bool SetClosureVariableValue(Isolate* isolate,
  9854. Handle<Context> context,
  9855. Handle<String> variable_name,
  9856. Handle<Object> new_value) {
  9857. ASSERT(context->IsFunctionContext());
  9858. Handle<SharedFunctionInfo> shared(context->closure()->shared());
  9859. Handle<ScopeInfo> scope_info(shared->scope_info());
  9860. // Context locals to the context extension.
  9861. if (SetContextLocalValue(
  9862. isolate, scope_info, context, variable_name, new_value)) {
  9863. return true;
  9864. }
  9865. // Properties from the function context extension. This will
  9866. // be variables introduced by eval.
  9867. if (context->has_extension()) {
  9868. Handle<JSObject> ext(JSObject::cast(context->extension()));
  9869. if (ext->HasProperty(*variable_name)) {
  9870. // We don't expect this to do anything except replacing property value.
  9871. SetProperty(isolate,
  9872. ext,
  9873. variable_name,
  9874. new_value,
  9875. NONE,
  9876. kNonStrictMode);
  9877. return true;
  9878. }
  9879. }
  9880. return false;
  9881. }
  9882. // Create a plain JSObject which materializes the scope for the specified
  9883. // catch context.
  9884. static Handle<JSObject> MaterializeCatchScope(Isolate* isolate,
  9885. Handle<Context> context) {
  9886. ASSERT(context->IsCatchContext());
  9887. Handle<String> name(String::cast(context->extension()));
  9888. Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX),
  9889. isolate);
  9890. Handle<JSObject> catch_scope =
  9891. isolate->factory()->NewJSObject(isolate->object_function());
  9892. RETURN_IF_EMPTY_HANDLE_VALUE(
  9893. isolate,
  9894. SetProperty(isolate,
  9895. catch_scope,
  9896. name,
  9897. thrown_object,
  9898. NONE,
  9899. kNonStrictMode),
  9900. Handle<JSObject>());
  9901. return catch_scope;
  9902. }
  9903. static bool SetCatchVariableValue(Isolate* isolate,
  9904. Handle<Context> context,
  9905. Handle<String> variable_name,
  9906. Handle<Object> new_value) {
  9907. ASSERT(context->IsCatchContext());
  9908. Handle<String> name(String::cast(context->extension()));
  9909. if (!name->Equals(*variable_name)) {
  9910. return false;
  9911. }
  9912. context->set(Context::THROWN_OBJECT_INDEX, *new_value);
  9913. return true;
  9914. }
  9915. // Create a plain JSObject which materializes the block scope for the specified
  9916. // block context.
  9917. static Handle<JSObject> MaterializeBlockScope(
  9918. Isolate* isolate,
  9919. Handle<Context> context) {
  9920. ASSERT(context->IsBlockContext());
  9921. Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
  9922. // Allocate and initialize a JSObject with all the arguments, stack locals
  9923. // heap locals and extension properties of the debugged function.
  9924. Handle<JSObject> block_scope =
  9925. isolate->factory()->NewJSObject(isolate->object_function());
  9926. // Fill all context locals.
  9927. if (!scope_info->CopyContextLocalsToScopeObject(
  9928. isolate, context, block_scope)) {
  9929. return Handle<JSObject>();
  9930. }
  9931. return block_scope;
  9932. }
  9933. // Create a plain JSObject which materializes the module scope for the specified
  9934. // module context.
  9935. static Handle<JSObject> MaterializeModuleScope(
  9936. Isolate* isolate,
  9937. Handle<Context> context) {
  9938. ASSERT(context->IsModuleContext());
  9939. Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
  9940. // Allocate and initialize a JSObject with all the members of the debugged
  9941. // module.
  9942. Handle<JSObject> module_scope =
  9943. isolate->factory()->NewJSObject(isolate->object_function());
  9944. // Fill all context locals.
  9945. if (!scope_info->CopyContextLocalsToScopeObject(
  9946. isolate, context, module_scope)) {
  9947. return Handle<JSObject>();
  9948. }
  9949. return module_scope;
  9950. }
  9951. // Iterate over the actual scopes visible from a stack frame or from a closure.
  9952. // The iteration proceeds from the innermost visible nested scope outwards.
  9953. // All scopes are backed by an actual context except the local scope,
  9954. // which is inserted "artificially" in the context chain.
  9955. class ScopeIterator {
  9956. public:
  9957. enum ScopeType {
  9958. ScopeTypeGlobal = 0,
  9959. ScopeTypeLocal,
  9960. ScopeTypeWith,
  9961. ScopeTypeClosure,
  9962. ScopeTypeCatch,
  9963. ScopeTypeBlock,
  9964. ScopeTypeModule
  9965. };
  9966. ScopeIterator(Isolate* isolate,
  9967. JavaScriptFrame* frame,
  9968. int inlined_jsframe_index)
  9969. : isolate_(isolate),
  9970. frame_(frame),
  9971. inlined_jsframe_index_(inlined_jsframe_index),
  9972. function_(frame->function()),
  9973. context_(Context::cast(frame->context())),
  9974. nested_scope_chain_(4),
  9975. failed_(false) {
  9976. // Catch the case when the debugger stops in an internal function.
  9977. Handle<SharedFunctionInfo> shared_info(function_->shared());
  9978. Handle<ScopeInfo> scope_info(shared_info->scope_info());
  9979. if (shared_info->script() == isolate->heap()->undefined_value()) {
  9980. while (context_->closure() == *function_) {
  9981. context_ = Handle<Context>(context_->previous(), isolate_);
  9982. }
  9983. return;
  9984. }
  9985. // Get the debug info (create it if it does not exist).
  9986. if (!isolate->debug()->EnsureDebugInfo(shared_info, function_)) {
  9987. // Return if ensuring debug info failed.
  9988. return;
  9989. }
  9990. Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared_info);
  9991. // Find the break point where execution has stopped.
  9992. BreakLocationIterator break_location_iterator(debug_info,
  9993. ALL_BREAK_LOCATIONS);
  9994. // pc points to the instruction after the current one, possibly a break
  9995. // location as well. So the "- 1" to exclude it from the search.
  9996. break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
  9997. if (break_location_iterator.IsExit()) {
  9998. // We are within the return sequence. At the momemt it is not possible to
  9999. // get a source position which is consistent with the current scope chain.
  10000. // Thus all nested with, catch and block contexts are skipped and we only
  10001. // provide the function scope.
  10002. if (scope_info->HasContext()) {
  10003. context_ = Handle<Context>(context_->declaration_context(), isolate_);
  10004. } else {
  10005. while (context_->closure() == *function_) {
  10006. context_ = Handle<Context>(context_->previous(), isolate_);
  10007. }
  10008. }
  10009. if (scope_info->scope_type() != EVAL_SCOPE) {
  10010. nested_scope_chain_.Add(scope_info);
  10011. }
  10012. } else {
  10013. // Reparse the code and analyze the scopes.
  10014. Handle<Script> script(Script::cast(shared_info->script()));
  10015. Scope* scope = NULL;
  10016. // Check whether we are in global, eval or function code.
  10017. Handle<ScopeInfo> scope_info(shared_info->scope_info());
  10018. if (scope_info->scope_type() != FUNCTION_SCOPE) {
  10019. // Global or eval code.
  10020. CompilationInfoWithZone info(script);
  10021. if (scope_info->scope_type() == GLOBAL_SCOPE) {
  10022. info.MarkAsGlobal();
  10023. } else {
  10024. ASSERT(scope_info->scope_type() == EVAL_SCOPE);
  10025. info.MarkAsEval();
  10026. info.SetContext(Handle<Context>(function_->context()));
  10027. }
  10028. if (Parser::Parse(&info) && Scope::Analyze(&info)) {
  10029. scope = info.function()->scope();
  10030. }
  10031. RetrieveScopeChain(scope, shared_info);
  10032. } else {
  10033. // Function code
  10034. CompilationInfoWithZone info(shared_info);
  10035. if (Parser::Parse(&info) && Scope::Analyze(&info)) {
  10036. scope = info.function()->scope();
  10037. }
  10038. RetrieveScopeChain(scope, shared_info);
  10039. }
  10040. }
  10041. }
  10042. ScopeIterator(Isolate* isolate,
  10043. Handle<JSFunction> function)
  10044. : isolate_(isolate),
  10045. frame_(NULL),
  10046. inlined_jsframe_index_(0),
  10047. function_(function),
  10048. context_(function->context()),
  10049. failed_(false) {
  10050. if (function->IsBuiltin()) {
  10051. context_ = Handle<Context>();
  10052. }
  10053. }
  10054. // More scopes?
  10055. bool Done() {
  10056. ASSERT(!failed_);
  10057. return context_.is_null();
  10058. }
  10059. bool Failed() { return failed_; }
  10060. // Move to the next scope.
  10061. void Next() {
  10062. ASSERT(!failed_);
  10063. ScopeType scope_type = Type();
  10064. if (scope_type == ScopeTypeGlobal) {
  10065. // The global scope is always the last in the chain.
  10066. ASSERT(context_->IsNativeContext());
  10067. context_ = Handle<Context>();
  10068. return;
  10069. }
  10070. if (nested_scope_chain_.is_empty()) {
  10071. context_ = Handle<Context>(context_->previous(), isolate_);
  10072. } else {
  10073. if (nested_scope_chain_.last()->HasContext()) {
  10074. ASSERT(context_->previous() != NULL);
  10075. context_ = Handle<Context>(context_->previous(), isolate_);
  10076. }
  10077. nested_scope_chain_.RemoveLast();
  10078. }
  10079. }
  10080. // Return the type of the current scope.
  10081. ScopeType Type() {
  10082. ASSERT(!failed_);
  10083. if (!nested_scope_chain_.is_empty()) {
  10084. Handle<ScopeInfo> scope_info = nested_scope_chain_.last();
  10085. switch (scope_info->scope_type()) {
  10086. case FUNCTION_SCOPE:
  10087. ASSERT(context_->IsFunctionContext() ||
  10088. !scope_info->HasContext());
  10089. return ScopeTypeLocal;
  10090. case MODULE_SCOPE:
  10091. ASSERT(context_->IsModuleContext());
  10092. return ScopeTypeModule;
  10093. case GLOBAL_SCOPE:
  10094. ASSERT(context_->IsNativeContext());
  10095. return ScopeTypeGlobal;
  10096. case WITH_SCOPE:
  10097. ASSERT(context_->IsWithContext());
  10098. return ScopeTypeWith;
  10099. case CATCH_SCOPE:
  10100. ASSERT(context_->IsCatchContext());
  10101. return ScopeTypeCatch;
  10102. case BLOCK_SCOPE:
  10103. ASSERT(!scope_info->HasContext() ||
  10104. context_->IsBlockContext());
  10105. return ScopeTypeBlock;
  10106. case EVAL_SCOPE:
  10107. UNREACHABLE();
  10108. }
  10109. }
  10110. if (context_->IsNativeContext()) {
  10111. ASSERT(context_->global_object()->IsGlobalObject());
  10112. return ScopeTypeGlobal;
  10113. }
  10114. if (context_->IsFunctionContext()) {
  10115. return ScopeTypeClosure;
  10116. }
  10117. if (context_->IsCatchContext()) {
  10118. return ScopeTypeCatch;
  10119. }
  10120. if (context_->IsBlockContext()) {
  10121. return ScopeTypeBlock;
  10122. }
  10123. if (context_->IsModuleContext()) {
  10124. return ScopeTypeModule;
  10125. }
  10126. ASSERT(context_->IsWithContext());
  10127. return ScopeTypeWith;
  10128. }
  10129. // Return the JavaScript object with the content of the current scope.
  10130. Handle<JSObject> ScopeObject() {
  10131. ASSERT(!failed_);
  10132. switch (Type()) {
  10133. case ScopeIterator::ScopeTypeGlobal:
  10134. return Handle<JSObject>(CurrentContext()->global_object());
  10135. case ScopeIterator::ScopeTypeLocal:
  10136. // Materialize the content of the local scope into a JSObject.
  10137. ASSERT(nested_scope_chain_.length() == 1);
  10138. return MaterializeLocalScope(isolate_, frame_, inlined_jsframe_index_);
  10139. case ScopeIterator::ScopeTypeWith:
  10140. // Return the with object.
  10141. return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
  10142. case ScopeIterator::ScopeTypeCatch:
  10143. return MaterializeCatchScope(isolate_, CurrentContext());
  10144. case ScopeIterator::ScopeTypeClosure:
  10145. // Materialize the content of the closure scope into a JSObject.
  10146. return MaterializeClosure(isolate_, CurrentContext());
  10147. case ScopeIterator::ScopeTypeBlock:
  10148. return MaterializeBlockScope(isolate_, CurrentContext());
  10149. case ScopeIterator::ScopeTypeModule:
  10150. return MaterializeModuleScope(isolate_, CurrentContext());
  10151. }
  10152. UNREACHABLE();
  10153. return Handle<JSObject>();
  10154. }
  10155. bool SetVariableValue(Handle<String> variable_name,
  10156. Handle<Object> new_value) {
  10157. ASSERT(!failed_);
  10158. switch (Type()) {
  10159. case ScopeIterator::ScopeTypeGlobal:
  10160. break;
  10161. case ScopeIterator::ScopeTypeLocal:
  10162. return SetLocalVariableValue(isolate_, frame_, inlined_jsframe_index_,
  10163. variable_name, new_value);
  10164. case ScopeIterator::ScopeTypeWith:
  10165. break;
  10166. case ScopeIterator::ScopeTypeCatch:
  10167. return SetCatchVariableValue(isolate_, CurrentContext(),
  10168. variable_name, new_value);
  10169. case ScopeIterator::ScopeTypeClosure:
  10170. return SetClosureVariableValue(isolate_, CurrentContext(),
  10171. variable_name, new_value);
  10172. case ScopeIterator::ScopeTypeBlock:
  10173. // TODO(2399): should we implement it?
  10174. break;
  10175. case ScopeIterator::ScopeTypeModule:
  10176. // TODO(2399): should we implement it?
  10177. break;
  10178. }
  10179. return false;
  10180. }
  10181. Handle<ScopeInfo> CurrentScopeInfo() {
  10182. ASSERT(!failed_);
  10183. if (!nested_scope_chain_.is_empty()) {
  10184. return nested_scope_chain_.last();
  10185. } else if (context_->IsBlockContext()) {
  10186. return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension()));
  10187. } else if (context_->IsFunctionContext()) {
  10188. return Handle<ScopeInfo>(context_->closure()->shared()->scope_info());
  10189. }
  10190. return Handle<ScopeInfo>::null();
  10191. }
  10192. // Return the context for this scope. For the local context there might not
  10193. // be an actual context.
  10194. Handle<Context> CurrentContext() {
  10195. ASSERT(!failed_);
  10196. if (Type() == ScopeTypeGlobal ||
  10197. nested_scope_chain_.is_empty()) {
  10198. return context_;
  10199. } else if (nested_scope_chain_.last()->HasContext()) {
  10200. return context_;
  10201. } else {
  10202. return Handle<Context>();
  10203. }
  10204. }
  10205. #ifdef DEBUG
  10206. // Debug print of the content of the current scope.
  10207. void DebugPrint() {
  10208. ASSERT(!failed_);
  10209. switch (Type()) {
  10210. case ScopeIterator::ScopeTypeGlobal:
  10211. PrintF("Global:\n");
  10212. CurrentContext()->Print();
  10213. break;
  10214. case ScopeIterator::ScopeTypeLocal: {
  10215. PrintF("Local:\n");
  10216. function_->shared()->scope_info()->Print();
  10217. if (!CurrentContext().is_null()) {
  10218. CurrentContext()->Print();
  10219. if (CurrentContext()->has_extension()) {
  10220. Handle<Object> extension(CurrentContext()->extension(), isolate_);
  10221. if (extension->IsJSContextExtensionObject()) {
  10222. extension->Print();
  10223. }
  10224. }
  10225. }
  10226. break;
  10227. }
  10228. case ScopeIterator::ScopeTypeWith:
  10229. PrintF("With:\n");
  10230. CurrentContext()->extension()->Print();
  10231. break;
  10232. case ScopeIterator::ScopeTypeCatch:
  10233. PrintF("Catch:\n");
  10234. CurrentContext()->extension()->Print();
  10235. CurrentContext()->get(Context::THROWN_OBJECT_INDEX)->Print();
  10236. break;
  10237. case ScopeIterator::ScopeTypeClosure:
  10238. PrintF("Closure:\n");
  10239. CurrentContext()->Print();
  10240. if (CurrentContext()->has_extension()) {
  10241. Handle<Object> extension(CurrentContext()->extension(), isolate_);
  10242. if (extension->IsJSContextExtensionObject()) {
  10243. extension->Print();
  10244. }
  10245. }
  10246. break;
  10247. default:
  10248. UNREACHABLE();
  10249. }
  10250. PrintF("\n");
  10251. }
  10252. #endif
  10253. private:
  10254. Isolate* isolate_;
  10255. JavaScriptFrame* frame_;
  10256. int inlined_jsframe_index_;
  10257. Handle<JSFunction> function_;
  10258. Handle<Context> context_;
  10259. List<Handle<ScopeInfo> > nested_scope_chain_;
  10260. bool failed_;
  10261. void RetrieveScopeChain(Scope* scope,
  10262. Handle<SharedFunctionInfo> shared_info) {
  10263. if (scope != NULL) {
  10264. int source_position = shared_info->code()->SourcePosition(frame_->pc());
  10265. scope->GetNestedScopeChain(&nested_scope_chain_, source_position);
  10266. } else {
  10267. // A failed reparse indicates that the preparser has diverged from the
  10268. // parser or that the preparse data given to the initial parse has been
  10269. // faulty. We fail in debug mode but in release mode we only provide the
  10270. // information we get from the context chain but nothing about
  10271. // completely stack allocated scopes or stack allocated locals.
  10272. // Or it could be due to stack overflow.
  10273. ASSERT(isolate_->has_pending_exception());
  10274. failed_ = true;
  10275. }
  10276. }
  10277. DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
  10278. };
  10279. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
  10280. HandleScope scope(isolate);
  10281. ASSERT(args.length() == 2);
  10282. // Check arguments.
  10283. Object* check;
  10284. { MaybeObject* maybe_check = Runtime_CheckExecutionState(
  10285. RUNTIME_ARGUMENTS(isolate, args));
  10286. if (!maybe_check->ToObject(&check)) return maybe_check;
  10287. }
  10288. CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
  10289. // Get the frame where the debugging is performed.
  10290. StackFrame::Id id = UnwrapFrameId(wrapped_id);
  10291. JavaScriptFrameIterator it(isolate, id);
  10292. JavaScriptFrame* frame = it.frame();
  10293. // Count the visible scopes.
  10294. int n = 0;
  10295. for (ScopeIterator it(isolate, frame, 0);
  10296. !it.Done();
  10297. it.Next()) {
  10298. n++;
  10299. }
  10300. return Smi::FromInt(n);
  10301. }
  10302. // Returns the list of step-in positions (text offset) in a function of the
  10303. // stack frame in a range from the current debug break position to the end
  10304. // of the corresponding statement.
  10305. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetStepInPositions) {
  10306. HandleScope scope(isolate);
  10307. ASSERT(args.length() == 2);
  10308. // Check arguments.
  10309. Object* check;
  10310. { MaybeObject* maybe_check = Runtime_CheckExecutionState(
  10311. RUNTIME_ARGUMENTS(isolate, args));
  10312. if (!maybe_check->ToObject(&check)) return maybe_check;
  10313. }
  10314. CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
  10315. // Get the frame where the debugging is performed.
  10316. StackFrame::Id id = UnwrapFrameId(wrapped_id);
  10317. JavaScriptFrameIterator frame_it(isolate, id);
  10318. JavaScriptFrame* frame = frame_it.frame();
  10319. Handle<JSFunction> fun =
  10320. Handle<JSFunction>(frame->function());
  10321. Handle<SharedFunctionInfo> shared =
  10322. Handle<SharedFunctionInfo>(fun->shared());
  10323. if (!isolate->debug()->EnsureDebugInfo(shared, fun)) {
  10324. return isolate->heap()->undefined_value();
  10325. }
  10326. Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared);
  10327. int len = 0;
  10328. Handle<JSArray> array(isolate->factory()->NewJSArray(10));
  10329. // Find the break point where execution has stopped.
  10330. BreakLocationIterator break_location_iterator(debug_info,
  10331. ALL_BREAK_LOCATIONS);
  10332. break_location_iterator.FindBreakLocationFromAddress(frame->pc());
  10333. int current_statement_pos = break_location_iterator.statement_position();
  10334. while (!break_location_iterator.Done()) {
  10335. if (break_location_iterator.pc() > frame->pc()) {
  10336. if (break_location_iterator.IsStepInLocation(isolate)) {
  10337. Smi* position_value = Smi::FromInt(break_location_iterator.position());
  10338. JSObject::SetElement(array, len,
  10339. Handle<Object>(position_value, isolate),
  10340. NONE, kNonStrictMode);
  10341. len++;
  10342. }
  10343. }
  10344. // Advance iterator.
  10345. break_location_iterator.Next();
  10346. if (current_statement_pos !=
  10347. break_location_iterator.statement_position()) {
  10348. break;
  10349. }
  10350. }
  10351. return *array;
  10352. }
  10353. static const int kScopeDetailsTypeIndex = 0;
  10354. static const int kScopeDetailsObjectIndex = 1;
  10355. static const int kScopeDetailsSize = 2;
  10356. static MaybeObject* MaterializeScopeDetails(Isolate* isolate,
  10357. ScopeIterator* it) {
  10358. // Calculate the size of the result.
  10359. int details_size = kScopeDetailsSize;
  10360. Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
  10361. // Fill in scope details.
  10362. details->set(kScopeDetailsTypeIndex, Smi::FromInt(it->Type()));
  10363. Handle<JSObject> scope_object = it->ScopeObject();
  10364. RETURN_IF_EMPTY_HANDLE(isolate, scope_object);
  10365. details->set(kScopeDetailsObjectIndex, *scope_object);
  10366. return *isolate->factory()->NewJSArrayWithElements(details);
  10367. }
  10368. // Return an array with scope details
  10369. // args[0]: number: break id
  10370. // args[1]: number: frame index
  10371. // args[2]: number: inlined frame index
  10372. // args[3]: number: scope index
  10373. //
  10374. // The array returned contains the following information:
  10375. // 0: Scope type
  10376. // 1: Scope object
  10377. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
  10378. HandleScope scope(isolate);
  10379. ASSERT(args.length() == 4);
  10380. // Check arguments.
  10381. Object* check;
  10382. { MaybeObject* maybe_check = Runtime_CheckExecutionState(
  10383. RUNTIME_ARGUMENTS(isolate, args));
  10384. if (!maybe_check->ToObject(&check)) return maybe_check;
  10385. }
  10386. CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
  10387. CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
  10388. CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
  10389. // Get the frame where the debugging is performed.
  10390. StackFrame::Id id = UnwrapFrameId(wrapped_id);
  10391. JavaScriptFrameIterator frame_it(isolate, id);
  10392. JavaScriptFrame* frame = frame_it.frame();
  10393. // Find the requested scope.
  10394. int n = 0;
  10395. ScopeIterator it(isolate, frame, inlined_jsframe_index);
  10396. for (; !it.Done() && n < index; it.Next()) {
  10397. n++;
  10398. }
  10399. if (it.Done()) {
  10400. return isolate->heap()->undefined_value();
  10401. }
  10402. return MaterializeScopeDetails(isolate, &it);
  10403. }
  10404. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeCount) {
  10405. HandleScope scope(isolate);
  10406. ASSERT(args.length() == 1);
  10407. // Check arguments.
  10408. CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
  10409. // Count the visible scopes.
  10410. int n = 0;
  10411. for (ScopeIterator it(isolate, fun); !it.Done(); it.Next()) {
  10412. n++;
  10413. }
  10414. return Smi::FromInt(n);
  10415. }
  10416. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeDetails) {
  10417. HandleScope scope(isolate);
  10418. ASSERT(args.length() == 2);
  10419. // Check arguments.
  10420. CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
  10421. CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
  10422. // Find the requested scope.
  10423. int n = 0;
  10424. ScopeIterator it(isolate, fun);
  10425. for (; !it.Done() && n < index; it.Next()) {
  10426. n++;
  10427. }
  10428. if (it.Done()) {
  10429. return isolate->heap()->undefined_value();
  10430. }
  10431. return MaterializeScopeDetails(isolate, &it);
  10432. }
  10433. static bool SetScopeVariableValue(ScopeIterator* it, int index,
  10434. Handle<String> variable_name,
  10435. Handle<Object> new_value) {
  10436. for (int n = 0; !it->Done() && n < index; it->Next()) {
  10437. n++;
  10438. }
  10439. if (it->Done()) {
  10440. return false;
  10441. }
  10442. return it->SetVariableValue(variable_name, new_value);
  10443. }
  10444. // Change variable value in closure or local scope
  10445. // args[0]: number or JsFunction: break id or function
  10446. // args[1]: number: frame index (when arg[0] is break id)
  10447. // args[2]: number: inlined frame index (when arg[0] is break id)
  10448. // args[3]: number: scope index
  10449. // args[4]: string: variable name
  10450. // args[5]: object: new value
  10451. //
  10452. // Return true if success and false otherwise
  10453. RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScopeVariableValue) {
  10454. HandleScope scope(isolate);
  10455. ASSERT(args.length() == 6);
  10456. // Check arguments.
  10457. CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
  10458. CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4);
  10459. Handle<Object> new_value = args.at<Object>(5);
  10460. bool res;
  10461. if (args[0]->IsNumber()) {
  10462. Object* check;
  10463. { MaybeObject* maybe_check = Runtime_CheckExecutionState(
  10464. RUNTIME_ARGUMENTS(isolate, args));
  10465. if (!maybe_check->ToObject(&check)) return maybe_check;
  10466. }
  10467. CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
  10468. CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
  10469. // Get the frame where the debugging is performed.
  10470. StackFrame::Id id = UnwrapFrameId(wrapped_id);
  10471. JavaScriptFrameIterator frame_it(isolate, id);
  10472. JavaScriptFrame* frame = frame_it.frame();
  10473. ScopeIterator it(isolate, frame, inlined_jsframe_index);
  10474. res = SetScopeVariableValue(&it, index, variable_name, new_value);
  10475. } else {
  10476. CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
  10477. ScopeIterator it(isolate, fun);
  10478. res = SetScopeVariableValue(&it, index, variable_name, new_value);
  10479. }
  10480. return isolate->heap()->ToBoolean(res);
  10481. }
  10482. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) {
  10483. HandleScope scope(isolate);
  10484. ASSERT(args.length() == 0);
  10485. #ifdef DEBUG
  10486. // Print the scopes for the top frame.
  10487. StackFrameLocator locator(isolate);
  10488. JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
  10489. for (ScopeIterator it(isolate, frame, 0);
  10490. !it.Done();
  10491. it.Next()) {
  10492. it.DebugPrint();
  10493. }
  10494. #endif
  10495. return isolate->heap()->undefined_value();
  10496. }
  10497. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadCount) {
  10498. HandleScope scope(isolate);
  10499. ASSERT(args.length() == 1);
  10500. // Check arguments.
  10501. Object* result;
  10502. { MaybeObject* maybe_result = Runtime_CheckExecutionState(
  10503. RUNTIME_ARGUMENTS(isolate, args));
  10504. if (!maybe_result->ToObject(&result)) return maybe_result;
  10505. }
  10506. // Count all archived V8 threads.
  10507. int n = 0;
  10508. for (ThreadState* thread =
  10509. isolate->thread_manager()->FirstThreadStateInUse();
  10510. thread != NULL;
  10511. thread = thread->Next()) {
  10512. n++;
  10513. }
  10514. // Total number of threads is current thread and archived threads.
  10515. return Smi::FromInt(n + 1);
  10516. }
  10517. static const int kThreadDetailsCurrentThreadIndex = 0;
  10518. static const int kThreadDetailsThreadIdIndex = 1;
  10519. static const int kThreadDetailsSize = 2;
  10520. // Return an array with thread details
  10521. // args[0]: number: break id
  10522. // args[1]: number: thread index
  10523. //
  10524. // The array returned contains the following information:
  10525. // 0: Is current thread?
  10526. // 1: Thread id
  10527. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadDetails) {
  10528. HandleScope scope(isolate);
  10529. ASSERT(args.length() == 2);
  10530. // Check arguments.
  10531. Object* check;
  10532. { MaybeObject* maybe_check = Runtime_CheckExecutionState(
  10533. RUNTIME_ARGUMENTS(isolate, args));
  10534. if (!maybe_check->ToObject(&check)) return maybe_check;
  10535. }
  10536. CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
  10537. // Allocate array for result.
  10538. Handle<FixedArray> details =
  10539. isolate->factory()->NewFixedArray(kThreadDetailsSize);
  10540. // Thread index 0 is current thread.
  10541. if (index == 0) {
  10542. // Fill the details.
  10543. details->set(kThreadDetailsCurrentThreadIndex,
  10544. isolate->heap()->true_value());
  10545. details->set(kThreadDetailsThreadIdIndex,
  10546. Smi::FromInt(ThreadId::Current().ToInteger()));
  10547. } else {
  10548. // Find the thread with the requested index.
  10549. int n = 1;
  10550. ThreadState* thread =
  10551. isolate->thread_manager()->FirstThreadStateInUse();
  10552. while (index != n && thread != NULL) {
  10553. thread = thread->Next();
  10554. n++;
  10555. }
  10556. if (thread == NULL) {
  10557. return isolate->heap()->undefined_value();
  10558. }
  10559. // Fill the details.
  10560. details->set(kThreadDetailsCurrentThreadIndex,
  10561. isolate->heap()->false_value());
  10562. details->set(kThreadDetailsThreadIdIndex,
  10563. Smi::FromInt(thread->id().ToInteger()));
  10564. }
  10565. // Convert to JS array and return.
  10566. return *isolate->factory()->NewJSArrayWithElements(details);
  10567. }
  10568. // Sets the disable break state
  10569. // args[0]: disable break state
  10570. RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDisableBreak) {
  10571. HandleScope scope(isolate);
  10572. ASSERT(args.length() == 1);
  10573. CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 0);
  10574. isolate->debug()->set_disable_break(disable_break);
  10575. return isolate->heap()->undefined_value();
  10576. }
  10577. static bool IsPositionAlignmentCodeCorrect(int alignment) {
  10578. return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED;
  10579. }
  10580. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetBreakLocations) {
  10581. HandleScope scope(isolate);
  10582. ASSERT(args.length() == 2);
  10583. CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
  10584. CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[1]);
  10585. if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
  10586. return isolate->ThrowIllegalOperation();
  10587. }
  10588. BreakPositionAlignment alignment =
  10589. static_cast<BreakPositionAlignment>(statement_aligned_code);
  10590. Handle<SharedFunctionInfo> shared(fun->shared());
  10591. // Find the number of break points
  10592. Handle<Object> break_locations =
  10593. Debug::GetSourceBreakLocations(shared, alignment);
  10594. if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
  10595. // Return array as JS array
  10596. return *isolate->factory()->NewJSArrayWithElements(
  10597. Handle<FixedArray>::cast(break_locations));
  10598. }
  10599. // Set a break point in a function.
  10600. // args[0]: function
  10601. // args[1]: number: break source position (within the function source)
  10602. // args[2]: number: break point object
  10603. RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFunctionBreakPoint) {
  10604. HandleScope scope(isolate);
  10605. ASSERT(args.length() == 3);
  10606. CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
  10607. CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
  10608. RUNTIME_ASSERT(source_position >= 0);
  10609. Handle<Object> break_point_object_arg = args.at<Object>(2);
  10610. // Set break point.
  10611. isolate->debug()->SetBreakPoint(function, break_point_object_arg,
  10612. &source_position);
  10613. return Smi::FromInt(source_position);
  10614. }
  10615. // Changes the state of a break point in a script and returns source position
  10616. // where break point was set. NOTE: Regarding performance see the NOTE for
  10617. // GetScriptFromScriptData.
  10618. // args[0]: script to set break point in
  10619. // args[1]: number: break source position (within the script source)
  10620. // args[2]: number, breakpoint position alignment
  10621. // args[3]: number: break point object
  10622. RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScriptBreakPoint) {
  10623. HandleScope scope(isolate);
  10624. ASSERT(args.length() == 4);
  10625. CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
  10626. CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
  10627. RUNTIME_ASSERT(source_position >= 0);
  10628. CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]);
  10629. Handle<Object> break_point_object_arg = args.at<Object>(3);
  10630. if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
  10631. return isolate->ThrowIllegalOperation();
  10632. }
  10633. BreakPositionAlignment alignment =
  10634. static_cast<BreakPositionAlignment>(statement_aligned_code);
  10635. // Get the script from the script wrapper.
  10636. RUNTIME_ASSERT(wrapper->value()->IsScript());
  10637. Handle<Script> script(Script::cast(wrapper->value()));
  10638. // Set break point.
  10639. if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
  10640. &source_position,
  10641. alignment)) {
  10642. return isolate->heap()->undefined_value();
  10643. }
  10644. return Smi::FromInt(source_position);
  10645. }
  10646. // Clear a break point
  10647. // args[0]: number: break point object
  10648. RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearBreakPoint) {
  10649. HandleScope scope(isolate);
  10650. ASSERT(args.length() == 1);
  10651. Handle<Object> break_point_object_arg = args.at<Object>(0);
  10652. // Clear break point.
  10653. isolate->debug()->ClearBreakPoint(break_point_object_arg);
  10654. return isolate->heap()->undefined_value();
  10655. }
  10656. // Change the state of break on exceptions.
  10657. // args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
  10658. // args[1]: Boolean indicating on/off.
  10659. RUNTIME_FUNCTION(MaybeObject*, Runtime_ChangeBreakOnException) {
  10660. HandleScope scope(isolate);
  10661. ASSERT(args.length() == 2);
  10662. RUNTIME_ASSERT(args[0]->IsNumber());
  10663. CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
  10664. // If the number doesn't match an enum value, the ChangeBreakOnException
  10665. // function will default to affecting caught exceptions.
  10666. ExceptionBreakType type =
  10667. static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
  10668. // Update break point state.
  10669. isolate->debug()->ChangeBreakOnException(type, enable);
  10670. return isolate->heap()->undefined_value();
  10671. }
  10672. // Returns the state of break on exceptions
  10673. // args[0]: boolean indicating uncaught exceptions
  10674. RUNTIME_FUNCTION(MaybeObject*, Runtime_IsBreakOnException) {
  10675. HandleScope scope(isolate);
  10676. ASSERT(args.length() == 1);
  10677. RUNTIME_ASSERT(args[0]->IsNumber());
  10678. ExceptionBreakType type =
  10679. static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
  10680. bool result = isolate->debug()->IsBreakOnException(type);
  10681. return Smi::FromInt(result);
  10682. }
  10683. // Prepare for stepping
  10684. // args[0]: break id for checking execution state
  10685. // args[1]: step action from the enumeration StepAction
  10686. // args[2]: number of times to perform the step, for step out it is the number
  10687. // of frames to step down.
  10688. RUNTIME_FUNCTION(MaybeObject*, Runtime_PrepareStep) {
  10689. HandleScope scope(isolate);
  10690. ASSERT(args.length() == 3);
  10691. // Check arguments.
  10692. Object* check;
  10693. { MaybeObject* maybe_check = Runtime_CheckExecutionState(
  10694. RUNTIME_ARGUMENTS(isolate, args));
  10695. if (!maybe_check->ToObject(&check)) return maybe_check;
  10696. }
  10697. if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
  10698. return isolate->Throw(isolate->heap()->illegal_argument_string());
  10699. }
  10700. // Get the step action and check validity.
  10701. StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
  10702. if (step_action != StepIn &&
  10703. step_action != StepNext &&
  10704. step_action != StepOut &&
  10705. step_action != StepInMin &&
  10706. step_action != StepMin) {
  10707. return isolate->Throw(isolate->heap()->illegal_argument_string());
  10708. }
  10709. // Get the number of steps.
  10710. int step_count = NumberToInt32(args[2]);
  10711. if (step_count < 1) {
  10712. return isolate->Throw(isolate->heap()->illegal_argument_string());
  10713. }
  10714. // Clear all current stepping setup.
  10715. isolate->debug()->ClearStepping();
  10716. // Prepare step.
  10717. isolate->debug()->PrepareStep(static_cast<StepAction>(step_action),
  10718. step_count);
  10719. return isolate->heap()->undefined_value();
  10720. }
  10721. // Clear all stepping set by PrepareStep.
  10722. RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) {
  10723. HandleScope scope(isolate);
  10724. ASSERT(args.length() == 0);
  10725. isolate->debug()->ClearStepping();
  10726. return isolate->heap()->undefined_value();
  10727. }
  10728. // Helper function to find or create the arguments object for
  10729. // Runtime_DebugEvaluate.
  10730. static Handle<JSObject> MaterializeArgumentsObject(
  10731. Isolate* isolate,
  10732. Handle<JSObject> target,
  10733. Handle<JSFunction> function) {
  10734. // Do not materialize the arguments object for eval or top-level code.
  10735. // Skip if "arguments" is already taken.
  10736. if (!function->shared()->is_function() ||
  10737. target->HasLocalProperty(isolate->heap()->arguments_string())) {
  10738. return target;
  10739. }
  10740. // FunctionGetArguments can't throw an exception.
  10741. Handle<JSObject> arguments = Handle<JSObject>::cast(
  10742. Accessors::FunctionGetArguments(function));
  10743. SetProperty(isolate,
  10744. target,
  10745. isolate->factory()->arguments_string(),
  10746. arguments,
  10747. ::NONE,
  10748. kNonStrictMode);
  10749. return target;
  10750. }
  10751. // Compile and evaluate source for the given context.
  10752. static MaybeObject* DebugEvaluate(Isolate* isolate,
  10753. Handle<Context> context,
  10754. Handle<Object> context_extension,
  10755. Handle<Object> receiver,
  10756. Handle<String> source) {
  10757. if (context_extension->IsJSObject()) {
  10758. Handle<JSObject> extension = Handle<JSObject>::cast(context_extension);
  10759. Handle<JSFunction> closure(context->closure(), isolate);
  10760. context = isolate->factory()->NewWithContext(closure, context, extension);
  10761. }
  10762. Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
  10763. source,
  10764. context,
  10765. context->IsNativeContext(),
  10766. CLASSIC_MODE,
  10767. NO_PARSE_RESTRICTION,
  10768. RelocInfo::kNoPosition);
  10769. RETURN_IF_EMPTY_HANDLE(isolate, shared);
  10770. Handle<JSFunction> eval_fun =
  10771. isolate->factory()->NewFunctionFromSharedFunctionInfo(
  10772. shared, context, NOT_TENURED);
  10773. bool pending_exception;
  10774. Handle<Object> result = Execution::Call(
  10775. eval_fun, receiver, 0, NULL, &pending_exception);
  10776. if (pending_exception) return Failure::Exception();
  10777. // Skip the global proxy as it has no properties and always delegates to the
  10778. // real global object.
  10779. if (result->IsJSGlobalProxy()) {
  10780. result = Handle<JSObject>(JSObject::cast(result->GetPrototype(isolate)));
  10781. }
  10782. // Clear the oneshot breakpoints so that the debugger does not step further.
  10783. isolate->debug()->ClearStepping();
  10784. return *result;
  10785. }
  10786. // Evaluate a piece of JavaScript in the context of a stack frame for
  10787. // debugging. Things that need special attention are:
  10788. // - Parameters and stack-allocated locals need to be materialized. Altered
  10789. // values need to be written back to the stack afterwards.
  10790. // - The arguments object needs to materialized.
  10791. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
  10792. HandleScope scope(isolate);
  10793. // Check the execution state and decode arguments frame and source to be
  10794. // evaluated.
  10795. ASSERT(args.length() == 6);
  10796. Object* check_result;
  10797. { MaybeObject* maybe_result = Runtime_CheckExecutionState(
  10798. RUNTIME_ARGUMENTS(isolate, args));
  10799. if (!maybe_result->ToObject(&check_result)) return maybe_result;
  10800. }
  10801. CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
  10802. CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
  10803. CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
  10804. CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
  10805. Handle<Object> context_extension(args[5], isolate);
  10806. // Handle the processing of break.
  10807. DisableBreak disable_break_save(disable_break);
  10808. // Get the frame where the debugging is performed.
  10809. StackFrame::Id id = UnwrapFrameId(wrapped_id);
  10810. JavaScriptFrameIterator it(isolate, id);
  10811. JavaScriptFrame* frame = it.frame();
  10812. FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
  10813. Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
  10814. // Traverse the saved contexts chain to find the active context for the
  10815. // selected frame.
  10816. SaveContext* save = FindSavedContextForFrame(isolate, frame);
  10817. SaveContext savex(isolate);
  10818. isolate->set_context(*(save->context()));
  10819. // Evaluate on the context of the frame.
  10820. Handle<Context> context(Context::cast(frame->context()));
  10821. ASSERT(!context.is_null());
  10822. // Materialize stack locals and the arguments object.
  10823. Handle<JSObject> materialized =
  10824. isolate->factory()->NewJSObject(isolate->object_function());
  10825. materialized = MaterializeStackLocalsWithFrameInspector(
  10826. isolate, materialized, function, &frame_inspector);
  10827. RETURN_IF_EMPTY_HANDLE(isolate, materialized);
  10828. materialized = MaterializeArgumentsObject(isolate, materialized, function);
  10829. RETURN_IF_EMPTY_HANDLE(isolate, materialized);
  10830. // Add the materialized object in a with-scope to shadow the stack locals.
  10831. context = isolate->factory()->NewWithContext(function, context, materialized);
  10832. Handle<Object> receiver(frame->receiver(), isolate);
  10833. Object* evaluate_result_object;
  10834. { MaybeObject* maybe_result =
  10835. DebugEvaluate(isolate, context, context_extension, receiver, source);
  10836. if (!maybe_result->ToObject(&evaluate_result_object)) return maybe_result;
  10837. }
  10838. Handle<Object> result(evaluate_result_object, isolate);
  10839. // Write back potential changes to materialized stack locals to the stack.
  10840. UpdateStackLocalsFromMaterializedObject(
  10841. isolate, materialized, function, frame, inlined_jsframe_index);
  10842. return *result;
  10843. }
  10844. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) {
  10845. HandleScope scope(isolate);
  10846. // Check the execution state and decode arguments frame and source to be
  10847. // evaluated.
  10848. ASSERT(args.length() == 4);
  10849. Object* check_result;
  10850. { MaybeObject* maybe_result = Runtime_CheckExecutionState(
  10851. RUNTIME_ARGUMENTS(isolate, args));
  10852. if (!maybe_result->ToObject(&check_result)) return maybe_result;
  10853. }
  10854. CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
  10855. CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
  10856. Handle<Object> context_extension(args[3], isolate);
  10857. // Handle the processing of break.
  10858. DisableBreak disable_break_save(disable_break);
  10859. // Enter the top context from before the debugger was invoked.
  10860. SaveContext save(isolate);
  10861. SaveContext* top = &save;
  10862. while (top != NULL && *top->context() == *isolate->debug()->debug_context()) {
  10863. top = top->prev();
  10864. }
  10865. if (top != NULL) {
  10866. isolate->set_context(*top->context());
  10867. }
  10868. // Get the native context now set to the top context from before the
  10869. // debugger was invoked.
  10870. Handle<Context> context = isolate->native_context();
  10871. Handle<Object> receiver = isolate->global_object();
  10872. return DebugEvaluate(isolate, context, context_extension, receiver, source);
  10873. }
  10874. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetLoadedScripts) {
  10875. HandleScope scope(isolate);
  10876. ASSERT(args.length() == 0);
  10877. // Fill the script objects.
  10878. Handle<FixedArray> instances = isolate->debug()->GetLoadedScripts();
  10879. // Convert the script objects to proper JS objects.
  10880. for (int i = 0; i < instances->length(); i++) {
  10881. Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
  10882. // Get the script wrapper in a local handle before calling GetScriptWrapper,
  10883. // because using
  10884. // instances->set(i, *GetScriptWrapper(script))
  10885. // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
  10886. // already have dereferenced the instances handle.
  10887. Handle<JSValue> wrapper = GetScriptWrapper(script);
  10888. instances->set(i, *wrapper);
  10889. }
  10890. // Return result as a JS array.
  10891. Handle<JSObject> result =
  10892. isolate->factory()->NewJSObject(isolate->array_function());
  10893. isolate->factory()->SetContent(Handle<JSArray>::cast(result), instances);
  10894. return *result;
  10895. }
  10896. // Helper function used by Runtime_DebugReferencedBy below.
  10897. static int DebugReferencedBy(HeapIterator* iterator,
  10898. JSObject* target,
  10899. Object* instance_filter, int max_references,
  10900. FixedArray* instances, int instances_size,
  10901. JSFunction* arguments_function) {
  10902. Isolate* isolate = target->GetIsolate();
  10903. SealHandleScope shs(isolate);
  10904. DisallowHeapAllocation no_allocation;
  10905. // Iterate the heap.
  10906. int count = 0;
  10907. JSObject* last = NULL;
  10908. HeapObject* heap_obj = NULL;
  10909. while (((heap_obj = iterator->next()) != NULL) &&
  10910. (max_references == 0 || count < max_references)) {
  10911. // Only look at all JSObjects.
  10912. if (heap_obj->IsJSObject()) {
  10913. // Skip context extension objects and argument arrays as these are
  10914. // checked in the context of functions using them.
  10915. JSObject* obj = JSObject::cast(heap_obj);
  10916. if (obj->IsJSContextExtensionObject() ||
  10917. obj->map()->constructor() == arguments_function) {
  10918. continue;
  10919. }
  10920. // Check if the JS object has a reference to the object looked for.
  10921. if (obj->ReferencesObject(target)) {
  10922. // Check instance filter if supplied. This is normally used to avoid
  10923. // references from mirror objects (see Runtime_IsInPrototypeChain).
  10924. if (!instance_filter->IsUndefined()) {
  10925. Object* V = obj;
  10926. while (true) {
  10927. Object* prototype = V->GetPrototype(isolate);
  10928. if (prototype->IsNull()) {
  10929. break;
  10930. }
  10931. if (instance_filter == prototype) {
  10932. obj = NULL; // Don't add this object.
  10933. break;
  10934. }
  10935. V = prototype;
  10936. }
  10937. }
  10938. if (obj != NULL) {
  10939. // Valid reference found add to instance array if supplied an update
  10940. // count.
  10941. if (instances != NULL && count < instances_size) {
  10942. instances->set(count, obj);
  10943. }
  10944. last = obj;
  10945. count++;
  10946. }
  10947. }
  10948. }
  10949. }
  10950. // Check for circular reference only. This can happen when the object is only
  10951. // referenced from mirrors and has a circular reference in which case the
  10952. // object is not really alive and would have been garbage collected if not
  10953. // referenced from the mirror.
  10954. if (count == 1 && last == target) {
  10955. count = 0;
  10956. }
  10957. // Return the number of referencing objects found.
  10958. return count;
  10959. }
  10960. // Scan the heap for objects with direct references to an object
  10961. // args[0]: the object to find references to
  10962. // args[1]: constructor function for instances to exclude (Mirror)
  10963. // args[2]: the the maximum number of objects to return
  10964. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugReferencedBy) {
  10965. SealHandleScope shs(isolate);
  10966. ASSERT(args.length() == 3);
  10967. // First perform a full GC in order to avoid references from dead objects.
  10968. isolate->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
  10969. "%DebugReferencedBy");
  10970. // The heap iterator reserves the right to do a GC to make the heap iterable.
  10971. // Due to the GC above we know it won't need to do that, but it seems cleaner
  10972. // to get the heap iterator constructed before we start having unprotected
  10973. // Object* locals that are not protected by handles.
  10974. // Check parameters.
  10975. CONVERT_ARG_CHECKED(JSObject, target, 0);
  10976. Object* instance_filter = args[1];
  10977. RUNTIME_ASSERT(instance_filter->IsUndefined() ||
  10978. instance_filter->IsJSObject());
  10979. CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
  10980. RUNTIME_ASSERT(max_references >= 0);
  10981. // Get the constructor function for context extension and arguments array.
  10982. JSObject* arguments_boilerplate =
  10983. isolate->context()->native_context()->arguments_boilerplate();
  10984. JSFunction* arguments_function =
  10985. JSFunction::cast(arguments_boilerplate->map()->constructor());
  10986. // Get the number of referencing objects.
  10987. int count;
  10988. Heap* heap = isolate->heap();
  10989. HeapIterator heap_iterator(heap);
  10990. count = DebugReferencedBy(&heap_iterator,
  10991. target, instance_filter, max_references,
  10992. NULL, 0, arguments_function);
  10993. // Allocate an array to hold the result.
  10994. Object* object;
  10995. { MaybeObject* maybe_object = heap->AllocateFixedArray(count);
  10996. if (!maybe_object->ToObject(&object)) return maybe_object;
  10997. }
  10998. FixedArray* instances = FixedArray::cast(object);
  10999. // Fill the referencing objects.
  11000. // AllocateFixedArray above does not make the heap non-iterable.
  11001. ASSERT(heap->IsHeapIterable());
  11002. HeapIterator heap_iterator2(heap);
  11003. count = DebugReferencedBy(&heap_iterator2,
  11004. target, instance_filter, max_references,
  11005. instances, count, arguments_function);
  11006. // Return result as JS array.
  11007. Object* result;
  11008. MaybeObject* maybe_result = heap->AllocateJSObject(
  11009. isolate->context()->native_context()->array_function());
  11010. if (!maybe_result->ToObject(&result)) return maybe_result;
  11011. return JSArray::cast(result)->SetContent(instances);
  11012. }
  11013. // Helper function used by Runtime_DebugConstructedBy below.
  11014. static int DebugConstructedBy(HeapIterator* iterator,
  11015. JSFunction* constructor,
  11016. int max_references,
  11017. FixedArray* instances,
  11018. int instances_size) {
  11019. DisallowHeapAllocation no_allocation;
  11020. // Iterate the heap.
  11021. int count = 0;
  11022. HeapObject* heap_obj = NULL;
  11023. while (((heap_obj = iterator->next()) != NULL) &&
  11024. (max_references == 0 || count < max_references)) {
  11025. // Only look at all JSObjects.
  11026. if (heap_obj->IsJSObject()) {
  11027. JSObject* obj = JSObject::cast(heap_obj);
  11028. if (obj->map()->constructor() == constructor) {
  11029. // Valid reference found add to instance array if supplied an update
  11030. // count.
  11031. if (instances != NULL && count < instances_size) {
  11032. instances->set(count, obj);
  11033. }
  11034. count++;
  11035. }
  11036. }
  11037. }
  11038. // Return the number of referencing objects found.
  11039. return count;
  11040. }
  11041. // Scan the heap for objects constructed by a specific function.
  11042. // args[0]: the constructor to find instances of
  11043. // args[1]: the the maximum number of objects to return
  11044. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugConstructedBy) {
  11045. SealHandleScope shs(isolate);
  11046. ASSERT(args.length() == 2);
  11047. // First perform a full GC in order to avoid dead objects.
  11048. Heap* heap = isolate->heap();
  11049. heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
  11050. // Check parameters.
  11051. CONVERT_ARG_CHECKED(JSFunction, constructor, 0);
  11052. CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
  11053. RUNTIME_ASSERT(max_references >= 0);
  11054. // Get the number of referencing objects.
  11055. int count;
  11056. HeapIterator heap_iterator(heap);
  11057. count = DebugConstructedBy(&heap_iterator,
  11058. constructor,
  11059. max_references,
  11060. NULL,
  11061. 0);
  11062. // Allocate an array to hold the result.
  11063. Object* object;
  11064. { MaybeObject* maybe_object = heap->AllocateFixedArray(count);
  11065. if (!maybe_object->ToObject(&object)) return maybe_object;
  11066. }
  11067. FixedArray* instances = FixedArray::cast(object);
  11068. ASSERT(HEAP->IsHeapIterable());
  11069. // Fill the referencing objects.
  11070. HeapIterator heap_iterator2(heap);
  11071. count = DebugConstructedBy(&heap_iterator2,
  11072. constructor,
  11073. max_references,
  11074. instances,
  11075. count);
  11076. // Return result as JS array.
  11077. Object* result;
  11078. { MaybeObject* maybe_result = isolate->heap()->AllocateJSObject(
  11079. isolate->context()->native_context()->array_function());
  11080. if (!maybe_result->ToObject(&result)) return maybe_result;
  11081. }
  11082. return JSArray::cast(result)->SetContent(instances);
  11083. }
  11084. // Find the effective prototype object as returned by __proto__.
  11085. // args[0]: the object to find the prototype for.
  11086. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPrototype) {
  11087. SealHandleScope shs(isolate);
  11088. ASSERT(args.length() == 1);
  11089. CONVERT_ARG_CHECKED(JSObject, obj, 0);
  11090. return GetPrototypeSkipHiddenPrototypes(isolate, obj);
  11091. }
  11092. // Patches script source (should be called upon BeforeCompile event).
  11093. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugSetScriptSource) {
  11094. HandleScope scope(isolate);
  11095. ASSERT(args.length() == 2);
  11096. CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
  11097. CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
  11098. RUNTIME_ASSERT(script_wrapper->value()->IsScript());
  11099. Handle<Script> script(Script::cast(script_wrapper->value()));
  11100. int compilation_state = script->compilation_state();
  11101. RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL);
  11102. script->set_source(*source);
  11103. return isolate->heap()->undefined_value();
  11104. }
  11105. RUNTIME_FUNCTION(MaybeObject*, Runtime_SystemBreak) {
  11106. SealHandleScope shs(isolate);
  11107. ASSERT(args.length() == 0);
  11108. CPU::DebugBreak();
  11109. return isolate->heap()->undefined_value();
  11110. }
  11111. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleFunction) {
  11112. HandleScope scope(isolate);
  11113. #ifdef DEBUG
  11114. ASSERT(args.length() == 1);
  11115. // Get the function and make sure it is compiled.
  11116. CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
  11117. if (!JSFunction::EnsureCompiled(func, KEEP_EXCEPTION)) {
  11118. return Failure::Exception();
  11119. }
  11120. func->code()->PrintLn();
  11121. #endif // DEBUG
  11122. return isolate->heap()->undefined_value();
  11123. }
  11124. RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleConstructor) {
  11125. HandleScope scope(isolate);
  11126. #ifdef DEBUG
  11127. ASSERT(args.length() == 1);
  11128. // Get the function and make sure it is compiled.
  11129. CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
  11130. if (!JSFunction::EnsureCompiled(func, KEEP_EXCEPTION)) {
  11131. return Failure::Exception();
  11132. }
  11133. func->shared()->construct_stub()->PrintLn();
  11134. #endif // DEBUG
  11135. return isolate->heap()->undefined_value();
  11136. }
  11137. RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetInferredName) {
  11138. SealHandleScope shs(isolate);
  11139. ASSERT(args.length() == 1);
  11140. CONVERT_ARG_CHECKED(JSFunction, f, 0);
  11141. return f->shared()->inferred_name();
  11142. }
  11143. static int FindSharedFunctionInfosForScript(HeapIterator* iterator,
  11144. Script* script,
  11145. FixedArray* buffer) {
  11146. DisallowHeapAllocation no_allocation;
  11147. int counter = 0;
  11148. int buffer_size = buffer->length();
  11149. for (HeapObject* obj = iterator->next();
  11150. obj != NULL;
  11151. obj = iterator->next()) {
  11152. ASSERT(obj != NULL);
  11153. if (!obj->IsSharedFunctionInfo()) {
  11154. continue;
  11155. }
  11156. SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
  11157. if (shared->script() != script) {
  11158. continue;
  11159. }
  11160. if (counter < buffer_size) {
  11161. buffer->set(counter, shared);
  11162. }
  11163. counter++;
  11164. }
  11165. return counter;
  11166. }
  11167. // For a script finds all SharedFunctionInfo's in the heap that points
  11168. // to this script. Returns JSArray of SharedFunctionInfo wrapped
  11169. // in OpaqueReferences.
  11170. RUNTIME_FUNCTION(MaybeObject*,
  11171. Runtime_LiveEditFindSharedFunctionInfosForScript) {
  11172. HandleScope scope(isolate);
  11173. CHECK(isolate->debugger()->live_edit_enabled());
  11174. ASSERT(args.length() == 1);
  11175. CONVERT_ARG_CHECKED(JSValue, script_value, 0);
  11176. RUNTIME_ASSERT(script_value->value()->IsScript());
  11177. Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
  11178. const int kBufferSize = 32;
  11179. Handle<FixedArray> array;
  11180. array = isolate->factory()->NewFixedArray(kBufferSize);
  11181. int number;
  11182. Heap* heap = isolate->heap();
  11183. {
  11184. heap->EnsureHeapIsIterable();
  11185. DisallowHeapAllocation no_allocation;
  11186. HeapIterator heap_iterator(heap);
  11187. Script* scr = *script;
  11188. FixedArray* arr = *array;
  11189. number = FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
  11190. }
  11191. if (number > kBufferSize) {
  11192. array = isolate->factory()->NewFixedArray(number);
  11193. heap->EnsureHeapIsIterable();
  11194. DisallowHeapAllocation no_allocation;
  11195. HeapIterator heap_iterator(heap);
  11196. Script* scr = *script;
  11197. FixedArray* arr = *array;
  11198. FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
  11199. }
  11200. Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array);
  11201. result->set_length(Smi::FromInt(number));
  11202. LiveEdit::WrapSharedFunctionInfos(result);
  11203. return *result;
  11204. }
  11205. // For a script calculates compilation information about all its functions.
  11206. // The script source is explicitly specified by the second argument.
  11207. // The source of the actual script is not used, however it is important that
  11208. // all generated code keeps references to this particular instance of script.
  11209. // Returns a JSArray of compilation infos. The array is ordered so that
  11210. // each function with all its descendant is always stored in a continues range
  11211. // with the function itself going first. The root function is a script function.
  11212. RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditGatherCompileInfo) {
  11213. HandleScope scope(isolate);
  11214. CHECK(isolate->debugger()->live_edit_enabled());
  11215. ASSERT(args.length() == 2);
  11216. CONVERT_ARG_CHECKED(JSValue, script, 0);
  11217. CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
  11218. RUNTIME_ASSERT(script->value()->IsScript());
  11219. Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
  11220. JSArray* result = LiveEdit::GatherCompileInfo(script_handle, source);
  11221. if (isolate->has_pending_exception()) {
  11222. return Failure::Exception();
  11223. }
  11224. return result;
  11225. }
  11226. // Changes the source of the script to a new_source.
  11227. // If old_script_name is provided (i.e. is a String), also creates a copy of
  11228. // the script with its original source and sends notification to debugger.
  11229. RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceScript) {
  11230. HandleScope scope(isolate);
  11231. CHECK(isolate->debugger()->live_edit_enabled());
  11232. ASSERT(args.length() == 3);
  11233. CONVERT_ARG_CHECKED(JSValue, original_script_value, 0);
  11234. CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
  11235. Handle<Object> old_script_name(args[2], isolate);
  11236. RUNTIME_ASSERT(original_script_value->value()->IsScript());
  11237. Handle<Script> original_script(Script::cast(original_script_value->value()));
  11238. Object* old_script = LiveEdit::ChangeScriptSource(original_script,
  11239. new_source,
  11240. old_script_name);
  11241. if (old_script->IsScript()) {
  11242. Handle<Script> script_handle(Script::cast(old_script));
  11243. return *(GetScriptWrapper(script_handle));
  11244. } else {
  11245. return isolate->heap()->null_value();
  11246. }
  11247. }
  11248. RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSourceUpdated) {
  11249. HandleScope scope(isolate);
  11250. CHECK(isolate->debugger()->live_edit_enabled());
  11251. ASSERT(args.length() == 1);
  11252. CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 0);
  11253. return LiveEdit::FunctionSourceUpdated(shared_info);
  11254. }
  11255. // Replaces code of SharedFunctionInfo with a new one.
  11256. RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceFunctionCode) {
  11257. HandleScope scope(isolate);
  11258. CHECK(isolate->debugger()->live_edit_enabled());
  11259. ASSERT(args.length() == 2);
  11260. CONVERT_ARG_HANDLE_CHECKED(JSArray, new_compile_info, 0);
  11261. CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 1);
  11262. return LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
  11263. }
  11264. // Connects SharedFunctionInfo to another script.
  11265. RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSetScript) {
  11266. HandleScope scope(isolate);
  11267. CHECK(isolate->debugger()->live_edit_enabled());
  11268. ASSERT(args.length() == 2);
  11269. Handle<Object> function_object(args[0], isolate);
  11270. Handle<Object> script_object(args[1], isolate);
  11271. if (function_object->IsJSValue()) {
  11272. Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
  11273. if (script_object->IsJSValue()) {
  11274. RUNTIME_ASSERT(JSValue::cast(*script_object)->value()->IsScript());
  11275. Script* script = Script::cast(JSValue::cast(*script_object)->value());
  11276. script_object = Handle<Object>(script, isolate);
  11277. }
  11278. LiveEdit::SetFunctionScript(function_wrapper, script_object);
  11279. } else {
  11280. // Just ignore this. We may not have a SharedFunctionInfo for some functions
  11281. // and we check it in this function.
  11282. }
  11283. return isolate->heap()->undefined_value();
  11284. }
  11285. // In a code of a parent function replaces original function as embedded object
  11286. // with a substitution one.
  11287. RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceRefToNestedFunction) {
  11288. HandleScope scope(isolate);
  11289. CHECK(isolate->debugger()->live_edit_enabled());
  11290. ASSERT(args.length() == 3);
  11291. CONVERT_ARG_HANDLE_CHECKED(JSValue, parent_wrapper, 0);
  11292. CONVERT_ARG_HANDLE_CHECKED(JSValue, orig_wrapper, 1);
  11293. CONVERT_ARG_HANDLE_CHECKED(JSValue, subst_wrapper, 2);
  11294. LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper,
  11295. subst_wrapper);
  11296. return isolate->heap()->undefined_value();
  11297. }
  11298. // Updates positions of a shared function info (first parameter) according
  11299. // to script source change. Text change is described in second parameter as
  11300. // array of groups of 3 numbers:
  11301. // (change_begin, change_end, change_end_new_position).
  11302. // Each group describes a change in text; groups are sorted by change_begin.
  11303. RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditPatchFunctionPositions) {
  11304. HandleScope scope(isolate);
  11305. CHECK(isolate->debugger()->live_edit_enabled());
  11306. ASSERT(args.length() == 2);
  11307. CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
  11308. CONVERT_ARG_HANDLE_CHECKED(JSArray, position_change_array, 1);
  11309. return LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
  11310. }
  11311. // For array of SharedFunctionInfo's (each wrapped in JSValue)
  11312. // checks that none of them have activations on stacks (of any thread).
  11313. // Returns array of the same length with corresponding results of
  11314. // LiveEdit::FunctionPatchabilityStatus type.
  11315. RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCheckAndDropActivations) {
  11316. HandleScope scope(isolate);
  11317. CHECK(isolate->debugger()->live_edit_enabled());
  11318. ASSERT(args.length() == 2);
  11319. CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
  11320. CONVERT_BOOLEAN_ARG_CHECKED(do_drop, 1);
  11321. return *LiveEdit::CheckAndDropActivations(shared_array, do_drop);
  11322. }
  11323. // Compares 2 strings line-by-line, then token-wise and returns diff in form
  11324. // of JSArray of triplets (pos1, pos1_end, pos2_end) describing list
  11325. // of diff chunks.
  11326. RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCompareStrings) {
  11327. HandleScope scope(isolate);
  11328. CHECK(isolate->debugger()->live_edit_enabled());
  11329. ASSERT(args.length() == 2);
  11330. CONVERT_ARG_HANDLE_CHECKED(String, s1, 0);
  11331. CONVERT_ARG_HANDLE_CHECKED(String, s2, 1);
  11332. return *LiveEdit::CompareStrings(s1, s2);
  11333. }
  11334. // Restarts a call frame and completely drops all frames above.
  11335. // Returns true if successful. Otherwise returns undefined or an error message.
  11336. RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditRestartFrame) {
  11337. HandleScope scope(isolate);
  11338. CHECK(isolate->debugger()->live_edit_enabled());
  11339. ASSERT(args.length() == 2);
  11340. // Check arguments.
  11341. Object* check;
  11342. { MaybeObject* maybe_check = Runtime_CheckExecutionState(
  11343. RUNTIME_ARGUMENTS(isolate, args));
  11344. if (!maybe_check->ToObject(&check)) return maybe_check;
  11345. }
  11346. CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
  11347. Heap* heap = isolate->heap();
  11348. // Find the relevant frame with the requested index.
  11349. StackFrame::Id id = isolate->debug()->break_frame_id();
  11350. if (id == StackFrame::NO_ID) {
  11351. // If there are no JavaScript stack frames return undefined.
  11352. return heap->undefined_value();
  11353. }
  11354. int count = 0;
  11355. JavaScriptFrameIterator it(isolate, id);
  11356. for (; !it.done(); it.Advance()) {
  11357. if (index < count + it.frame()->GetInlineCount()) break;
  11358. count += it.frame()->GetInlineCount();
  11359. }
  11360. if (it.done()) return heap->undefined_value();
  11361. const char* error_message = LiveEdit::RestartFrame(it.frame());
  11362. if (error_message) {
  11363. return *(isolate->factory()->InternalizeUtf8String(error_message));
  11364. }
  11365. return heap->true_value();
  11366. }
  11367. // A testing entry. Returns statement position which is the closest to
  11368. // source_position.
  11369. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionCodePositionFromSource) {
  11370. HandleScope scope(isolate);
  11371. CHECK(isolate->debugger()->live_edit_enabled());
  11372. ASSERT(args.length() == 2);
  11373. CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
  11374. CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
  11375. Handle<Code> code(function->code(), isolate);
  11376. if (code->kind() != Code::FUNCTION &&
  11377. code->kind() != Code::OPTIMIZED_FUNCTION) {
  11378. return isolate->heap()->undefined_value();
  11379. }
  11380. RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION));
  11381. int closest_pc = 0;
  11382. int distance = kMaxInt;
  11383. while (!it.done()) {
  11384. int statement_position = static_cast<int>(it.rinfo()->data());
  11385. // Check if this break point is closer that what was previously found.
  11386. if (source_position <= statement_position &&
  11387. statement_position - source_position < distance) {
  11388. closest_pc =
  11389. static_cast<int>(it.rinfo()->pc() - code->instruction_start());
  11390. distance = statement_position - source_position;
  11391. // Check whether we can't get any closer.
  11392. if (distance == 0) break;
  11393. }
  11394. it.next();
  11395. }
  11396. return Smi::FromInt(closest_pc);
  11397. }
  11398. // Calls specified function with or without entering the debugger.
  11399. // This is used in unit tests to run code as if debugger is entered or simply
  11400. // to have a stack with C++ frame in the middle.
  11401. RUNTIME_FUNCTION(MaybeObject*, Runtime_ExecuteInDebugContext) {
  11402. HandleScope scope(isolate);
  11403. ASSERT(args.length() == 2);
  11404. CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
  11405. CONVERT_BOOLEAN_ARG_CHECKED(without_debugger, 1);
  11406. Handle<Object> result;
  11407. bool pending_exception;
  11408. {
  11409. if (without_debugger) {
  11410. result = Execution::Call(function, isolate->global_object(), 0, NULL,
  11411. &pending_exception);
  11412. } else {
  11413. EnterDebugger enter_debugger;
  11414. result = Execution::Call(function, isolate->global_object(), 0, NULL,
  11415. &pending_exception);
  11416. }
  11417. }
  11418. if (!pending_exception) {
  11419. return *result;
  11420. } else {
  11421. return Failure::Exception();
  11422. }
  11423. }
  11424. // Sets a v8 flag.
  11425. RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFlags) {
  11426. SealHandleScope shs(isolate);
  11427. CONVERT_ARG_CHECKED(String, arg, 0);
  11428. SmartArrayPointer<char> flags =
  11429. arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
  11430. FlagList::SetFlagsFromString(*flags, StrLength(*flags));
  11431. return isolate->heap()->undefined_value();
  11432. }
  11433. // Performs a GC.
  11434. // Presently, it only does a full GC.
  11435. RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectGarbage) {
  11436. SealHandleScope shs(isolate);
  11437. isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage");
  11438. return isolate->heap()->undefined_value();
  11439. }
  11440. // Gets the current heap usage.
  11441. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHeapUsage) {
  11442. SealHandleScope shs(isolate);
  11443. int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
  11444. if (!Smi::IsValid(usage)) {
  11445. return *isolate->factory()->NewNumberFromInt(usage);
  11446. }
  11447. return Smi::FromInt(usage);
  11448. }
  11449. #endif // ENABLE_DEBUGGER_SUPPORT
  11450. #ifdef V8_I18N_SUPPORT
  11451. RUNTIME_FUNCTION(MaybeObject*, Runtime_CanonicalizeLanguageTag) {
  11452. HandleScope scope(isolate);
  11453. ASSERT(args.length() == 1);
  11454. CONVERT_ARG_HANDLE_CHECKED(String, locale_id_str, 0);
  11455. v8::String::Utf8Value locale_id(v8::Utils::ToLocal(locale_id_str));
  11456. // Return value which denotes invalid language tag.
  11457. const char* const kInvalidTag = "invalid-tag";
  11458. UErrorCode error = U_ZERO_ERROR;
  11459. char icu_result[ULOC_FULLNAME_CAPACITY];
  11460. int icu_length = 0;
  11461. uloc_forLanguageTag(*locale_id, icu_result, ULOC_FULLNAME_CAPACITY,
  11462. &icu_length, &error);
  11463. if (U_FAILURE(error) || icu_length == 0) {
  11464. return isolate->heap()->AllocateStringFromOneByte(CStrVector(kInvalidTag));
  11465. }
  11466. char result[ULOC_FULLNAME_CAPACITY];
  11467. // Force strict BCP47 rules.
  11468. uloc_toLanguageTag(icu_result, result, ULOC_FULLNAME_CAPACITY, TRUE, &error);
  11469. if (U_FAILURE(error)) {
  11470. return isolate->heap()->AllocateStringFromOneByte(CStrVector(kInvalidTag));
  11471. }
  11472. return isolate->heap()->AllocateStringFromOneByte(CStrVector(result));
  11473. }
  11474. RUNTIME_FUNCTION(MaybeObject*, Runtime_AvailableLocalesOf) {
  11475. HandleScope scope(isolate);
  11476. ASSERT(args.length() == 1);
  11477. CONVERT_ARG_HANDLE_CHECKED(String, service, 0);
  11478. const icu::Locale* available_locales = NULL;
  11479. int32_t count = 0;
  11480. if (service->IsUtf8EqualTo(CStrVector("collator"))) {
  11481. available_locales = icu::Collator::getAvailableLocales(count);
  11482. } else if (service->IsUtf8EqualTo(CStrVector("numberformat"))) {
  11483. available_locales = icu::NumberFormat::getAvailableLocales(count);
  11484. } else if (service->IsUtf8EqualTo(CStrVector("dateformat"))) {
  11485. available_locales = icu::DateFormat::getAvailableLocales(count);
  11486. } else if (service->IsUtf8EqualTo(CStrVector("breakiterator"))) {
  11487. available_locales = icu::BreakIterator::getAvailableLocales(count);
  11488. }
  11489. UErrorCode error = U_ZERO_ERROR;
  11490. char result[ULOC_FULLNAME_CAPACITY];
  11491. Handle<JSObject> locales =
  11492. isolate->factory()->NewJSObject(isolate->object_function());
  11493. for (int32_t i = 0; i < count; ++i) {
  11494. const char* icu_name = available_locales[i].getName();
  11495. error = U_ZERO_ERROR;
  11496. // No need to force strict BCP47 rules.
  11497. uloc_toLanguageTag(icu_name, result, ULOC_FULLNAME_CAPACITY, FALSE, &error);
  11498. if (U_FAILURE(error)) {
  11499. // This shouldn't happen, but lets not break the user.
  11500. continue;
  11501. }
  11502. RETURN_IF_EMPTY_HANDLE(isolate,
  11503. JSObject::SetLocalPropertyIgnoreAttributes(
  11504. locales,
  11505. isolate->factory()->NewStringFromAscii(CStrVector(result)),
  11506. isolate->factory()->NewNumber(i),
  11507. NONE));
  11508. }
  11509. return *locales;
  11510. }
  11511. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultICULocale) {
  11512. SealHandleScope shs(isolate);
  11513. ASSERT(args.length() == 0);
  11514. icu::Locale default_locale;
  11515. // Set the locale
  11516. char result[ULOC_FULLNAME_CAPACITY];
  11517. UErrorCode status = U_ZERO_ERROR;
  11518. uloc_toLanguageTag(
  11519. default_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
  11520. if (U_SUCCESS(status)) {
  11521. return isolate->heap()->AllocateStringFromOneByte(CStrVector(result));
  11522. }
  11523. return isolate->heap()->AllocateStringFromOneByte(CStrVector("und"));
  11524. }
  11525. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLanguageTagVariants) {
  11526. HandleScope scope(isolate);
  11527. ASSERT(args.length() == 1);
  11528. CONVERT_ARG_HANDLE_CHECKED(JSArray, input, 0);
  11529. uint32_t length = static_cast<uint32_t>(input->length()->Number());
  11530. Handle<FixedArray> output = isolate->factory()->NewFixedArray(length);
  11531. Handle<Name> maximized =
  11532. isolate->factory()->NewStringFromAscii(CStrVector("maximized"));
  11533. Handle<Name> base =
  11534. isolate->factory()->NewStringFromAscii(CStrVector("base"));
  11535. for (unsigned int i = 0; i < length; ++i) {
  11536. MaybeObject* maybe_string = input->GetElement(i);
  11537. Object* locale_id;
  11538. if (!maybe_string->ToObject(&locale_id) || !locale_id->IsString()) {
  11539. return isolate->Throw(isolate->heap()->illegal_argument_string());
  11540. }
  11541. v8::String::Utf8Value utf8_locale_id(
  11542. v8::Utils::ToLocal(Handle<String>(String::cast(locale_id))));
  11543. UErrorCode error = U_ZERO_ERROR;
  11544. // Convert from BCP47 to ICU format.
  11545. // de-DE-u-co-phonebk -> de_DE@collation=phonebook
  11546. char icu_locale[ULOC_FULLNAME_CAPACITY];
  11547. int icu_locale_length = 0;
  11548. uloc_forLanguageTag(*utf8_locale_id, icu_locale, ULOC_FULLNAME_CAPACITY,
  11549. &icu_locale_length, &error);
  11550. if (U_FAILURE(error) || icu_locale_length == 0) {
  11551. return isolate->Throw(isolate->heap()->illegal_argument_string());
  11552. }
  11553. // Maximize the locale.
  11554. // de_DE@collation=phonebook -> de_Latn_DE@collation=phonebook
  11555. char icu_max_locale[ULOC_FULLNAME_CAPACITY];
  11556. uloc_addLikelySubtags(
  11557. icu_locale, icu_max_locale, ULOC_FULLNAME_CAPACITY, &error);
  11558. // Remove extensions from maximized locale.
  11559. // de_Latn_DE@collation=phonebook -> de_Latn_DE
  11560. char icu_base_max_locale[ULOC_FULLNAME_CAPACITY];
  11561. uloc_getBaseName(
  11562. icu_max_locale, icu_base_max_locale, ULOC_FULLNAME_CAPACITY, &error);
  11563. // Get original name without extensions.
  11564. // de_DE@collation=phonebook -> de_DE
  11565. char icu_base_locale[ULOC_FULLNAME_CAPACITY];
  11566. uloc_getBaseName(
  11567. icu_locale, icu_base_locale, ULOC_FULLNAME_CAPACITY, &error);
  11568. // Convert from ICU locale format to BCP47 format.
  11569. // de_Latn_DE -> de-Latn-DE
  11570. char base_max_locale[ULOC_FULLNAME_CAPACITY];
  11571. uloc_toLanguageTag(icu_base_max_locale, base_max_locale,
  11572. ULOC_FULLNAME_CAPACITY, FALSE, &error);
  11573. // de_DE -> de-DE
  11574. char base_locale[ULOC_FULLNAME_CAPACITY];
  11575. uloc_toLanguageTag(
  11576. icu_base_locale, base_locale, ULOC_FULLNAME_CAPACITY, FALSE, &error);
  11577. if (U_FAILURE(error)) {
  11578. return isolate->Throw(isolate->heap()->illegal_argument_string());
  11579. }
  11580. Handle<JSObject> result =
  11581. isolate->factory()->NewJSObject(isolate->object_function());
  11582. RETURN_IF_EMPTY_HANDLE(isolate,
  11583. JSObject::SetLocalPropertyIgnoreAttributes(
  11584. result,
  11585. maximized,
  11586. isolate->factory()->NewStringFromAscii(CStrVector(base_max_locale)),
  11587. NONE));
  11588. RETURN_IF_EMPTY_HANDLE(isolate,
  11589. JSObject::SetLocalPropertyIgnoreAttributes(
  11590. result,
  11591. base,
  11592. isolate->factory()->NewStringFromAscii(CStrVector(base_locale)),
  11593. NONE));
  11594. output->set(i, *result);
  11595. }
  11596. Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(output);
  11597. result->set_length(Smi::FromInt(length));
  11598. return *result;
  11599. }
  11600. RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateDateTimeFormat) {
  11601. HandleScope scope(isolate);
  11602. ASSERT(args.length() == 3);
  11603. CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
  11604. CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
  11605. CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
  11606. Handle<ObjectTemplateInfo> date_format_template =
  11607. I18N::GetTemplate(isolate);
  11608. // Create an empty object wrapper.
  11609. bool has_pending_exception = false;
  11610. Handle<JSObject> local_object = Execution::InstantiateObject(
  11611. date_format_template, &has_pending_exception);
  11612. if (has_pending_exception) {
  11613. ASSERT(isolate->has_pending_exception());
  11614. return Failure::Exception();
  11615. }
  11616. // Set date time formatter as internal field of the resulting JS object.
  11617. icu::SimpleDateFormat* date_format = DateFormat::InitializeDateTimeFormat(
  11618. isolate, locale, options, resolved);
  11619. if (!date_format) return isolate->ThrowIllegalOperation();
  11620. local_object->SetInternalField(0, reinterpret_cast<Smi*>(date_format));
  11621. RETURN_IF_EMPTY_HANDLE(isolate,
  11622. JSObject::SetLocalPropertyIgnoreAttributes(
  11623. local_object,
  11624. isolate->factory()->NewStringFromAscii(CStrVector("dateFormat")),
  11625. isolate->factory()->NewStringFromAscii(CStrVector("valid")),
  11626. NONE));
  11627. Persistent<v8::Object> wrapper(reinterpret_cast<v8::Isolate*>(isolate),
  11628. v8::Utils::ToLocal(local_object));
  11629. // Make object handle weak so we can delete the data format once GC kicks in.
  11630. wrapper.MakeWeak<void>(NULL, &DateFormat::DeleteDateFormat);
  11631. wrapper.ClearAndLeak();
  11632. return *local_object;
  11633. }
  11634. RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateFormat) {
  11635. HandleScope scope(isolate);
  11636. ASSERT(args.length() == 2);
  11637. CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
  11638. CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 1);
  11639. bool has_pending_exception = false;
  11640. Handle<Object> value = Execution::ToNumber(date, &has_pending_exception);
  11641. if (has_pending_exception) {
  11642. ASSERT(isolate->has_pending_exception());
  11643. return Failure::Exception();
  11644. }
  11645. icu::SimpleDateFormat* date_format =
  11646. DateFormat::UnpackDateFormat(isolate, date_format_holder);
  11647. if (!date_format) return isolate->ThrowIllegalOperation();
  11648. icu::UnicodeString result;
  11649. date_format->format(value->Number(), result);
  11650. return *isolate->factory()->NewStringFromTwoByte(
  11651. Vector<const uint16_t>(
  11652. reinterpret_cast<const uint16_t*>(result.getBuffer()),
  11653. result.length()));
  11654. }
  11655. RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateParse) {
  11656. HandleScope scope(isolate);
  11657. ASSERT(args.length() == 2);
  11658. CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
  11659. CONVERT_ARG_HANDLE_CHECKED(String, date_string, 1);
  11660. v8::String::Utf8Value utf8_date(v8::Utils::ToLocal(date_string));
  11661. icu::UnicodeString u_date(icu::UnicodeString::fromUTF8(*utf8_date));
  11662. icu::SimpleDateFormat* date_format =
  11663. DateFormat::UnpackDateFormat(isolate, date_format_holder);
  11664. if (!date_format) return isolate->ThrowIllegalOperation();
  11665. UErrorCode status = U_ZERO_ERROR;
  11666. UDate date = date_format->parse(u_date, status);
  11667. if (U_FAILURE(status)) return isolate->heap()->undefined_value();
  11668. bool has_pending_exception = false;
  11669. Handle<JSDate> result = Handle<JSDate>::cast(
  11670. Execution::NewDate(static_cast<double>(date), &has_pending_exception));
  11671. if (has_pending_exception) {
  11672. ASSERT(isolate->has_pending_exception());
  11673. return Failure::Exception();
  11674. }
  11675. return *result;
  11676. }
  11677. RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateNumberFormat) {
  11678. HandleScope scope(isolate);
  11679. ASSERT(args.length() == 3);
  11680. CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
  11681. CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
  11682. CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
  11683. Handle<ObjectTemplateInfo> number_format_template =
  11684. I18N::GetTemplate(isolate);
  11685. // Create an empty object wrapper.
  11686. bool has_pending_exception = false;
  11687. Handle<JSObject> local_object = Execution::InstantiateObject(
  11688. number_format_template, &has_pending_exception);
  11689. if (has_pending_exception) {
  11690. ASSERT(isolate->has_pending_exception());
  11691. return Failure::Exception();
  11692. }
  11693. // Set number formatter as internal field of the resulting JS object.
  11694. icu::DecimalFormat* number_format = NumberFormat::InitializeNumberFormat(
  11695. isolate, locale, options, resolved);
  11696. if (!number_format) return isolate->ThrowIllegalOperation();
  11697. local_object->SetInternalField(0, reinterpret_cast<Smi*>(number_format));
  11698. RETURN_IF_EMPTY_HANDLE(isolate,
  11699. JSObject::SetLocalPropertyIgnoreAttributes(
  11700. local_object,
  11701. isolate->factory()->NewStringFromAscii(CStrVector("numberFormat")),
  11702. isolate->factory()->NewStringFromAscii(CStrVector("valid")),
  11703. NONE));
  11704. Persistent<v8::Object> wrapper(reinterpret_cast<v8::Isolate*>(isolate),
  11705. v8::Utils::ToLocal(local_object));
  11706. // Make object handle weak so we can delete the number format once GC kicks
  11707. // in.
  11708. wrapper.MakeWeak<void>(NULL, &NumberFormat::DeleteNumberFormat);
  11709. wrapper.ClearAndLeak();
  11710. return *local_object;
  11711. }
  11712. RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberFormat) {
  11713. HandleScope scope(isolate);
  11714. ASSERT(args.length() == 2);
  11715. CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
  11716. CONVERT_ARG_HANDLE_CHECKED(Object, number, 1);
  11717. bool has_pending_exception = false;
  11718. Handle<Object> value = Execution::ToNumber(number, &has_pending_exception);
  11719. if (has_pending_exception) {
  11720. ASSERT(isolate->has_pending_exception());
  11721. return Failure::Exception();
  11722. }
  11723. icu::DecimalFormat* number_format =
  11724. NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
  11725. if (!number_format) return isolate->ThrowIllegalOperation();
  11726. icu::UnicodeString result;
  11727. number_format->format(value->Number(), result);
  11728. return *isolate->factory()->NewStringFromTwoByte(
  11729. Vector<const uint16_t>(
  11730. reinterpret_cast<const uint16_t*>(result.getBuffer()),
  11731. result.length()));
  11732. }
  11733. RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberParse) {
  11734. HandleScope scope(isolate);
  11735. ASSERT(args.length() == 2);
  11736. CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
  11737. CONVERT_ARG_HANDLE_CHECKED(String, number_string, 1);
  11738. v8::String::Utf8Value utf8_number(v8::Utils::ToLocal(number_string));
  11739. icu::UnicodeString u_number(icu::UnicodeString::fromUTF8(*utf8_number));
  11740. icu::DecimalFormat* number_format =
  11741. NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
  11742. if (!number_format) return isolate->ThrowIllegalOperation();
  11743. UErrorCode status = U_ZERO_ERROR;
  11744. icu::Formattable result;
  11745. // ICU 4.6 doesn't support parseCurrency call. We need to wait for ICU49
  11746. // to be part of Chrome.
  11747. // TODO(cira): Include currency parsing code using parseCurrency call.
  11748. // We need to check if the formatter parses all currencies or only the
  11749. // one it was constructed with (it will impact the API - how to return ISO
  11750. // code and the value).
  11751. number_format->parse(u_number, result, status);
  11752. if (U_FAILURE(status)) return isolate->heap()->undefined_value();
  11753. switch (result.getType()) {
  11754. case icu::Formattable::kDouble:
  11755. return *isolate->factory()->NewNumber(result.getDouble());
  11756. case icu::Formattable::kLong:
  11757. return *isolate->factory()->NewNumberFromInt(result.getLong());
  11758. case icu::Formattable::kInt64:
  11759. return *isolate->factory()->NewNumber(
  11760. static_cast<double>(result.getInt64()));
  11761. default:
  11762. return isolate->heap()->undefined_value();
  11763. }
  11764. }
  11765. RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateCollator) {
  11766. HandleScope scope(isolate);
  11767. ASSERT(args.length() == 3);
  11768. CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
  11769. CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
  11770. CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
  11771. Handle<ObjectTemplateInfo> collator_template = I18N::GetTemplate(isolate);
  11772. // Create an empty object wrapper.
  11773. bool has_pending_exception = false;
  11774. Handle<JSObject> local_object = Execution::InstantiateObject(
  11775. collator_template, &has_pending_exception);
  11776. if (has_pending_exception) {
  11777. ASSERT(isolate->has_pending_exception());
  11778. return Failure::Exception();
  11779. }
  11780. // Set collator as internal field of the resulting JS object.
  11781. icu::Collator* collator = Collator::InitializeCollator(
  11782. isolate, locale, options, resolved);
  11783. if (!collator) return isolate->ThrowIllegalOperation();
  11784. local_object->SetInternalField(0, reinterpret_cast<Smi*>(collator));
  11785. RETURN_IF_EMPTY_HANDLE(isolate,
  11786. JSObject::SetLocalPropertyIgnoreAttributes(
  11787. local_object,
  11788. isolate->factory()->NewStringFromAscii(CStrVector("collator")),
  11789. isolate->factory()->NewStringFromAscii(CStrVector("valid")),
  11790. NONE));
  11791. Persistent<v8::Object> wrapper(reinterpret_cast<v8::Isolate*>(isolate),
  11792. v8::Utils::ToLocal(local_object));
  11793. // Make object handle weak so we can delete the collator once GC kicks in.
  11794. wrapper.MakeWeak<void>(NULL, &Collator::DeleteCollator);
  11795. wrapper.ClearAndLeak();
  11796. return *local_object;
  11797. }
  11798. RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalCompare) {
  11799. HandleScope scope(isolate);
  11800. ASSERT(args.length() == 3);
  11801. CONVERT_ARG_HANDLE_CHECKED(JSObject, collator_holder, 0);
  11802. CONVERT_ARG_HANDLE_CHECKED(String, string1, 1);
  11803. CONVERT_ARG_HANDLE_CHECKED(String, string2, 2);
  11804. icu::Collator* collator = Collator::UnpackCollator(isolate, collator_holder);
  11805. if (!collator) return isolate->ThrowIllegalOperation();
  11806. v8::String::Value string_value1(v8::Utils::ToLocal(string1));
  11807. v8::String::Value string_value2(v8::Utils::ToLocal(string2));
  11808. const UChar* u_string1 = reinterpret_cast<const UChar*>(*string_value1);
  11809. const UChar* u_string2 = reinterpret_cast<const UChar*>(*string_value2);
  11810. UErrorCode status = U_ZERO_ERROR;
  11811. UCollationResult result = collator->compare(u_string1,
  11812. string_value1.length(),
  11813. u_string2,
  11814. string_value2.length(),
  11815. status);
  11816. if (U_FAILURE(status)) return isolate->ThrowIllegalOperation();
  11817. return *isolate->factory()->NewNumberFromInt(result);
  11818. }
  11819. #endif // V8_I18N_SUPPORT
  11820. // Finds the script object from the script data. NOTE: This operation uses
  11821. // heap traversal to find the function generated for the source position
  11822. // for the requested break point. For lazily compiled functions several heap
  11823. // traversals might be required rendering this operation as a rather slow
  11824. // operation. However for setting break points which is normally done through
  11825. // some kind of user interaction the performance is not crucial.
  11826. static Handle<Object> Runtime_GetScriptFromScriptName(
  11827. Handle<String> script_name) {
  11828. // Scan the heap for Script objects to find the script with the requested
  11829. // script data.
  11830. Handle<Script> script;
  11831. Factory* factory = script_name->GetIsolate()->factory();
  11832. Heap* heap = script_name->GetHeap();
  11833. heap->EnsureHeapIsIterable();
  11834. DisallowHeapAllocation no_allocation_during_heap_iteration;
  11835. HeapIterator iterator(heap);
  11836. HeapObject* obj = NULL;
  11837. while (script.is_null() && ((obj = iterator.next()) != NULL)) {
  11838. // If a script is found check if it has the script data requested.
  11839. if (obj->IsScript()) {
  11840. if (Script::cast(obj)->name()->IsString()) {
  11841. if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) {
  11842. script = Handle<Script>(Script::cast(obj));
  11843. }
  11844. }
  11845. }
  11846. }
  11847. // If no script with the requested script data is found return undefined.
  11848. if (script.is_null()) return factory->undefined_value();
  11849. // Return the script found.
  11850. return GetScriptWrapper(script);
  11851. }
  11852. // Get the script object from script data. NOTE: Regarding performance
  11853. // see the NOTE for GetScriptFromScriptData.
  11854. // args[0]: script data for the script to find the source for
  11855. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScript) {
  11856. HandleScope scope(isolate);
  11857. ASSERT(args.length() == 1);
  11858. CONVERT_ARG_CHECKED(String, script_name, 0);
  11859. // Find the requested script.
  11860. Handle<Object> result =
  11861. Runtime_GetScriptFromScriptName(Handle<String>(script_name));
  11862. return *result;
  11863. }
  11864. // Collect the raw data for a stack trace. Returns an array of 4
  11865. // element segments each containing a receiver, function, code and
  11866. // native code offset.
  11867. RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectStackTrace) {
  11868. HandleScope scope(isolate);
  11869. ASSERT_EQ(args.length(), 3);
  11870. CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
  11871. Handle<Object> caller = args.at<Object>(1);
  11872. CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[2]);
  11873. // Optionally capture a more detailed stack trace for the message.
  11874. isolate->CaptureAndSetDetailedStackTrace(error_object);
  11875. // Capture a simple stack trace for the stack property.
  11876. return *isolate->CaptureSimpleStackTrace(error_object, caller, limit);
  11877. }
  11878. // Retrieve the stack trace. This is the raw stack trace that yet has to
  11879. // be formatted. Since we only need this once, clear it afterwards.
  11880. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetAndClearOverflowedStackTrace) {
  11881. HandleScope scope(isolate);
  11882. ASSERT_EQ(args.length(), 1);
  11883. CONVERT_ARG_CHECKED(JSObject, error_object, 0);
  11884. String* key = isolate->heap()->hidden_stack_trace_string();
  11885. Object* result = error_object->GetHiddenProperty(key);
  11886. if (result->IsTheHole()) return isolate->heap()->undefined_value();
  11887. RUNTIME_ASSERT(result->IsJSArray() || result->IsUndefined());
  11888. error_object->DeleteHiddenProperty(key);
  11889. return result;
  11890. }
  11891. // Returns V8 version as a string.
  11892. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetV8Version) {
  11893. SealHandleScope shs(isolate);
  11894. ASSERT_EQ(args.length(), 0);
  11895. const char* version_string = v8::V8::GetVersion();
  11896. return isolate->heap()->AllocateStringFromOneByte(CStrVector(version_string),
  11897. NOT_TENURED);
  11898. }
  11899. RUNTIME_FUNCTION(MaybeObject*, Runtime_Abort) {
  11900. SealHandleScope shs(isolate);
  11901. ASSERT(args.length() == 2);
  11902. OS::PrintError("abort: %s\n",
  11903. reinterpret_cast<char*>(args[0]) + args.smi_at(1));
  11904. isolate->PrintStack(stderr);
  11905. OS::Abort();
  11906. UNREACHABLE();
  11907. return NULL;
  11908. }
  11909. RUNTIME_FUNCTION(MaybeObject*, Runtime_FlattenString) {
  11910. HandleScope scope(isolate);
  11911. ASSERT(args.length() == 1);
  11912. CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
  11913. FlattenString(str);
  11914. return isolate->heap()->undefined_value();
  11915. }
  11916. RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyContextDisposed) {
  11917. HandleScope scope(isolate);
  11918. ASSERT(args.length() == 0);
  11919. isolate->heap()->NotifyContextDisposed();
  11920. return isolate->heap()->undefined_value();
  11921. }
  11922. RUNTIME_FUNCTION(MaybeObject*, Runtime_MigrateInstance) {
  11923. HandleScope scope(isolate);
  11924. ASSERT(args.length() == 1);
  11925. CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
  11926. if (!object->IsJSObject()) return Smi::FromInt(0);
  11927. Handle<JSObject> js_object = Handle<JSObject>::cast(object);
  11928. if (!js_object->map()->is_deprecated()) return Smi::FromInt(0);
  11929. JSObject::MigrateInstance(js_object);
  11930. return *object;
  11931. }
  11932. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFromCache) {
  11933. SealHandleScope shs(isolate);
  11934. // This is only called from codegen, so checks might be more lax.
  11935. CONVERT_ARG_CHECKED(JSFunctionResultCache, cache, 0);
  11936. Object* key = args[1];
  11937. int finger_index = cache->finger_index();
  11938. Object* o = cache->get(finger_index);
  11939. if (o == key) {
  11940. // The fastest case: hit the same place again.
  11941. return cache->get(finger_index + 1);
  11942. }
  11943. for (int i = finger_index - 2;
  11944. i >= JSFunctionResultCache::kEntriesIndex;
  11945. i -= 2) {
  11946. o = cache->get(i);
  11947. if (o == key) {
  11948. cache->set_finger_index(i);
  11949. return cache->get(i + 1);
  11950. }
  11951. }
  11952. int size = cache->size();
  11953. ASSERT(size <= cache->length());
  11954. for (int i = size - 2; i > finger_index; i -= 2) {
  11955. o = cache->get(i);
  11956. if (o == key) {
  11957. cache->set_finger_index(i);
  11958. return cache->get(i + 1);
  11959. }
  11960. }
  11961. // There is no value in the cache. Invoke the function and cache result.
  11962. HandleScope scope(isolate);
  11963. Handle<JSFunctionResultCache> cache_handle(cache);
  11964. Handle<Object> key_handle(key, isolate);
  11965. Handle<Object> value;
  11966. {
  11967. Handle<JSFunction> factory(JSFunction::cast(
  11968. cache_handle->get(JSFunctionResultCache::kFactoryIndex)));
  11969. // TODO(antonm): consider passing a receiver when constructing a cache.
  11970. Handle<Object> receiver(isolate->native_context()->global_object(),
  11971. isolate);
  11972. // This handle is nor shared, nor used later, so it's safe.
  11973. Handle<Object> argv[] = { key_handle };
  11974. bool pending_exception;
  11975. value = Execution::Call(factory,
  11976. receiver,
  11977. ARRAY_SIZE(argv),
  11978. argv,
  11979. &pending_exception);
  11980. if (pending_exception) return Failure::Exception();
  11981. }
  11982. #ifdef VERIFY_HEAP
  11983. if (FLAG_verify_heap) {
  11984. cache_handle->JSFunctionResultCacheVerify();
  11985. }
  11986. #endif
  11987. // Function invocation may have cleared the cache. Reread all the data.
  11988. finger_index = cache_handle->finger_index();
  11989. size = cache_handle->size();
  11990. // If we have spare room, put new data into it, otherwise evict post finger
  11991. // entry which is likely to be the least recently used.
  11992. int index = -1;
  11993. if (size < cache_handle->length()) {
  11994. cache_handle->set_size(size + JSFunctionResultCache::kEntrySize);
  11995. index = size;
  11996. } else {
  11997. index = finger_index + JSFunctionResultCache::kEntrySize;
  11998. if (index == cache_handle->length()) {
  11999. index = JSFunctionResultCache::kEntriesIndex;
  12000. }
  12001. }
  12002. ASSERT(index % 2 == 0);
  12003. ASSERT(index >= JSFunctionResultCache::kEntriesIndex);
  12004. ASSERT(index < cache_handle->length());
  12005. cache_handle->set(index, *key_handle);
  12006. cache_handle->set(index + 1, *value);
  12007. cache_handle->set_finger_index(index);
  12008. #ifdef VERIFY_HEAP
  12009. if (FLAG_verify_heap) {
  12010. cache_handle->JSFunctionResultCacheVerify();
  12011. }
  12012. #endif
  12013. return *value;
  12014. }
  12015. RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetStartPosition) {
  12016. SealHandleScope shs(isolate);
  12017. CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
  12018. return Smi::FromInt(message->start_position());
  12019. }
  12020. RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetScript) {
  12021. SealHandleScope shs(isolate);
  12022. CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
  12023. return message->script();
  12024. }
  12025. #ifdef DEBUG
  12026. // ListNatives is ONLY used by the fuzz-natives.js in debug mode
  12027. // Exclude the code in release mode.
  12028. RUNTIME_FUNCTION(MaybeObject*, Runtime_ListNatives) {
  12029. HandleScope scope(isolate);
  12030. ASSERT(args.length() == 0);
  12031. #define COUNT_ENTRY(Name, argc, ressize) + 1
  12032. int entry_count = 0
  12033. RUNTIME_FUNCTION_LIST(COUNT_ENTRY)
  12034. INLINE_FUNCTION_LIST(COUNT_ENTRY)
  12035. INLINE_RUNTIME_FUNCTION_LIST(COUNT_ENTRY);
  12036. #undef COUNT_ENTRY
  12037. Factory* factory = isolate->factory();
  12038. Handle<FixedArray> elements = factory->NewFixedArray(entry_count);
  12039. int index = 0;
  12040. bool inline_runtime_functions = false;
  12041. #define ADD_ENTRY(Name, argc, ressize) \
  12042. { \
  12043. HandleScope inner(isolate); \
  12044. Handle<String> name; \
  12045. /* Inline runtime functions have an underscore in front of the name. */ \
  12046. if (inline_runtime_functions) { \
  12047. name = factory->NewStringFromAscii( \
  12048. Vector<const char>("_" #Name, StrLength("_" #Name))); \
  12049. } else { \
  12050. name = factory->NewStringFromAscii( \
  12051. Vector<const char>(#Name, StrLength(#Name))); \
  12052. } \
  12053. Handle<FixedArray> pair_elements = factory->NewFixedArray(2); \
  12054. pair_elements->set(0, *name); \
  12055. pair_elements->set(1, Smi::FromInt(argc)); \
  12056. Handle<JSArray> pair = factory->NewJSArrayWithElements(pair_elements); \
  12057. elements->set(index++, *pair); \
  12058. }
  12059. inline_runtime_functions = false;
  12060. RUNTIME_FUNCTION_LIST(ADD_ENTRY)
  12061. inline_runtime_functions = true;
  12062. INLINE_FUNCTION_LIST(ADD_ENTRY)
  12063. INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY)
  12064. #undef ADD_ENTRY
  12065. ASSERT_EQ(index, entry_count);
  12066. Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
  12067. return *result;
  12068. }
  12069. #endif
  12070. RUNTIME_FUNCTION(MaybeObject*, Runtime_Log) {
  12071. SealHandleScope shs(isolate);
  12072. ASSERT(args.length() == 2);
  12073. CONVERT_ARG_CHECKED(String, format, 0);
  12074. CONVERT_ARG_CHECKED(JSArray, elms, 1);
  12075. DisallowHeapAllocation no_gc;
  12076. String::FlatContent format_content = format->GetFlatContent();
  12077. RUNTIME_ASSERT(format_content.IsAscii());
  12078. Vector<const uint8_t> chars = format_content.ToOneByteVector();
  12079. isolate->logger()->LogRuntime(Vector<const char>::cast(chars), elms);
  12080. return isolate->heap()->undefined_value();
  12081. }
  12082. RUNTIME_FUNCTION(MaybeObject*, Runtime_IS_VAR) {
  12083. UNREACHABLE(); // implemented as macro in the parser
  12084. return NULL;
  12085. }
  12086. #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \
  12087. RUNTIME_FUNCTION(MaybeObject*, Runtime_Has##Name) { \
  12088. CONVERT_ARG_CHECKED(JSObject, obj, 0); \
  12089. return isolate->heap()->ToBoolean(obj->Has##Name()); \
  12090. }
  12091. ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiElements)
  12092. ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements)
  12093. ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements)
  12094. ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
  12095. ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
  12096. ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
  12097. ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(NonStrictArgumentsElements)
  12098. ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalPixelElements)
  12099. ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
  12100. ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalByteElements)
  12101. ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedByteElements)
  12102. ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalShortElements)
  12103. ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedShortElements)
  12104. ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalIntElements)
  12105. ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedIntElements)
  12106. ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalFloatElements)
  12107. ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalDoubleElements)
  12108. // Properties test sitting with elements tests - not fooling anyone.
  12109. ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties)
  12110. #undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
  12111. RUNTIME_FUNCTION(MaybeObject*, Runtime_HaveSameMap) {
  12112. SealHandleScope shs(isolate);
  12113. ASSERT(args.length() == 2);
  12114. CONVERT_ARG_CHECKED(JSObject, obj1, 0);
  12115. CONVERT_ARG_CHECKED(JSObject, obj2, 1);
  12116. return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
  12117. }
  12118. RUNTIME_FUNCTION(MaybeObject*, Runtime_IsObserved) {
  12119. SealHandleScope shs(isolate);
  12120. ASSERT(args.length() == 1);
  12121. if (!args[0]->IsJSReceiver()) return isolate->heap()->false_value();
  12122. JSReceiver* obj = JSReceiver::cast(args[0]);
  12123. if (obj->IsJSGlobalProxy()) {
  12124. Object* proto = obj->GetPrototype();
  12125. if (proto->IsNull()) return isolate->heap()->false_value();
  12126. ASSERT(proto->IsJSGlobalObject());
  12127. obj = JSReceiver::cast(proto);
  12128. }
  12129. return isolate->heap()->ToBoolean(obj->map()->is_observed());
  12130. }
  12131. RUNTIME_FUNCTION(MaybeObject*, Runtime_SetIsObserved) {
  12132. SealHandleScope shs(isolate);
  12133. ASSERT(args.length() == 1);
  12134. CONVERT_ARG_CHECKED(JSReceiver, obj, 0);
  12135. if (obj->IsJSGlobalProxy()) {
  12136. Object* proto = obj->GetPrototype();
  12137. if (proto->IsNull()) return isolate->heap()->undefined_value();
  12138. ASSERT(proto->IsJSGlobalObject());
  12139. obj = JSReceiver::cast(proto);
  12140. }
  12141. if (obj->IsJSProxy())
  12142. return isolate->heap()->undefined_value();
  12143. ASSERT(!(obj->map()->is_observed() && obj->IsJSObject() &&
  12144. JSObject::cast(obj)->HasFastElements()));
  12145. ASSERT(obj->IsJSObject());
  12146. return JSObject::cast(obj)->SetObserved(isolate);
  12147. }
  12148. RUNTIME_FUNCTION(MaybeObject*, Runtime_SetObserverDeliveryPending) {
  12149. SealHandleScope shs(isolate);
  12150. ASSERT(args.length() == 0);
  12151. isolate->set_observer_delivery_pending(true);
  12152. return isolate->heap()->undefined_value();
  12153. }
  12154. RUNTIME_FUNCTION(MaybeObject*, Runtime_GetObservationState) {
  12155. SealHandleScope shs(isolate);
  12156. ASSERT(args.length() == 0);
  12157. return isolate->heap()->observation_state();
  12158. }
  12159. RUNTIME_FUNCTION(MaybeObject*, Runtime_ObservationWeakMapCreate) {
  12160. HandleScope scope(isolate);
  12161. ASSERT(args.length() == 0);
  12162. // TODO(adamk): Currently this runtime function is only called three times per
  12163. // isolate. If it's called more often, the map should be moved into the
  12164. // strong root list.
  12165. Handle<Map> map =
  12166. isolate->factory()->NewMap(JS_WEAK_MAP_TYPE, JSWeakMap::kSize);
  12167. Handle<JSWeakMap> weakmap =
  12168. Handle<JSWeakMap>::cast(isolate->factory()->NewJSObjectFromMap(map));
  12169. return WeakCollectionInitialize(isolate, weakmap);
  12170. }
  12171. RUNTIME_FUNCTION(MaybeObject*, Runtime_UnwrapGlobalProxy) {
  12172. SealHandleScope shs(isolate);
  12173. ASSERT(args.length() == 1);
  12174. Object* object = args[0];
  12175. if (object->IsJSGlobalProxy()) {
  12176. object = object->GetPrototype(isolate);
  12177. if (object->IsNull()) return isolate->heap()->undefined_value();
  12178. }
  12179. return object;
  12180. }
  12181. static MaybeObject* ArrayConstructorCommon(Isolate* isolate,
  12182. Handle<JSFunction> constructor,
  12183. Handle<Object> type_info,
  12184. Arguments* caller_args) {
  12185. bool holey = false;
  12186. bool can_use_type_feedback = true;
  12187. if (caller_args->length() == 1) {
  12188. Object* argument_one = (*caller_args)[0];
  12189. if (argument_one->IsSmi()) {
  12190. int value = Smi::cast(argument_one)->value();
  12191. if (value < 0 || value >= JSObject::kInitialMaxFastElementArray) {
  12192. // the array is a dictionary in this case.
  12193. can_use_type_feedback = false;
  12194. } else if (value != 0) {
  12195. holey = true;
  12196. }
  12197. } else {
  12198. // Non-smi length argument produces a dictionary
  12199. can_use_type_feedback = false;
  12200. }
  12201. }
  12202. JSArray* array;
  12203. MaybeObject* maybe_array;
  12204. if (!type_info.is_null() &&
  12205. *type_info != isolate->heap()->undefined_value() &&
  12206. Cell::cast(*type_info)->value()->IsAllocationSite() &&
  12207. can_use_type_feedback) {
  12208. Handle<Cell> cell = Handle<Cell>::cast(type_info);
  12209. Handle<AllocationSite> site = Handle<AllocationSite>(
  12210. AllocationSite::cast(cell->value()), isolate);
  12211. ASSERT(!site->IsLiteralSite());
  12212. ElementsKind to_kind = site->GetElementsKind();
  12213. if (holey && !IsFastHoleyElementsKind(to_kind)) {
  12214. to_kind = GetHoleyElementsKind(to_kind);
  12215. // Update the allocation site info to reflect the advice alteration.
  12216. site->SetElementsKind(to_kind);
  12217. }
  12218. maybe_array = isolate->heap()->AllocateJSObjectWithAllocationSite(
  12219. *constructor, site);
  12220. if (!maybe_array->To(&array)) return maybe_array;
  12221. } else {
  12222. maybe_array = isolate->heap()->AllocateJSObject(*constructor);
  12223. if (!maybe_array->To(&array)) return maybe_array;
  12224. // We might need to transition to holey
  12225. ElementsKind kind = constructor->initial_map()->elements_kind();
  12226. if (holey && !IsFastHoleyElementsKind(kind)) {
  12227. kind = GetHoleyElementsKind(kind);
  12228. maybe_array = array->TransitionElementsKind(kind);
  12229. if (maybe_array->IsFailure()) return maybe_array;
  12230. }
  12231. }
  12232. maybe_array = isolate->heap()->AllocateJSArrayStorage(array, 0, 0,
  12233. DONT_INITIALIZE_ARRAY_ELEMENTS);
  12234. if (maybe_array->IsFailure()) return maybe_array;
  12235. maybe_array = ArrayConstructInitializeElements(array, caller_args);
  12236. if (maybe_array->IsFailure()) return maybe_array;
  12237. return array;
  12238. }
  12239. RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConstructor) {
  12240. HandleScope scope(isolate);
  12241. // If we get 2 arguments then they are the stub parameters (constructor, type
  12242. // info). If we get 3, then the first one is a pointer to the arguments
  12243. // passed by the caller.
  12244. Arguments empty_args(0, NULL);
  12245. bool no_caller_args = args.length() == 2;
  12246. ASSERT(no_caller_args || args.length() == 3);
  12247. int parameters_start = no_caller_args ? 0 : 1;
  12248. Arguments* caller_args = no_caller_args