OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 ThrowException( | 311 ThrowException( |
312 String::New("Array length exceeds maximum length.")); | 312 String::New("Array length exceeds maximum length.")); |
313 } | 313 } |
314 return static_cast<size_t>(raw_value); | 314 return static_cast<size_t>(raw_value); |
315 } | 315 } |
316 | 316 |
317 | 317 |
318 const char kArrayBufferReferencePropName[] = "_is_array_buffer_"; | 318 const char kArrayBufferReferencePropName[] = "_is_array_buffer_"; |
319 const char kArrayBufferMarkerPropName[] = "_array_buffer_ref_"; | 319 const char kArrayBufferMarkerPropName[] = "_array_buffer_ref_"; |
320 | 320 |
| 321 static const int kExternalArrayAllocationHeaderSize = 2; |
321 | 322 |
322 Handle<Value> Shell::CreateExternalArray(const Arguments& args, | 323 Handle<Value> Shell::CreateExternalArray(const Arguments& args, |
323 ExternalArrayType type, | 324 ExternalArrayType type, |
324 size_t element_size) { | 325 size_t element_size) { |
325 TryCatch try_catch; | 326 TryCatch try_catch; |
326 bool is_array_buffer_construct = element_size == 0; | 327 bool is_array_buffer_construct = element_size == 0; |
327 if (is_array_buffer_construct) { | 328 if (is_array_buffer_construct) { |
328 type = v8::kExternalByteArray; | 329 type = v8::kExternalByteArray; |
329 element_size = 1; | 330 element_size = 1; |
330 } | 331 } |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 } | 427 } |
427 | 428 |
428 Persistent<Object> persistent_array = Persistent<Object>::New(array); | 429 Persistent<Object> persistent_array = Persistent<Object>::New(array); |
429 if (data == NULL && length != 0) { | 430 if (data == NULL && length != 0) { |
430 // Make sure the total size fits into a (signed) int. | 431 // Make sure the total size fits into a (signed) int. |
431 static const int kMaxSize = 0x7fffffff; | 432 static const int kMaxSize = 0x7fffffff; |
432 if (length > (kMaxSize - sizeof(size_t)) / element_size) { | 433 if (length > (kMaxSize - sizeof(size_t)) / element_size) { |
433 return ThrowException(String::New("Array exceeds maximum size (2G)")); | 434 return ThrowException(String::New("Array exceeds maximum size (2G)")); |
434 } | 435 } |
435 // Prepend the size of the allocated chunk to the data itself. | 436 // Prepend the size of the allocated chunk to the data itself. |
436 int total_size = length * element_size + sizeof(size_t); | 437 int total_size = length * element_size + |
| 438 kExternalArrayAllocationHeaderSize * sizeof(size_t); |
437 data = malloc(total_size); | 439 data = malloc(total_size); |
438 if (data == NULL) { | 440 if (data == NULL) { |
439 return ThrowException(String::New("Memory allocation failed.")); | 441 return ThrowException(String::New("Memory allocation failed.")); |
440 } | 442 } |
441 *reinterpret_cast<size_t*>(data) = total_size; | 443 *reinterpret_cast<size_t*>(data) = total_size; |
442 data = reinterpret_cast<size_t*>(data) + 1; | 444 data = reinterpret_cast<size_t*>(data) + kExternalArrayAllocationHeaderSize; |
443 memset(data, 0, length * element_size); | 445 memset(data, 0, length * element_size); |
444 V8::AdjustAmountOfExternalAllocatedMemory(total_size); | 446 V8::AdjustAmountOfExternalAllocatedMemory(total_size); |
445 } | 447 } |
446 persistent_array.MakeWeak(data, ExternalArrayWeakCallback); | 448 persistent_array.MakeWeak(data, ExternalArrayWeakCallback); |
447 persistent_array.MarkIndependent(); | 449 persistent_array.MarkIndependent(); |
448 | 450 |
449 array->SetIndexedPropertiesToExternalArrayData( | 451 array->SetIndexedPropertiesToExternalArrayData( |
450 reinterpret_cast<uint8_t*>(data) + offset, type, | 452 reinterpret_cast<uint8_t*>(data) + offset, type, |
451 static_cast<int>(length)); | 453 static_cast<int>(length)); |
452 array->Set(String::New("length"), | 454 array->Set(String::New("length"), |
453 Int32::New(static_cast<int32_t>(length)), ReadOnly); | 455 Int32::New(static_cast<int32_t>(length)), ReadOnly); |
454 array->Set(String::New("BYTES_PER_ELEMENT"), | 456 array->Set(String::New("BYTES_PER_ELEMENT"), |
455 Int32::New(static_cast<int32_t>(element_size))); | 457 Int32::New(static_cast<int32_t>(element_size))); |
456 return array; | 458 return array; |
457 } | 459 } |
458 | 460 |
459 | 461 |
460 void Shell::ExternalArrayWeakCallback(Persistent<Value> object, void* data) { | 462 void Shell::ExternalArrayWeakCallback(Persistent<Value> object, void* data) { |
461 HandleScope scope; | 463 HandleScope scope; |
462 Handle<String> prop_name = String::New(kArrayBufferReferencePropName); | 464 Handle<String> prop_name = String::New(kArrayBufferReferencePropName); |
463 Handle<Object> converted_object = object->ToObject(); | 465 Handle<Object> converted_object = object->ToObject(); |
464 Local<Value> prop_value = converted_object->Get(prop_name); | 466 Local<Value> prop_value = converted_object->Get(prop_name); |
465 if (data != NULL && !prop_value->IsObject()) { | 467 if (data != NULL && !prop_value->IsObject()) { |
466 data = reinterpret_cast<size_t*>(data) - 1; | 468 data = reinterpret_cast<size_t*>(data) - kExternalArrayAllocationHeaderSize; |
467 V8::AdjustAmountOfExternalAllocatedMemory( | 469 V8::AdjustAmountOfExternalAllocatedMemory( |
468 -static_cast<int>(*reinterpret_cast<size_t*>(data))); | 470 -static_cast<int>(*reinterpret_cast<size_t*>(data))); |
469 free(data); | 471 free(data); |
470 } | 472 } |
471 object.Dispose(); | 473 object.Dispose(); |
472 } | 474 } |
473 | 475 |
474 | 476 |
475 Handle<Value> Shell::ArrayBuffer(const Arguments& args) { | 477 Handle<Value> Shell::ArrayBuffer(const Arguments& args) { |
476 return CreateExternalArray(args, v8::kExternalByteArray, 0); | 478 return CreateExternalArray(args, v8::kExternalByteArray, 0); |
(...skipping 1076 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1553 } | 1555 } |
1554 | 1556 |
1555 } // namespace v8 | 1557 } // namespace v8 |
1556 | 1558 |
1557 | 1559 |
1558 #ifndef GOOGLE3 | 1560 #ifndef GOOGLE3 |
1559 int main(int argc, char* argv[]) { | 1561 int main(int argc, char* argv[]) { |
1560 return v8::Shell::Main(argc, argv); | 1562 return v8::Shell::Main(argc, argv); |
1561 } | 1563 } |
1562 #endif | 1564 #endif |
OLD | NEW |