PageRenderTime 74ms CodeModel.GetById 25ms RepoModel.GetById 1ms 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

Large files files are truncated, but you can click here to view the full file

  1. // Copyright 2012 the V8 project authors. All rights reserved.
  2. // Redistribution and use in source and binary forms, with or without
  3. // modification, are permitted provided that the following conditions are
  4. // met:
  5. //
  6. // * Redistributions of source code must retain the above copyright
  7. // notice, this list of conditions and the following disclaimer.
  8. // * Redistributions in binary form must reproduce the above
  9. // copyright notice, this list of conditions and the following
  10. // disclaimer in the documentation and/or other materials provided
  11. // with the distribution.
  12. // * Neither the name of Google Inc. nor the names of its
  13. // contributors may be used to endorse or promote products derived
  14. // from this software without specific prior written permission.
  15. //
  16. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  17. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  18. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  19. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  20. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  21. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  22. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  26. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. #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( \

Large files files are truncated, but you can click here to view the full file