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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 #if !defined(_WIN32) && !defined(_WIN64) | 60 #if !defined(_WIN32) && !defined(_WIN64) |
61 #include <unistd.h> // NOLINT | 61 #include <unistd.h> // NOLINT |
62 #endif | 62 #endif |
63 | 63 |
64 #ifndef ASSERT | 64 #ifndef ASSERT |
65 #define ASSERT(condition) assert(condition) | 65 #define ASSERT(condition) assert(condition) |
66 #endif | 66 #endif |
67 | 67 |
68 namespace v8 { | 68 namespace v8 { |
69 | 69 |
| 70 |
| 71 static Handle<Value> Throw(const char* message) { |
| 72 return ThrowException(String::New(message)); |
| 73 } |
| 74 |
| 75 |
| 76 // TODO(rossberg): should replace these by proper uses of HasInstance, |
| 77 // once we figure out a good way to make the templates global. |
| 78 const char kArrayBufferMarkerPropName[] = "d8::_is_array_buffer_"; |
| 79 const char kArrayMarkerPropName[] = "d8::_is_typed_array_"; |
| 80 |
| 81 |
| 82 #define FOR_EACH_SYMBOL(V) \ |
| 83 V(ArrayBuffer, "ArrayBuffer") \ |
| 84 V(ArrayBufferMarkerPropName, kArrayBufferMarkerPropName) \ |
| 85 V(ArrayMarkerPropName, kArrayMarkerPropName) \ |
| 86 V(buffer, "buffer") \ |
| 87 V(byteLength, "byteLength") \ |
| 88 V(byteOffset, "byteOffset") \ |
| 89 V(BYTES_PER_ELEMENT, "BYTES_PER_ELEMENT") \ |
| 90 V(length, "length") |
| 91 |
| 92 |
| 93 class Symbols { |
| 94 public: |
| 95 explicit Symbols(Isolate* isolate) : isolate_(isolate) { |
| 96 HandleScope scope; |
| 97 #define INIT_SYMBOL(name, value) \ |
| 98 name##_ = Persistent<String>::New(String::NewSymbol(value)); |
| 99 FOR_EACH_SYMBOL(INIT_SYMBOL) |
| 100 #undef INIT_SYMBOL |
| 101 isolate->SetData(this); |
| 102 } |
| 103 |
| 104 ~Symbols() { |
| 105 #define DISPOSE_SYMBOL(name, value) name##_.Dispose(); |
| 106 FOR_EACH_SYMBOL(DISPOSE_SYMBOL) |
| 107 #undef DISPOSE_SYMBOL |
| 108 isolate_->SetData(NULL); // Not really needed, just to be sure... |
| 109 } |
| 110 |
| 111 #define DEFINE_SYMBOL_GETTER(name, value) \ |
| 112 static Persistent<String> name(Isolate* isolate) { \ |
| 113 return reinterpret_cast<Symbols*>(isolate->GetData())->name##_; \ |
| 114 } |
| 115 FOR_EACH_SYMBOL(DEFINE_SYMBOL_GETTER) |
| 116 #undef DEFINE_SYMBOL_GETTER |
| 117 |
| 118 private: |
| 119 Isolate* isolate_; |
| 120 #define DEFINE_MEMBER(name, value) Persistent<String> name##_; |
| 121 FOR_EACH_SYMBOL(DEFINE_MEMBER) |
| 122 #undef DEFINE_MEMBER |
| 123 }; |
| 124 |
| 125 |
70 LineEditor *LineEditor::first_ = NULL; | 126 LineEditor *LineEditor::first_ = NULL; |
71 | 127 |
72 | 128 |
73 LineEditor::LineEditor(Type type, const char* name) | 129 LineEditor::LineEditor(Type type, const char* name) |
74 : type_(type), | 130 : type_(type), |
75 name_(name), | 131 name_(name), |
76 next_(first_) { | 132 next_(first_) { |
77 first_ = this; | 133 first_ = this; |
78 } | 134 } |
79 | 135 |
80 | 136 |
81 LineEditor* LineEditor::Get() { | 137 LineEditor* LineEditor::Get() { |
82 LineEditor* current = first_; | 138 LineEditor* current = first_; |
83 LineEditor* best = current; | 139 LineEditor* best = current; |
84 while (current != NULL) { | 140 while (current != NULL) { |
85 if (current->type_ > best->type_) | 141 if (current->type_ > best->type_) |
86 best = current; | 142 best = current; |
87 current = current->next_; | 143 current = current->next_; |
88 } | 144 } |
89 return best; | 145 return best; |
90 } | 146 } |
91 | 147 |
92 | 148 |
93 class DumbLineEditor: public LineEditor { | 149 class DumbLineEditor: public LineEditor { |
94 public: | 150 public: |
95 DumbLineEditor() : LineEditor(LineEditor::DUMB, "dumb") { } | 151 explicit DumbLineEditor(Isolate* isolate) |
| 152 : LineEditor(LineEditor::DUMB, "dumb"), isolate_(isolate) { } |
96 virtual Handle<String> Prompt(const char* prompt); | 153 virtual Handle<String> Prompt(const char* prompt); |
| 154 private: |
| 155 Isolate* isolate_; |
97 }; | 156 }; |
98 | 157 |
99 | 158 |
100 static DumbLineEditor dumb_line_editor; | |
101 | |
102 | |
103 Handle<String> DumbLineEditor::Prompt(const char* prompt) { | 159 Handle<String> DumbLineEditor::Prompt(const char* prompt) { |
104 printf("%s", prompt); | 160 printf("%s", prompt); |
105 return Shell::ReadFromStdin(); | 161 return Shell::ReadFromStdin(isolate_); |
106 } | 162 } |
107 | 163 |
108 | 164 |
109 #ifndef V8_SHARED | 165 #ifndef V8_SHARED |
110 CounterMap* Shell::counter_map_; | 166 CounterMap* Shell::counter_map_; |
111 i::OS::MemoryMappedFile* Shell::counters_file_ = NULL; | 167 i::OS::MemoryMappedFile* Shell::counters_file_ = NULL; |
112 CounterCollection Shell::local_counters_; | 168 CounterCollection Shell::local_counters_; |
113 CounterCollection* Shell::counters_ = &local_counters_; | 169 CounterCollection* Shell::counters_ = &local_counters_; |
114 i::Mutex* Shell::context_mutex_(i::OS::CreateMutex()); | 170 i::Mutex* Shell::context_mutex_(i::OS::CreateMutex()); |
115 Persistent<Context> Shell::utility_context_; | 171 Persistent<Context> Shell::utility_context_; |
116 #endif // V8_SHARED | 172 #endif // V8_SHARED |
117 | 173 |
118 LineEditor* Shell::console = NULL; | |
119 Persistent<Context> Shell::evaluation_context_; | 174 Persistent<Context> Shell::evaluation_context_; |
120 ShellOptions Shell::options; | 175 ShellOptions Shell::options; |
121 const char* Shell::kPrompt = "d8> "; | 176 const char* Shell::kPrompt = "d8> "; |
122 | 177 |
123 | 178 |
124 const int MB = 1024 * 1024; | 179 const int MB = 1024 * 1024; |
125 | 180 |
126 | 181 |
127 #ifndef V8_SHARED | 182 #ifndef V8_SHARED |
128 bool CounterMap::Match(void* key1, void* key2) { | 183 bool CounterMap::Match(void* key1, void* key2) { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 | 280 |
226 Handle<Value> Shell::DisableProfiler(const Arguments& args) { | 281 Handle<Value> Shell::DisableProfiler(const Arguments& args) { |
227 V8::PauseProfiler(); | 282 V8::PauseProfiler(); |
228 return Undefined(); | 283 return Undefined(); |
229 } | 284 } |
230 | 285 |
231 | 286 |
232 Handle<Value> Shell::Read(const Arguments& args) { | 287 Handle<Value> Shell::Read(const Arguments& args) { |
233 String::Utf8Value file(args[0]); | 288 String::Utf8Value file(args[0]); |
234 if (*file == NULL) { | 289 if (*file == NULL) { |
235 return ThrowException(String::New("Error loading file")); | 290 return Throw("Error loading file"); |
236 } | 291 } |
237 Handle<String> source = ReadFile(*file); | 292 Handle<String> source = ReadFile(args.GetIsolate(), *file); |
238 if (source.IsEmpty()) { | 293 if (source.IsEmpty()) { |
239 return ThrowException(String::New("Error loading file")); | 294 return Throw("Error loading file"); |
240 } | 295 } |
241 return source; | 296 return source; |
242 } | 297 } |
243 | 298 |
244 | 299 |
245 Handle<String> Shell::ReadFromStdin() { | 300 Handle<String> Shell::ReadFromStdin(Isolate* isolate) { |
246 static const int kBufferSize = 256; | 301 static const int kBufferSize = 256; |
247 char buffer[kBufferSize]; | 302 char buffer[kBufferSize]; |
248 Handle<String> accumulator = String::New(""); | 303 Handle<String> accumulator = String::New(""); |
249 int length; | 304 int length; |
250 while (true) { | 305 while (true) { |
251 // Continue reading if the line ends with an escape '\\' or the line has | 306 // Continue reading if the line ends with an escape '\\' or the line has |
252 // not been fully read into the buffer yet (does not end with '\n'). | 307 // not been fully read into the buffer yet (does not end with '\n'). |
253 // If fgets gets an error, just give up. | 308 // If fgets gets an error, just give up. |
254 char* input = NULL; | 309 char* input = NULL; |
255 { // Release lock for blocking input. | 310 { // Release lock for blocking input. |
256 Unlocker unlock(Isolate::GetCurrent()); | 311 Unlocker unlock(isolate); |
257 input = fgets(buffer, kBufferSize, stdin); | 312 input = fgets(buffer, kBufferSize, stdin); |
258 } | 313 } |
259 if (input == NULL) return Handle<String>(); | 314 if (input == NULL) return Handle<String>(); |
260 length = static_cast<int>(strlen(buffer)); | 315 length = static_cast<int>(strlen(buffer)); |
261 if (length == 0) { | 316 if (length == 0) { |
262 return accumulator; | 317 return accumulator; |
263 } else if (buffer[length-1] != '\n') { | 318 } else if (buffer[length-1] != '\n') { |
264 accumulator = String::Concat(accumulator, String::New(buffer, length)); | 319 accumulator = String::Concat(accumulator, String::New(buffer, length)); |
265 } else if (length > 1 && buffer[length-2] == '\\') { | 320 } else if (length > 1 && buffer[length-2] == '\\') { |
266 buffer[length-2] = '\n'; | 321 buffer[length-2] = '\n'; |
267 accumulator = String::Concat(accumulator, String::New(buffer, length-1)); | 322 accumulator = String::Concat(accumulator, String::New(buffer, length-1)); |
268 } else { | 323 } else { |
269 return String::Concat(accumulator, String::New(buffer, length-1)); | 324 return String::Concat(accumulator, String::New(buffer, length-1)); |
270 } | 325 } |
271 } | 326 } |
272 } | 327 } |
273 | 328 |
274 | 329 |
275 Handle<Value> Shell::Load(const Arguments& args) { | 330 Handle<Value> Shell::Load(const Arguments& args) { |
276 for (int i = 0; i < args.Length(); i++) { | 331 for (int i = 0; i < args.Length(); i++) { |
277 HandleScope handle_scope; | 332 HandleScope handle_scope; |
278 String::Utf8Value file(args[i]); | 333 String::Utf8Value file(args[i]); |
279 if (*file == NULL) { | 334 if (*file == NULL) { |
280 return ThrowException(String::New("Error loading file")); | 335 return Throw("Error loading file"); |
281 } | 336 } |
282 Handle<String> source = ReadFile(*file); | 337 Handle<String> source = ReadFile(args.GetIsolate(), *file); |
283 if (source.IsEmpty()) { | 338 if (source.IsEmpty()) { |
284 return ThrowException(String::New("Error loading file")); | 339 return Throw("Error loading file"); |
285 } | 340 } |
286 if (!ExecuteString(source, String::New(*file), false, true)) { | 341 if (!ExecuteString(source, String::New(*file), false, true)) { |
287 return ThrowException(String::New("Error executing file")); | 342 return Throw("Error executing file"); |
288 } | 343 } |
289 } | 344 } |
290 return Undefined(); | 345 return Undefined(); |
291 } | 346 } |
292 | 347 |
293 static int32_t convertToInt(Local<Value> value_in, TryCatch* try_catch) { | 348 static int32_t convertToInt(Local<Value> value_in, TryCatch* try_catch) { |
294 if (value_in->IsInt32()) { | 349 if (value_in->IsInt32()) { |
295 return value_in->Int32Value(); | 350 return value_in->Int32Value(); |
296 } | 351 } |
297 | 352 |
298 Local<Value> number = value_in->ToNumber(); | 353 Local<Value> number = value_in->ToNumber(); |
299 if (try_catch->HasCaught()) return 0; | 354 if (try_catch->HasCaught()) return 0; |
300 | 355 |
301 ASSERT(number->IsNumber()); | 356 ASSERT(number->IsNumber()); |
302 Local<Int32> int32 = number->ToInt32(); | 357 Local<Int32> int32 = number->ToInt32(); |
303 if (try_catch->HasCaught() || int32.IsEmpty()) return 0; | 358 if (try_catch->HasCaught() || int32.IsEmpty()) return 0; |
304 | 359 |
305 int32_t value = int32->Int32Value(); | 360 int32_t value = int32->Int32Value(); |
306 if (try_catch->HasCaught()) return 0; | 361 if (try_catch->HasCaught()) return 0; |
307 | 362 |
308 return value; | 363 return value; |
309 } | 364 } |
310 | 365 |
311 | 366 |
312 static int32_t convertToUint(Local<Value> value_in, TryCatch* try_catch) { | 367 static int32_t convertToUint(Local<Value> value_in, TryCatch* try_catch) { |
313 int32_t raw_value = convertToInt(value_in, try_catch); | 368 int32_t raw_value = convertToInt(value_in, try_catch); |
314 if (try_catch->HasCaught()) return 0; | 369 if (try_catch->HasCaught()) return 0; |
315 | 370 |
316 if (raw_value < 0) { | 371 if (raw_value < 0) { |
317 ThrowException(String::New("Array length must not be negative.")); | 372 Throw("Array length must not be negative."); |
318 return 0; | 373 return 0; |
319 } | 374 } |
320 | 375 |
321 static const int kMaxLength = 0x3fffffff; | 376 static const int kMaxLength = 0x3fffffff; |
322 #ifndef V8_SHARED | 377 #ifndef V8_SHARED |
323 ASSERT(kMaxLength == i::ExternalArray::kMaxLength); | 378 ASSERT(kMaxLength == i::ExternalArray::kMaxLength); |
324 #endif // V8_SHARED | 379 #endif // V8_SHARED |
325 if (raw_value > static_cast<int32_t>(kMaxLength)) { | 380 if (raw_value > static_cast<int32_t>(kMaxLength)) { |
326 ThrowException( | 381 Throw("Array length exceeds maximum length."); |
327 String::New("Array length exceeds maximum length.")); | |
328 } | 382 } |
329 return raw_value; | 383 return raw_value; |
330 } | 384 } |
331 | 385 |
332 | 386 |
333 // TODO(rossberg): should replace these by proper uses of HasInstance, | 387 Handle<Value> Shell::CreateExternalArrayBuffer(Isolate* isolate, |
334 // once we figure out a good way to make the templates global. | 388 Handle<Object> buffer, |
335 const char kArrayBufferMarkerPropName[] = "d8::_is_array_buffer_"; | |
336 const char kArrayMarkerPropName[] = "d8::_is_typed_array_"; | |
337 | |
338 | |
339 Handle<Value> Shell::CreateExternalArrayBuffer(Handle<Object> buffer, | |
340 int32_t length) { | 389 int32_t length) { |
341 static const int32_t kMaxSize = 0x7fffffff; | 390 static const int32_t kMaxSize = 0x7fffffff; |
342 // Make sure the total size fits into a (signed) int. | 391 // Make sure the total size fits into a (signed) int. |
343 if (length < 0 || length > kMaxSize) { | 392 if (length < 0 || length > kMaxSize) { |
344 return ThrowException(String::New("ArrayBuffer exceeds maximum size (2G)")); | 393 return Throw("ArrayBuffer exceeds maximum size (2G)"); |
345 } | 394 } |
346 uint8_t* data = new uint8_t[length]; | 395 uint8_t* data = new uint8_t[length]; |
347 if (data == NULL) { | 396 if (data == NULL) { |
348 return ThrowException(String::New("Memory allocation failed")); | 397 return Throw("Memory allocation failed"); |
349 } | 398 } |
350 memset(data, 0, length); | 399 memset(data, 0, length); |
351 | 400 |
352 buffer->SetHiddenValue(String::New(kArrayBufferMarkerPropName), True()); | 401 buffer->SetHiddenValue(Symbols::ArrayBufferMarkerPropName(isolate), True()); |
353 Persistent<Object> persistent_array = Persistent<Object>::New(buffer); | 402 Persistent<Object> persistent_array = Persistent<Object>::New(buffer); |
354 persistent_array.MakeWeak(data, ExternalArrayWeakCallback); | 403 persistent_array.MakeWeak(data, ExternalArrayWeakCallback); |
355 persistent_array.MarkIndependent(); | 404 persistent_array.MarkIndependent(); |
356 V8::AdjustAmountOfExternalAllocatedMemory(length); | 405 V8::AdjustAmountOfExternalAllocatedMemory(length); |
357 | 406 |
358 buffer->SetIndexedPropertiesToExternalArrayData( | 407 buffer->SetIndexedPropertiesToExternalArrayData( |
359 data, v8::kExternalByteArray, length); | 408 data, v8::kExternalByteArray, length); |
360 buffer->Set(String::New("byteLength"), Int32::New(length), ReadOnly); | 409 buffer->Set(Symbols::byteLength(isolate), Int32::New(length), ReadOnly); |
361 | 410 |
362 return buffer; | 411 return buffer; |
363 } | 412 } |
364 | 413 |
365 | 414 |
366 Handle<Value> Shell::ArrayBuffer(const Arguments& args) { | 415 Handle<Value> Shell::ArrayBuffer(const Arguments& args) { |
367 if (!args.IsConstructCall()) { | 416 if (!args.IsConstructCall()) { |
368 Handle<Value>* rec_args = new Handle<Value>[args.Length()]; | 417 Handle<Value>* rec_args = new Handle<Value>[args.Length()]; |
369 for (int i = 0; i < args.Length(); ++i) rec_args[i] = args[i]; | 418 for (int i = 0; i < args.Length(); ++i) rec_args[i] = args[i]; |
370 Handle<Value> result = args.Callee()->NewInstance(args.Length(), rec_args); | 419 Handle<Value> result = args.Callee()->NewInstance(args.Length(), rec_args); |
371 delete[] rec_args; | 420 delete[] rec_args; |
372 return result; | 421 return result; |
373 } | 422 } |
374 | 423 |
375 if (args.Length() == 0) { | 424 if (args.Length() == 0) { |
376 return ThrowException( | 425 return Throw("ArrayBuffer constructor must have one argument"); |
377 String::New("ArrayBuffer constructor must have one argument")); | |
378 } | 426 } |
379 TryCatch try_catch; | 427 TryCatch try_catch; |
380 int32_t length = convertToUint(args[0], &try_catch); | 428 int32_t length = convertToUint(args[0], &try_catch); |
381 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 429 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
382 | 430 |
383 return CreateExternalArrayBuffer(args.This(), length); | 431 return CreateExternalArrayBuffer(args.GetIsolate(), args.This(), length); |
384 } | 432 } |
385 | 433 |
386 | 434 |
387 Handle<Object> Shell::CreateExternalArray(Handle<Object> array, | 435 Handle<Object> Shell::CreateExternalArray(Isolate* isolate, |
| 436 Handle<Object> array, |
388 Handle<Object> buffer, | 437 Handle<Object> buffer, |
389 ExternalArrayType type, | 438 ExternalArrayType type, |
390 int32_t length, | 439 int32_t length, |
391 int32_t byteLength, | 440 int32_t byteLength, |
392 int32_t byteOffset, | 441 int32_t byteOffset, |
393 int32_t element_size) { | 442 int32_t element_size) { |
394 ASSERT(element_size == 1 || element_size == 2 || | 443 ASSERT(element_size == 1 || element_size == 2 || |
395 element_size == 4 || element_size == 8); | 444 element_size == 4 || element_size == 8); |
396 ASSERT(byteLength == length * element_size); | 445 ASSERT(byteLength == length * element_size); |
397 | 446 |
398 void* data = buffer->GetIndexedPropertiesExternalArrayData(); | 447 void* data = buffer->GetIndexedPropertiesExternalArrayData(); |
399 ASSERT(data != NULL); | 448 ASSERT(data != NULL); |
400 | 449 |
401 array->SetIndexedPropertiesToExternalArrayData( | 450 array->SetIndexedPropertiesToExternalArrayData( |
402 static_cast<uint8_t*>(data) + byteOffset, type, length); | 451 static_cast<uint8_t*>(data) + byteOffset, type, length); |
403 array->SetHiddenValue(String::New(kArrayMarkerPropName), Int32::New(type)); | 452 array->SetHiddenValue(Symbols::ArrayMarkerPropName(isolate), |
404 array->Set(String::New("byteLength"), Int32::New(byteLength), ReadOnly); | 453 Int32::New(type)); |
405 array->Set(String::New("byteOffset"), Int32::New(byteOffset), ReadOnly); | 454 array->Set(Symbols::byteLength(isolate), Int32::New(byteLength), ReadOnly); |
406 array->Set(String::New("length"), Int32::New(length), ReadOnly); | 455 array->Set(Symbols::byteOffset(isolate), Int32::New(byteOffset), ReadOnly); |
407 array->Set(String::New("BYTES_PER_ELEMENT"), Int32::New(element_size)); | 456 array->Set(Symbols::length(isolate), Int32::New(length), ReadOnly); |
408 array->Set(String::New("buffer"), buffer, ReadOnly); | 457 array->Set(Symbols::BYTES_PER_ELEMENT(isolate), Int32::New(element_size)); |
| 458 array->Set(Symbols::buffer(isolate), buffer, ReadOnly); |
409 | 459 |
410 return array; | 460 return array; |
411 } | 461 } |
412 | 462 |
413 | 463 |
414 Handle<Value> Shell::CreateExternalArray(const Arguments& args, | 464 Handle<Value> Shell::CreateExternalArray(const Arguments& args, |
415 ExternalArrayType type, | 465 ExternalArrayType type, |
416 int32_t element_size) { | 466 int32_t element_size) { |
| 467 Isolate* isolate = args.GetIsolate(); |
417 if (!args.IsConstructCall()) { | 468 if (!args.IsConstructCall()) { |
418 Handle<Value>* rec_args = new Handle<Value>[args.Length()]; | 469 Handle<Value>* rec_args = new Handle<Value>[args.Length()]; |
419 for (int i = 0; i < args.Length(); ++i) rec_args[i] = args[i]; | 470 for (int i = 0; i < args.Length(); ++i) rec_args[i] = args[i]; |
420 Handle<Value> result = args.Callee()->NewInstance(args.Length(), rec_args); | 471 Handle<Value> result = args.Callee()->NewInstance(args.Length(), rec_args); |
421 delete[] rec_args; | 472 delete[] rec_args; |
422 return result; | 473 return result; |
423 } | 474 } |
424 | 475 |
425 TryCatch try_catch; | 476 TryCatch try_catch; |
426 ASSERT(element_size == 1 || element_size == 2 || | 477 ASSERT(element_size == 1 || element_size == 2 || |
427 element_size == 4 || element_size == 8); | 478 element_size == 4 || element_size == 8); |
428 | 479 |
429 // All of the following constructors are supported: | 480 // All of the following constructors are supported: |
430 // TypedArray(unsigned long length) | 481 // TypedArray(unsigned long length) |
431 // TypedArray(type[] array) | 482 // TypedArray(type[] array) |
432 // TypedArray(TypedArray array) | 483 // TypedArray(TypedArray array) |
433 // TypedArray(ArrayBuffer buffer, | 484 // TypedArray(ArrayBuffer buffer, |
434 // optional unsigned long byteOffset, | 485 // optional unsigned long byteOffset, |
435 // optional unsigned long length) | 486 // optional unsigned long length) |
436 Handle<Object> buffer; | 487 Handle<Object> buffer; |
437 int32_t length; | 488 int32_t length; |
438 int32_t byteLength; | 489 int32_t byteLength; |
439 int32_t byteOffset; | 490 int32_t byteOffset; |
440 bool init_from_array = false; | 491 bool init_from_array = false; |
441 if (args.Length() == 0) { | 492 if (args.Length() == 0) { |
442 return ThrowException( | 493 return Throw("Array constructor must have at least one argument"); |
443 String::New("Array constructor must have at least one argument")); | |
444 } | 494 } |
445 if (args[0]->IsObject() && | 495 if (args[0]->IsObject() && |
446 !args[0]->ToObject()->GetHiddenValue( | 496 !args[0]->ToObject()->GetHiddenValue( |
447 String::New(kArrayBufferMarkerPropName)).IsEmpty()) { | 497 Symbols::ArrayBufferMarkerPropName(isolate)).IsEmpty()) { |
448 // Construct from ArrayBuffer. | 498 // Construct from ArrayBuffer. |
449 buffer = args[0]->ToObject(); | 499 buffer = args[0]->ToObject(); |
450 int32_t bufferLength = | 500 int32_t bufferLength = |
451 convertToUint(buffer->Get(String::New("byteLength")), &try_catch); | 501 convertToUint(buffer->Get(Symbols::byteLength(isolate)), &try_catch); |
452 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 502 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
453 | 503 |
454 if (args.Length() < 2 || args[1]->IsUndefined()) { | 504 if (args.Length() < 2 || args[1]->IsUndefined()) { |
455 byteOffset = 0; | 505 byteOffset = 0; |
456 } else { | 506 } else { |
457 byteOffset = convertToUint(args[1], &try_catch); | 507 byteOffset = convertToUint(args[1], &try_catch); |
458 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 508 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
459 if (byteOffset > bufferLength) { | 509 if (byteOffset > bufferLength) { |
460 return ThrowException(String::New("byteOffset out of bounds")); | 510 return Throw("byteOffset out of bounds"); |
461 } | 511 } |
462 if (byteOffset % element_size != 0) { | 512 if (byteOffset % element_size != 0) { |
463 return ThrowException( | 513 return Throw("byteOffset must be multiple of element size"); |
464 String::New("byteOffset must be multiple of element size")); | |
465 } | 514 } |
466 } | 515 } |
467 | 516 |
468 if (args.Length() < 3 || args[2]->IsUndefined()) { | 517 if (args.Length() < 3 || args[2]->IsUndefined()) { |
469 byteLength = bufferLength - byteOffset; | 518 byteLength = bufferLength - byteOffset; |
470 length = byteLength / element_size; | 519 length = byteLength / element_size; |
471 if (byteLength % element_size != 0) { | 520 if (byteLength % element_size != 0) { |
472 return ThrowException( | 521 return Throw("buffer size must be multiple of element size"); |
473 String::New("buffer size must be multiple of element size")); | |
474 } | 522 } |
475 } else { | 523 } else { |
476 length = convertToUint(args[2], &try_catch); | 524 length = convertToUint(args[2], &try_catch); |
477 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 525 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
478 byteLength = length * element_size; | 526 byteLength = length * element_size; |
479 if (byteOffset + byteLength > bufferLength) { | 527 if (byteOffset + byteLength > bufferLength) { |
480 return ThrowException(String::New("length out of bounds")); | 528 return Throw("length out of bounds"); |
481 } | 529 } |
482 } | 530 } |
483 } else { | 531 } else { |
484 if (args[0]->IsObject() && | 532 if (args[0]->IsObject() && |
485 args[0]->ToObject()->Has(String::New("length"))) { | 533 args[0]->ToObject()->Has(Symbols::length(isolate))) { |
486 // Construct from array. | 534 // Construct from array. |
487 length = convertToUint( | 535 length = convertToUint( |
488 args[0]->ToObject()->Get(String::New("length")), &try_catch); | 536 args[0]->ToObject()->Get(Symbols::length(isolate)), &try_catch); |
489 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 537 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
490 init_from_array = true; | 538 init_from_array = true; |
491 } else { | 539 } else { |
492 // Construct from size. | 540 // Construct from size. |
493 length = convertToUint(args[0], &try_catch); | 541 length = convertToUint(args[0], &try_catch); |
494 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 542 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
495 } | 543 } |
496 byteLength = length * element_size; | 544 byteLength = length * element_size; |
497 byteOffset = 0; | 545 byteOffset = 0; |
498 | 546 |
499 Handle<Object> global = Context::GetCurrent()->Global(); | 547 Handle<Object> global = Context::GetCurrent()->Global(); |
500 Handle<Value> array_buffer = global->Get(String::New("ArrayBuffer")); | 548 Handle<Value> array_buffer = global->Get(Symbols::ArrayBuffer(isolate)); |
501 ASSERT(!try_catch.HasCaught() && array_buffer->IsFunction()); | 549 ASSERT(!try_catch.HasCaught() && array_buffer->IsFunction()); |
502 Handle<Value> buffer_args[] = { Uint32::New(byteLength) }; | 550 Handle<Value> buffer_args[] = { Uint32::New(byteLength) }; |
503 Handle<Value> result = Handle<Function>::Cast(array_buffer)->NewInstance( | 551 Handle<Value> result = Handle<Function>::Cast(array_buffer)->NewInstance( |
504 1, buffer_args); | 552 1, buffer_args); |
505 if (try_catch.HasCaught()) return result; | 553 if (try_catch.HasCaught()) return result; |
506 buffer = result->ToObject(); | 554 buffer = result->ToObject(); |
507 } | 555 } |
508 | 556 |
509 Handle<Object> array = CreateExternalArray( | 557 Handle<Object> array = |
510 args.This(), buffer, type, length, byteLength, byteOffset, element_size); | 558 CreateExternalArray(isolate, args.This(), buffer, type, length, |
| 559 byteLength, byteOffset, element_size); |
511 | 560 |
512 if (init_from_array) { | 561 if (init_from_array) { |
513 Handle<Object> init = args[0]->ToObject(); | 562 Handle<Object> init = args[0]->ToObject(); |
514 for (int i = 0; i < length; ++i) array->Set(i, init->Get(i)); | 563 for (int i = 0; i < length; ++i) array->Set(i, init->Get(i)); |
515 } | 564 } |
516 | 565 |
517 return array; | 566 return array; |
518 } | 567 } |
519 | 568 |
520 | 569 |
521 Handle<Value> Shell::ArrayBufferSlice(const Arguments& args) { | 570 Handle<Value> Shell::ArrayBufferSlice(const Arguments& args) { |
522 TryCatch try_catch; | 571 TryCatch try_catch; |
523 | 572 |
524 if (!args.This()->IsObject()) { | 573 if (!args.This()->IsObject()) { |
525 return ThrowException( | 574 return Throw("'slice' invoked on non-object receiver"); |
526 String::New("'slice' invoked on non-object receiver")); | |
527 } | 575 } |
528 | 576 |
| 577 Isolate* isolate = args.GetIsolate(); |
529 Local<Object> self = args.This(); | 578 Local<Object> self = args.This(); |
530 Local<Value> marker = | 579 Local<Value> marker = |
531 self->GetHiddenValue(String::New(kArrayBufferMarkerPropName)); | 580 self->GetHiddenValue(Symbols::ArrayBufferMarkerPropName(isolate)); |
532 if (marker.IsEmpty()) { | 581 if (marker.IsEmpty()) { |
533 return ThrowException( | 582 return Throw("'slice' invoked on wrong receiver type"); |
534 String::New("'slice' invoked on wrong receiver type")); | |
535 } | 583 } |
536 | 584 |
537 int32_t length = | 585 int32_t length = |
538 convertToUint(self->Get(String::New("byteLength")), &try_catch); | 586 convertToUint(self->Get(Symbols::byteLength(isolate)), &try_catch); |
539 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 587 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
540 | 588 |
541 if (args.Length() == 0) { | 589 if (args.Length() == 0) { |
542 return ThrowException( | 590 return Throw("'slice' must have at least one argument"); |
543 String::New("'slice' must have at least one argument")); | |
544 } | 591 } |
545 int32_t begin = convertToInt(args[0], &try_catch); | 592 int32_t begin = convertToInt(args[0], &try_catch); |
546 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 593 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
547 if (begin < 0) begin += length; | 594 if (begin < 0) begin += length; |
548 if (begin < 0) begin = 0; | 595 if (begin < 0) begin = 0; |
549 if (begin > length) begin = length; | 596 if (begin > length) begin = length; |
550 | 597 |
551 int32_t end; | 598 int32_t end; |
552 if (args.Length() < 2 || args[1]->IsUndefined()) { | 599 if (args.Length() < 2 || args[1]->IsUndefined()) { |
553 end = length; | 600 end = length; |
(...skipping 18 matching lines...) Expand all Loading... |
572 memcpy(dest, src, end - begin); | 619 memcpy(dest, src, end - begin); |
573 | 620 |
574 return buffer; | 621 return buffer; |
575 } | 622 } |
576 | 623 |
577 | 624 |
578 Handle<Value> Shell::ArraySubArray(const Arguments& args) { | 625 Handle<Value> Shell::ArraySubArray(const Arguments& args) { |
579 TryCatch try_catch; | 626 TryCatch try_catch; |
580 | 627 |
581 if (!args.This()->IsObject()) { | 628 if (!args.This()->IsObject()) { |
582 return ThrowException( | 629 return Throw("'subarray' invoked on non-object receiver"); |
583 String::New("'subarray' invoked on non-object receiver")); | |
584 } | 630 } |
585 | 631 |
| 632 Isolate* isolate = args.GetIsolate(); |
586 Local<Object> self = args.This(); | 633 Local<Object> self = args.This(); |
587 Local<Value> marker = self->GetHiddenValue(String::New(kArrayMarkerPropName)); | 634 Local<Value> marker = |
| 635 self->GetHiddenValue(Symbols::ArrayMarkerPropName(isolate)); |
588 if (marker.IsEmpty()) { | 636 if (marker.IsEmpty()) { |
589 return ThrowException( | 637 return Throw("'subarray' invoked on wrong receiver type"); |
590 String::New("'subarray' invoked on wrong receiver type")); | |
591 } | 638 } |
592 | 639 |
593 Handle<Object> buffer = self->Get(String::New("buffer"))->ToObject(); | 640 Handle<Object> buffer = self->Get(Symbols::buffer(isolate))->ToObject(); |
594 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 641 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
595 int32_t length = | 642 int32_t length = |
596 convertToUint(self->Get(String::New("length")), &try_catch); | 643 convertToUint(self->Get(Symbols::length(isolate)), &try_catch); |
597 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 644 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
598 int32_t byteOffset = | 645 int32_t byteOffset = |
599 convertToUint(self->Get(String::New("byteOffset")), &try_catch); | 646 convertToUint(self->Get(Symbols::byteOffset(isolate)), &try_catch); |
600 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 647 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
601 int32_t element_size = | 648 int32_t element_size = |
602 convertToUint(self->Get(String::New("BYTES_PER_ELEMENT")), &try_catch); | 649 convertToUint(self->Get(Symbols::BYTES_PER_ELEMENT(isolate)), &try_catch); |
603 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 650 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
604 | 651 |
605 if (args.Length() == 0) { | 652 if (args.Length() == 0) { |
606 return ThrowException( | 653 return Throw("'subarray' must have at least one argument"); |
607 String::New("'subarray' must have at least one argument")); | |
608 } | 654 } |
609 int32_t begin = convertToInt(args[0], &try_catch); | 655 int32_t begin = convertToInt(args[0], &try_catch); |
610 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 656 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
611 if (begin < 0) begin += length; | 657 if (begin < 0) begin += length; |
612 if (begin < 0) begin = 0; | 658 if (begin < 0) begin = 0; |
613 if (begin > length) begin = length; | 659 if (begin > length) begin = length; |
614 | 660 |
615 int32_t end; | 661 int32_t end; |
616 if (args.Length() < 2 || args[1]->IsUndefined()) { | 662 if (args.Length() < 2 || args[1]->IsUndefined()) { |
617 end = length; | 663 end = length; |
(...skipping 14 matching lines...) Expand all Loading... |
632 buffer, Uint32::New(byteOffset), Uint32::New(length) | 678 buffer, Uint32::New(byteOffset), Uint32::New(length) |
633 }; | 679 }; |
634 return constructor->NewInstance(3, construct_args); | 680 return constructor->NewInstance(3, construct_args); |
635 } | 681 } |
636 | 682 |
637 | 683 |
638 Handle<Value> Shell::ArraySet(const Arguments& args) { | 684 Handle<Value> Shell::ArraySet(const Arguments& args) { |
639 TryCatch try_catch; | 685 TryCatch try_catch; |
640 | 686 |
641 if (!args.This()->IsObject()) { | 687 if (!args.This()->IsObject()) { |
642 return ThrowException( | 688 return Throw("'set' invoked on non-object receiver"); |
643 String::New("'set' invoked on non-object receiver")); | |
644 } | 689 } |
645 | 690 |
| 691 Isolate* isolate = args.GetIsolate(); |
646 Local<Object> self = args.This(); | 692 Local<Object> self = args.This(); |
647 Local<Value> marker = self->GetHiddenValue(String::New(kArrayMarkerPropName)); | 693 Local<Value> marker = |
| 694 self->GetHiddenValue(Symbols::ArrayMarkerPropName(isolate)); |
648 if (marker.IsEmpty()) { | 695 if (marker.IsEmpty()) { |
649 return ThrowException( | 696 return Throw("'set' invoked on wrong receiver type"); |
650 String::New("'set' invoked on wrong receiver type")); | |
651 } | 697 } |
652 int32_t length = | 698 int32_t length = |
653 convertToUint(self->Get(String::New("length")), &try_catch); | 699 convertToUint(self->Get(Symbols::length(isolate)), &try_catch); |
654 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 700 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
655 int32_t element_size = | 701 int32_t element_size = |
656 convertToUint(self->Get(String::New("BYTES_PER_ELEMENT")), &try_catch); | 702 convertToUint(self->Get(Symbols::BYTES_PER_ELEMENT(isolate)), &try_catch); |
657 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 703 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
658 | 704 |
659 if (args.Length() == 0) { | 705 if (args.Length() == 0) { |
660 return ThrowException( | 706 return Throw("'set' must have at least one argument"); |
661 String::New("'set' must have at least one argument")); | |
662 } | 707 } |
663 if (!args[0]->IsObject() || | 708 if (!args[0]->IsObject() || |
664 !args[0]->ToObject()->Has(String::New("length"))) { | 709 !args[0]->ToObject()->Has(Symbols::length(isolate))) { |
665 return ThrowException( | 710 return Throw("'set' invoked with non-array argument"); |
666 String::New("'set' invoked with non-array argument")); | |
667 } | 711 } |
668 Handle<Object> source = args[0]->ToObject(); | 712 Handle<Object> source = args[0]->ToObject(); |
669 int32_t source_length = | 713 int32_t source_length = |
670 convertToUint(source->Get(String::New("length")), &try_catch); | 714 convertToUint(source->Get(Symbols::length(isolate)), &try_catch); |
671 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 715 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
672 | 716 |
673 int32_t offset; | 717 int32_t offset; |
674 if (args.Length() < 2 || args[1]->IsUndefined()) { | 718 if (args.Length() < 2 || args[1]->IsUndefined()) { |
675 offset = 0; | 719 offset = 0; |
676 } else { | 720 } else { |
677 offset = convertToUint(args[1], &try_catch); | 721 offset = convertToUint(args[1], &try_catch); |
678 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 722 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
679 } | 723 } |
680 if (offset + source_length > length) { | 724 if (offset + source_length > length) { |
681 return ThrowException(String::New("offset or source length out of bounds")); | 725 return Throw("offset or source length out of bounds"); |
682 } | 726 } |
683 | 727 |
684 int32_t source_element_size; | 728 int32_t source_element_size; |
685 if (source->GetHiddenValue(String::New(kArrayMarkerPropName)).IsEmpty()) { | 729 if (source->GetHiddenValue(Symbols::ArrayMarkerPropName(isolate)).IsEmpty()) { |
686 source_element_size = 0; | 730 source_element_size = 0; |
687 } else { | 731 } else { |
688 source_element_size = | 732 source_element_size = |
689 convertToUint(source->Get(String::New("BYTES_PER_ELEMENT")), &try_catch); | 733 convertToUint(source->Get(Symbols::BYTES_PER_ELEMENT(isolate)), |
| 734 &try_catch); |
690 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 735 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
691 } | 736 } |
692 | 737 |
693 if (element_size == source_element_size && | 738 if (element_size == source_element_size && |
694 self->GetConstructor()->StrictEquals(source->GetConstructor())) { | 739 self->GetConstructor()->StrictEquals(source->GetConstructor())) { |
695 // Use memmove on the array buffers. | 740 // Use memmove on the array buffers. |
696 Handle<Object> buffer = self->Get(String::New("buffer"))->ToObject(); | 741 Handle<Object> buffer = self->Get(Symbols::buffer(isolate))->ToObject(); |
697 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 742 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
698 Handle<Object> source_buffer = | 743 Handle<Object> source_buffer = |
699 source->Get(String::New("buffer"))->ToObject(); | 744 source->Get(Symbols::buffer(isolate))->ToObject(); |
700 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 745 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
701 int32_t byteOffset = | 746 int32_t byteOffset = |
702 convertToUint(self->Get(String::New("byteOffset")), &try_catch); | 747 convertToUint(self->Get(Symbols::byteOffset(isolate)), &try_catch); |
703 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 748 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
704 int32_t source_byteOffset = | 749 int32_t source_byteOffset = |
705 convertToUint(source->Get(String::New("byteOffset")), &try_catch); | 750 convertToUint(source->Get(Symbols::byteOffset(isolate)), &try_catch); |
706 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 751 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
707 | 752 |
708 uint8_t* dest = byteOffset + offset * element_size + static_cast<uint8_t*>( | 753 uint8_t* dest = byteOffset + offset * element_size + static_cast<uint8_t*>( |
709 buffer->GetIndexedPropertiesExternalArrayData()); | 754 buffer->GetIndexedPropertiesExternalArrayData()); |
710 uint8_t* src = source_byteOffset + static_cast<uint8_t*>( | 755 uint8_t* src = source_byteOffset + static_cast<uint8_t*>( |
711 source_buffer->GetIndexedPropertiesExternalArrayData()); | 756 source_buffer->GetIndexedPropertiesExternalArrayData()); |
712 memmove(dest, src, source_length * element_size); | 757 memmove(dest, src, source_length * element_size); |
713 } else if (source_element_size == 0) { | 758 } else if (source_element_size == 0) { |
714 // Source is not a typed array, copy element-wise sequentially. | 759 // Source is not a typed array, copy element-wise sequentially. |
715 for (int i = 0; i < source_length; ++i) { | 760 for (int i = 0; i < source_length; ++i) { |
716 self->Set(offset + i, source->Get(i)); | 761 self->Set(offset + i, source->Get(i)); |
717 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 762 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
718 } | 763 } |
719 } else { | 764 } else { |
720 // Need to copy element-wise to make the right conversions. | 765 // Need to copy element-wise to make the right conversions. |
721 Handle<Object> buffer = self->Get(String::New("buffer"))->ToObject(); | 766 Handle<Object> buffer = self->Get(Symbols::buffer(isolate))->ToObject(); |
722 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 767 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
723 Handle<Object> source_buffer = | 768 Handle<Object> source_buffer = |
724 source->Get(String::New("buffer"))->ToObject(); | 769 source->Get(Symbols::buffer(isolate))->ToObject(); |
725 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 770 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
726 | 771 |
727 if (buffer->StrictEquals(source_buffer)) { | 772 if (buffer->StrictEquals(source_buffer)) { |
728 // Same backing store, need to handle overlap correctly. | 773 // Same backing store, need to handle overlap correctly. |
729 // This gets a bit tricky in the case of different element sizes | 774 // This gets a bit tricky in the case of different element sizes |
730 // (which, of course, is extremely unlikely to ever occur in practice). | 775 // (which, of course, is extremely unlikely to ever occur in practice). |
731 int32_t byteOffset = | 776 int32_t byteOffset = |
732 convertToUint(self->Get(String::New("byteOffset")), &try_catch); | 777 convertToUint(self->Get(Symbols::byteOffset(isolate)), &try_catch); |
733 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 778 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
734 int32_t source_byteOffset = | 779 int32_t source_byteOffset = |
735 convertToUint(source->Get(String::New("byteOffset")), &try_catch); | 780 convertToUint(source->Get(Symbols::byteOffset(isolate)), &try_catch); |
736 if (try_catch.HasCaught()) return try_catch.ReThrow(); | 781 if (try_catch.HasCaught()) return try_catch.ReThrow(); |
737 | 782 |
738 // Copy as much as we can from left to right. | 783 // Copy as much as we can from left to right. |
739 int i = 0; | 784 int i = 0; |
740 int32_t next_dest_offset = byteOffset + (offset + 1) * element_size; | 785 int32_t next_dest_offset = byteOffset + (offset + 1) * element_size; |
741 int32_t next_src_offset = source_byteOffset + source_element_size; | 786 int32_t next_src_offset = source_byteOffset + source_element_size; |
742 while (i < length && next_dest_offset <= next_src_offset) { | 787 while (i < length && next_dest_offset <= next_src_offset) { |
743 self->Set(offset + i, source->Get(i)); | 788 self->Set(offset + i, source->Get(i)); |
744 ++i; | 789 ++i; |
745 next_dest_offset += element_size; | 790 next_dest_offset += element_size; |
(...skipping 25 matching lines...) Expand all Loading... |
771 self->Set(offset + i, source->Get(i)); | 816 self->Set(offset + i, source->Get(i)); |
772 } | 817 } |
773 } | 818 } |
774 | 819 |
775 return Undefined(); | 820 return Undefined(); |
776 } | 821 } |
777 | 822 |
778 | 823 |
779 void Shell::ExternalArrayWeakCallback(Persistent<Value> object, void* data) { | 824 void Shell::ExternalArrayWeakCallback(Persistent<Value> object, void* data) { |
780 HandleScope scope; | 825 HandleScope scope; |
| 826 Isolate* isolate = Isolate::GetCurrent(); |
781 int32_t length = | 827 int32_t length = |
782 object->ToObject()->Get(String::New("byteLength"))->Uint32Value(); | 828 object->ToObject()->Get(Symbols::byteLength(isolate))->Uint32Value(); |
783 V8::AdjustAmountOfExternalAllocatedMemory(-length); | 829 V8::AdjustAmountOfExternalAllocatedMemory(-length); |
784 delete[] static_cast<uint8_t*>(data); | 830 delete[] static_cast<uint8_t*>(data); |
785 object.Dispose(); | 831 object.Dispose(); |
786 } | 832 } |
787 | 833 |
788 | 834 |
789 Handle<Value> Shell::Int8Array(const Arguments& args) { | 835 Handle<Value> Shell::Int8Array(const Arguments& args) { |
790 return CreateExternalArray(args, v8::kExternalByteArray, sizeof(int8_t)); | 836 return CreateExternalArray(args, v8::kExternalByteArray, sizeof(int8_t)); |
791 } | 837 } |
792 | 838 |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1138 Handle<FunctionTemplate> Shell::CreateArrayTemplate(InvocationCallback fun) { | 1184 Handle<FunctionTemplate> Shell::CreateArrayTemplate(InvocationCallback fun) { |
1139 Handle<FunctionTemplate> array_template = FunctionTemplate::New(fun); | 1185 Handle<FunctionTemplate> array_template = FunctionTemplate::New(fun); |
1140 Local<Template> proto_template = array_template->PrototypeTemplate(); | 1186 Local<Template> proto_template = array_template->PrototypeTemplate(); |
1141 proto_template->Set(String::New("set"), FunctionTemplate::New(ArraySet)); | 1187 proto_template->Set(String::New("set"), FunctionTemplate::New(ArraySet)); |
1142 proto_template->Set(String::New("subarray"), | 1188 proto_template->Set(String::New("subarray"), |
1143 FunctionTemplate::New(ArraySubArray)); | 1189 FunctionTemplate::New(ArraySubArray)); |
1144 return array_template; | 1190 return array_template; |
1145 } | 1191 } |
1146 | 1192 |
1147 | 1193 |
1148 Handle<ObjectTemplate> Shell::CreateGlobalTemplate() { | 1194 Handle<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) { |
1149 Handle<ObjectTemplate> global_template = ObjectTemplate::New(); | 1195 Handle<ObjectTemplate> global_template = ObjectTemplate::New(); |
1150 global_template->Set(String::New("print"), FunctionTemplate::New(Print)); | 1196 global_template->Set(String::New("print"), FunctionTemplate::New(Print)); |
1151 global_template->Set(String::New("write"), FunctionTemplate::New(Write)); | 1197 global_template->Set(String::New("write"), FunctionTemplate::New(Write)); |
1152 global_template->Set(String::New("read"), FunctionTemplate::New(Read)); | 1198 global_template->Set(String::New("read"), FunctionTemplate::New(Read)); |
1153 global_template->Set(String::New("readbuffer"), | 1199 global_template->Set(String::New("readbuffer"), |
1154 FunctionTemplate::New(ReadBuffer)); | 1200 FunctionTemplate::New(ReadBuffer)); |
1155 global_template->Set(String::New("readline"), | 1201 global_template->Set(String::New("readline"), |
1156 FunctionTemplate::New(ReadLine)); | 1202 FunctionTemplate::New(ReadLine)); |
1157 global_template->Set(String::New("load"), FunctionTemplate::New(Load)); | 1203 global_template->Set(String::New("load"), FunctionTemplate::New(Load)); |
1158 global_template->Set(String::New("quit"), FunctionTemplate::New(Quit)); | 1204 global_template->Set(String::New("quit"), FunctionTemplate::New(Quit)); |
1159 global_template->Set(String::New("version"), FunctionTemplate::New(Version)); | 1205 global_template->Set(String::New("version"), FunctionTemplate::New(Version)); |
1160 global_template->Set(String::New("enableProfiler"), | 1206 global_template->Set(String::New("enableProfiler"), |
1161 FunctionTemplate::New(EnableProfiler)); | 1207 FunctionTemplate::New(EnableProfiler)); |
1162 global_template->Set(String::New("disableProfiler"), | 1208 global_template->Set(String::New("disableProfiler"), |
1163 FunctionTemplate::New(DisableProfiler)); | 1209 FunctionTemplate::New(DisableProfiler)); |
1164 | 1210 |
1165 // Bind the handlers for external arrays. | 1211 // Bind the handlers for external arrays. |
1166 PropertyAttribute attr = | 1212 PropertyAttribute attr = |
1167 static_cast<PropertyAttribute>(ReadOnly | DontDelete); | 1213 static_cast<PropertyAttribute>(ReadOnly | DontDelete); |
1168 global_template->Set(String::New("ArrayBuffer"), | 1214 global_template->Set(Symbols::ArrayBuffer(isolate), |
1169 CreateArrayBufferTemplate(ArrayBuffer), attr); | 1215 CreateArrayBufferTemplate(ArrayBuffer), attr); |
1170 global_template->Set(String::New("Int8Array"), | 1216 global_template->Set(String::New("Int8Array"), |
1171 CreateArrayTemplate(Int8Array), attr); | 1217 CreateArrayTemplate(Int8Array), attr); |
1172 global_template->Set(String::New("Uint8Array"), | 1218 global_template->Set(String::New("Uint8Array"), |
1173 CreateArrayTemplate(Uint8Array), attr); | 1219 CreateArrayTemplate(Uint8Array), attr); |
1174 global_template->Set(String::New("Int16Array"), | 1220 global_template->Set(String::New("Int16Array"), |
1175 CreateArrayTemplate(Int16Array), attr); | 1221 CreateArrayTemplate(Int16Array), attr); |
1176 global_template->Set(String::New("Uint16Array"), | 1222 global_template->Set(String::New("Uint16Array"), |
1177 CreateArrayTemplate(Uint16Array), attr); | 1223 CreateArrayTemplate(Uint16Array), attr); |
1178 global_template->Set(String::New("Int32Array"), | 1224 global_template->Set(String::New("Int32Array"), |
(...skipping 16 matching lines...) Expand all Loading... |
1195 #if !defined(V8_SHARED) && !defined(_WIN32) && !defined(_WIN64) | 1241 #if !defined(V8_SHARED) && !defined(_WIN32) && !defined(_WIN64) |
1196 Handle<ObjectTemplate> os_templ = ObjectTemplate::New(); | 1242 Handle<ObjectTemplate> os_templ = ObjectTemplate::New(); |
1197 AddOSMethods(os_templ); | 1243 AddOSMethods(os_templ); |
1198 global_template->Set(String::New("os"), os_templ); | 1244 global_template->Set(String::New("os"), os_templ); |
1199 #endif // V8_SHARED | 1245 #endif // V8_SHARED |
1200 | 1246 |
1201 return global_template; | 1247 return global_template; |
1202 } | 1248 } |
1203 | 1249 |
1204 | 1250 |
1205 void Shell::Initialize() { | 1251 void Shell::Initialize(Isolate* isolate) { |
1206 #ifdef COMPRESS_STARTUP_DATA_BZ2 | 1252 #ifdef COMPRESS_STARTUP_DATA_BZ2 |
1207 BZip2Decompressor startup_data_decompressor; | 1253 BZip2Decompressor startup_data_decompressor; |
1208 int bz2_result = startup_data_decompressor.Decompress(); | 1254 int bz2_result = startup_data_decompressor.Decompress(); |
1209 if (bz2_result != BZ_OK) { | 1255 if (bz2_result != BZ_OK) { |
1210 fprintf(stderr, "bzip error code: %d\n", bz2_result); | 1256 fprintf(stderr, "bzip error code: %d\n", bz2_result); |
1211 Exit(1); | 1257 Exit(1); |
1212 } | 1258 } |
1213 #endif | 1259 #endif |
1214 | 1260 |
1215 #ifndef V8_SHARED | 1261 #ifndef V8_SHARED |
1216 Shell::counter_map_ = new CounterMap(); | 1262 Shell::counter_map_ = new CounterMap(); |
1217 // Set up counters | 1263 // Set up counters |
1218 if (i::StrLength(i::FLAG_map_counters) != 0) | 1264 if (i::StrLength(i::FLAG_map_counters) != 0) |
1219 MapCounters(i::FLAG_map_counters); | 1265 MapCounters(i::FLAG_map_counters); |
1220 if (i::FLAG_dump_counters || i::FLAG_track_gc_object_stats) { | 1266 if (i::FLAG_dump_counters || i::FLAG_track_gc_object_stats) { |
1221 V8::SetCounterFunction(LookupCounter); | 1267 V8::SetCounterFunction(LookupCounter); |
1222 V8::SetCreateHistogramFunction(CreateHistogram); | 1268 V8::SetCreateHistogramFunction(CreateHistogram); |
1223 V8::SetAddHistogramSampleFunction(AddHistogramSample); | 1269 V8::SetAddHistogramSampleFunction(AddHistogramSample); |
1224 } | 1270 } |
1225 #endif // V8_SHARED | 1271 #endif // V8_SHARED |
1226 if (options.test_shell) return; | 1272 if (options.test_shell) return; |
1227 | 1273 |
1228 #ifndef V8_SHARED | 1274 #ifndef V8_SHARED |
1229 Locker lock; | 1275 Locker lock; |
1230 HandleScope scope; | 1276 HandleScope scope; |
1231 Handle<ObjectTemplate> global_template = CreateGlobalTemplate(); | 1277 Handle<ObjectTemplate> global_template = CreateGlobalTemplate(isolate); |
1232 utility_context_ = Context::New(NULL, global_template); | 1278 utility_context_ = Context::New(NULL, global_template); |
1233 | 1279 |
1234 #ifdef ENABLE_DEBUGGER_SUPPORT | 1280 #ifdef ENABLE_DEBUGGER_SUPPORT |
1235 // Start the debugger agent if requested. | 1281 // Start the debugger agent if requested. |
1236 if (i::FLAG_debugger_agent) { | 1282 if (i::FLAG_debugger_agent) { |
1237 v8::Debug::EnableAgent("d8 shell", i::FLAG_debugger_port, true); | 1283 v8::Debug::EnableAgent("d8 shell", i::FLAG_debugger_port, true); |
1238 v8::Debug::SetDebugMessageDispatchHandler(DispatchDebugMessages, true); | 1284 v8::Debug::SetDebugMessageDispatchHandler(DispatchDebugMessages, true); |
1239 } | 1285 } |
1240 #endif // ENABLE_DEBUGGER_SUPPORT | 1286 #endif // ENABLE_DEBUGGER_SUPPORT |
1241 #endif // V8_SHARED | 1287 #endif // V8_SHARED |
1242 } | 1288 } |
1243 | 1289 |
1244 | 1290 |
1245 Persistent<Context> Shell::CreateEvaluationContext() { | 1291 Persistent<Context> Shell::CreateEvaluationContext(Isolate* isolate) { |
1246 #ifndef V8_SHARED | 1292 #ifndef V8_SHARED |
1247 // This needs to be a critical section since this is not thread-safe | 1293 // This needs to be a critical section since this is not thread-safe |
1248 i::ScopedLock lock(context_mutex_); | 1294 i::ScopedLock lock(context_mutex_); |
1249 #endif // V8_SHARED | 1295 #endif // V8_SHARED |
1250 // Initialize the global objects | 1296 // Initialize the global objects |
1251 Handle<ObjectTemplate> global_template = CreateGlobalTemplate(); | 1297 Handle<ObjectTemplate> global_template = CreateGlobalTemplate(isolate); |
1252 Persistent<Context> context = Context::New(NULL, global_template); | 1298 Persistent<Context> context = Context::New(NULL, global_template); |
1253 ASSERT(!context.IsEmpty()); | 1299 ASSERT(!context.IsEmpty()); |
1254 Context::Scope scope(context); | 1300 Context::Scope scope(context); |
1255 | 1301 |
1256 #ifndef V8_SHARED | 1302 #ifndef V8_SHARED |
1257 i::JSArguments js_args = i::FLAG_js_arguments; | 1303 i::JSArguments js_args = i::FLAG_js_arguments; |
1258 i::Handle<i::FixedArray> arguments_array = | 1304 i::Handle<i::FixedArray> arguments_array = |
1259 FACTORY->NewFixedArray(js_args.argc()); | 1305 FACTORY->NewFixedArray(js_args.argc()); |
1260 for (int j = 0; j < js_args.argc(); j++) { | 1306 for (int j = 0; j < js_args.argc(); j++) { |
1261 i::Handle<i::String> arg = | 1307 i::Handle<i::String> arg = |
(...skipping 25 matching lines...) Expand all Loading... |
1287 }; | 1333 }; |
1288 | 1334 |
1289 | 1335 |
1290 int CompareKeys(const void* a, const void* b) { | 1336 int CompareKeys(const void* a, const void* b) { |
1291 return strcmp(static_cast<const CounterAndKey*>(a)->key, | 1337 return strcmp(static_cast<const CounterAndKey*>(a)->key, |
1292 static_cast<const CounterAndKey*>(b)->key); | 1338 static_cast<const CounterAndKey*>(b)->key); |
1293 } | 1339 } |
1294 | 1340 |
1295 | 1341 |
1296 void Shell::OnExit() { | 1342 void Shell::OnExit() { |
1297 if (console != NULL) console->Close(); | |
1298 if (i::FLAG_dump_counters) { | 1343 if (i::FLAG_dump_counters) { |
1299 int number_of_counters = 0; | 1344 int number_of_counters = 0; |
1300 for (CounterMap::Iterator i(counter_map_); i.More(); i.Next()) { | 1345 for (CounterMap::Iterator i(counter_map_); i.More(); i.Next()) { |
1301 number_of_counters++; | 1346 number_of_counters++; |
1302 } | 1347 } |
1303 CounterAndKey* counters = new CounterAndKey[number_of_counters]; | 1348 CounterAndKey* counters = new CounterAndKey[number_of_counters]; |
1304 int j = 0; | 1349 int j = 0; |
1305 for (CounterMap::Iterator i(counter_map_); i.More(); i.Next(), j++) { | 1350 for (CounterMap::Iterator i(counter_map_); i.More(); i.Next(), j++) { |
1306 counters[j].counter = i.CurrentValue(); | 1351 counters[j].counter = i.CurrentValue(); |
1307 counters[j].key = i.CurrentKey(); | 1352 counters[j].key = i.CurrentKey(); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1347 struct stat file_stat; | 1392 struct stat file_stat; |
1348 if (fstat(fileno(file), &file_stat) != 0) return NULL; | 1393 if (fstat(fileno(file), &file_stat) != 0) return NULL; |
1349 bool is_regular_file = ((file_stat.st_mode & S_IFREG) != 0); | 1394 bool is_regular_file = ((file_stat.st_mode & S_IFREG) != 0); |
1350 if (is_regular_file) return file; | 1395 if (is_regular_file) return file; |
1351 fclose(file); | 1396 fclose(file); |
1352 return NULL; | 1397 return NULL; |
1353 #endif | 1398 #endif |
1354 } | 1399 } |
1355 | 1400 |
1356 | 1401 |
1357 static char* ReadChars(const char* name, int* size_out) { | 1402 static char* ReadChars(Isolate* isolate, const char* name, int* size_out) { |
1358 // Release the V8 lock while reading files. | 1403 // Release the V8 lock while reading files. |
1359 v8::Unlocker unlocker(Isolate::GetCurrent()); | 1404 v8::Unlocker unlocker(isolate); |
1360 FILE* file = FOpen(name, "rb"); | 1405 FILE* file = FOpen(name, "rb"); |
1361 if (file == NULL) return NULL; | 1406 if (file == NULL) return NULL; |
1362 | 1407 |
1363 fseek(file, 0, SEEK_END); | 1408 fseek(file, 0, SEEK_END); |
1364 int size = ftell(file); | 1409 int size = ftell(file); |
1365 rewind(file); | 1410 rewind(file); |
1366 | 1411 |
1367 char* chars = new char[size + 1]; | 1412 char* chars = new char[size + 1]; |
1368 chars[size] = '\0'; | 1413 chars[size] = '\0'; |
1369 for (int i = 0; i < size;) { | 1414 for (int i = 0; i < size;) { |
1370 int read = static_cast<int>(fread(&chars[i], 1, size - i, file)); | 1415 int read = static_cast<int>(fread(&chars[i], 1, size - i, file)); |
1371 i += read; | 1416 i += read; |
1372 } | 1417 } |
1373 fclose(file); | 1418 fclose(file); |
1374 *size_out = size; | 1419 *size_out = size; |
1375 return chars; | 1420 return chars; |
1376 } | 1421 } |
1377 | 1422 |
1378 | 1423 |
1379 Handle<Value> Shell::ReadBuffer(const Arguments& args) { | 1424 Handle<Value> Shell::ReadBuffer(const Arguments& args) { |
1380 ASSERT(sizeof(char) == sizeof(uint8_t)); // NOLINT | 1425 ASSERT(sizeof(char) == sizeof(uint8_t)); // NOLINT |
1381 String::Utf8Value filename(args[0]); | 1426 String::Utf8Value filename(args[0]); |
1382 int length; | 1427 int length; |
1383 if (*filename == NULL) { | 1428 if (*filename == NULL) { |
1384 return ThrowException(String::New("Error loading file")); | 1429 return Throw("Error loading file"); |
1385 } | 1430 } |
1386 | 1431 |
1387 uint8_t* data = reinterpret_cast<uint8_t*>(ReadChars(*filename, &length)); | 1432 uint8_t* data = reinterpret_cast<uint8_t*>( |
| 1433 ReadChars(args.GetIsolate(), *filename, &length)); |
1388 if (data == NULL) { | 1434 if (data == NULL) { |
1389 return ThrowException(String::New("Error reading file")); | 1435 return Throw("Error reading file"); |
1390 } | 1436 } |
| 1437 Isolate* isolate = args.GetIsolate(); |
1391 Handle<Object> buffer = Object::New(); | 1438 Handle<Object> buffer = Object::New(); |
1392 buffer->SetHiddenValue(String::New(kArrayBufferMarkerPropName), True()); | 1439 buffer->SetHiddenValue(Symbols::ArrayBufferMarkerPropName(isolate), True()); |
1393 Persistent<Object> persistent_buffer = Persistent<Object>::New(buffer); | 1440 Persistent<Object> persistent_buffer = Persistent<Object>::New(buffer); |
1394 persistent_buffer.MakeWeak(data, ExternalArrayWeakCallback); | 1441 persistent_buffer.MakeWeak(data, ExternalArrayWeakCallback); |
1395 persistent_buffer.MarkIndependent(); | 1442 persistent_buffer.MarkIndependent(); |
1396 V8::AdjustAmountOfExternalAllocatedMemory(length); | 1443 V8::AdjustAmountOfExternalAllocatedMemory(length); |
1397 | 1444 |
1398 buffer->SetIndexedPropertiesToExternalArrayData( | 1445 buffer->SetIndexedPropertiesToExternalArrayData( |
1399 data, kExternalUnsignedByteArray, length); | 1446 data, kExternalUnsignedByteArray, length); |
1400 buffer->Set(String::New("byteLength"), | 1447 buffer->Set(Symbols::byteLength(isolate), |
1401 Int32::New(static_cast<int32_t>(length)), ReadOnly); | 1448 Int32::New(static_cast<int32_t>(length)), ReadOnly); |
1402 return buffer; | 1449 return buffer; |
1403 } | 1450 } |
1404 | 1451 |
1405 | 1452 |
1406 #ifndef V8_SHARED | 1453 #ifndef V8_SHARED |
1407 static char* ReadToken(char* data, char token) { | 1454 static char* ReadToken(char* data, char token) { |
1408 char* next = i::OS::StrChr(data, token); | 1455 char* next = i::OS::StrChr(data, token); |
1409 if (next != NULL) { | 1456 if (next != NULL) { |
1410 *next = '\0'; | 1457 *next = '\0'; |
1411 return (next + 1); | 1458 return (next + 1); |
1412 } | 1459 } |
1413 | 1460 |
1414 return NULL; | 1461 return NULL; |
1415 } | 1462 } |
1416 | 1463 |
1417 | 1464 |
1418 static char* ReadLine(char* data) { | 1465 static char* ReadLine(char* data) { |
1419 return ReadToken(data, '\n'); | 1466 return ReadToken(data, '\n'); |
1420 } | 1467 } |
1421 | 1468 |
1422 | 1469 |
1423 static char* ReadWord(char* data) { | 1470 static char* ReadWord(char* data) { |
1424 return ReadToken(data, ' '); | 1471 return ReadToken(data, ' '); |
1425 } | 1472 } |
1426 #endif // V8_SHARED | 1473 #endif // V8_SHARED |
1427 | 1474 |
1428 | 1475 |
1429 // Reads a file into a v8 string. | 1476 // Reads a file into a v8 string. |
1430 Handle<String> Shell::ReadFile(const char* name) { | 1477 Handle<String> Shell::ReadFile(Isolate* isolate, const char* name) { |
1431 int size = 0; | 1478 int size = 0; |
1432 char* chars = ReadChars(name, &size); | 1479 char* chars = ReadChars(isolate, name, &size); |
1433 if (chars == NULL) return Handle<String>(); | 1480 if (chars == NULL) return Handle<String>(); |
1434 Handle<String> result = String::New(chars); | 1481 Handle<String> result = String::New(chars); |
1435 delete[] chars; | 1482 delete[] chars; |
1436 return result; | 1483 return result; |
1437 } | 1484 } |
1438 | 1485 |
1439 | 1486 |
1440 void Shell::RunShell() { | 1487 void Shell::RunShell(Isolate* isolate) { |
1441 Locker locker; | 1488 Locker locker; |
1442 Context::Scope context_scope(evaluation_context_); | 1489 Context::Scope context_scope(evaluation_context_); |
1443 HandleScope outer_scope; | 1490 HandleScope outer_scope; |
1444 Handle<String> name = String::New("(d8)"); | 1491 Handle<String> name = String::New("(d8)"); |
1445 console = LineEditor::Get(); | 1492 DumbLineEditor dumb_line_editor(isolate); |
| 1493 LineEditor* console = LineEditor::Get(); |
1446 printf("V8 version %s [console: %s]\n", V8::GetVersion(), console->name()); | 1494 printf("V8 version %s [console: %s]\n", V8::GetVersion(), console->name()); |
1447 console->Open(); | 1495 console->Open(); |
1448 while (true) { | 1496 while (true) { |
1449 HandleScope inner_scope; | 1497 HandleScope inner_scope; |
1450 Handle<String> input = console->Prompt(Shell::kPrompt); | 1498 Handle<String> input = console->Prompt(Shell::kPrompt); |
1451 if (input.IsEmpty()) break; | 1499 if (input.IsEmpty()) break; |
1452 ExecuteString(input, name, true, true); | 1500 ExecuteString(input, name, true, true); |
1453 } | 1501 } |
1454 printf("\n"); | 1502 printf("\n"); |
| 1503 console->Close(); |
1455 } | 1504 } |
1456 | 1505 |
1457 | 1506 |
1458 #ifndef V8_SHARED | 1507 #ifndef V8_SHARED |
1459 class ShellThread : public i::Thread { | 1508 class ShellThread : public i::Thread { |
1460 public: | 1509 public: |
1461 // Takes ownership of the underlying char array of |files|. | 1510 // Takes ownership of the underlying char array of |files|. |
1462 ShellThread(int no, char* files) | 1511 ShellThread(Isolate* isolate, int no, char* files) |
1463 : Thread("d8:ShellThread"), | 1512 : Thread("d8:ShellThread"), |
1464 no_(no), files_(files) { } | 1513 isolate_(isolate), no_(no), files_(files) { } |
1465 | 1514 |
1466 ~ShellThread() { | 1515 ~ShellThread() { |
1467 delete[] files_; | 1516 delete[] files_; |
1468 } | 1517 } |
1469 | 1518 |
1470 virtual void Run(); | 1519 virtual void Run(); |
1471 private: | 1520 private: |
| 1521 Isolate* isolate_; |
1472 int no_; | 1522 int no_; |
1473 char* files_; | 1523 char* files_; |
1474 }; | 1524 }; |
1475 | 1525 |
1476 | 1526 |
1477 void ShellThread::Run() { | 1527 void ShellThread::Run() { |
1478 char* ptr = files_; | 1528 char* ptr = files_; |
1479 while ((ptr != NULL) && (*ptr != '\0')) { | 1529 while ((ptr != NULL) && (*ptr != '\0')) { |
1480 // For each newline-separated line. | 1530 // For each newline-separated line. |
1481 char* next_line = ReadLine(ptr); | 1531 char* next_line = ReadLine(ptr); |
1482 | 1532 |
1483 if (*ptr == '#') { | 1533 if (*ptr == '#') { |
1484 // Skip comment lines. | 1534 // Skip comment lines. |
1485 ptr = next_line; | 1535 ptr = next_line; |
1486 continue; | 1536 continue; |
1487 } | 1537 } |
1488 | 1538 |
1489 // Prepare the context for this thread. | 1539 // Prepare the context for this thread. |
1490 Locker locker; | 1540 Locker locker; |
1491 HandleScope outer_scope; | 1541 HandleScope outer_scope; |
1492 Persistent<Context> thread_context = Shell::CreateEvaluationContext(); | 1542 Persistent<Context> thread_context = |
| 1543 Shell::CreateEvaluationContext(isolate_); |
1493 Context::Scope context_scope(thread_context); | 1544 Context::Scope context_scope(thread_context); |
1494 | 1545 |
1495 while ((ptr != NULL) && (*ptr != '\0')) { | 1546 while ((ptr != NULL) && (*ptr != '\0')) { |
1496 HandleScope inner_scope; | 1547 HandleScope inner_scope; |
1497 char* filename = ptr; | 1548 char* filename = ptr; |
1498 ptr = ReadWord(ptr); | 1549 ptr = ReadWord(ptr); |
1499 | 1550 |
1500 // Skip empty strings. | 1551 // Skip empty strings. |
1501 if (strlen(filename) == 0) { | 1552 if (strlen(filename) == 0) { |
1502 continue; | 1553 continue; |
1503 } | 1554 } |
1504 | 1555 |
1505 Handle<String> str = Shell::ReadFile(filename); | 1556 Handle<String> str = Shell::ReadFile(isolate_, filename); |
1506 if (str.IsEmpty()) { | 1557 if (str.IsEmpty()) { |
1507 printf("File '%s' not found\n", filename); | 1558 printf("File '%s' not found\n", filename); |
1508 Shell::Exit(1); | 1559 Shell::Exit(1); |
1509 } | 1560 } |
1510 | 1561 |
1511 Shell::ExecuteString(str, String::New(filename), false, false); | 1562 Shell::ExecuteString(str, String::New(filename), false, false); |
1512 } | 1563 } |
1513 | 1564 |
1514 thread_context.Dispose(); | 1565 thread_context.Dispose(); |
1515 ptr = next_line; | 1566 ptr = next_line; |
1516 } | 1567 } |
1517 } | 1568 } |
1518 #endif // V8_SHARED | 1569 #endif // V8_SHARED |
1519 | 1570 |
1520 | 1571 |
1521 SourceGroup::~SourceGroup() { | 1572 SourceGroup::~SourceGroup() { |
1522 #ifndef V8_SHARED | 1573 #ifndef V8_SHARED |
1523 delete next_semaphore_; | 1574 delete next_semaphore_; |
1524 next_semaphore_ = NULL; | 1575 next_semaphore_ = NULL; |
1525 delete done_semaphore_; | 1576 delete done_semaphore_; |
1526 done_semaphore_ = NULL; | 1577 done_semaphore_ = NULL; |
1527 delete thread_; | 1578 delete thread_; |
1528 thread_ = NULL; | 1579 thread_ = NULL; |
1529 #endif // V8_SHARED | 1580 #endif // V8_SHARED |
1530 } | 1581 } |
1531 | 1582 |
1532 | 1583 |
1533 void SourceGroup::Execute() { | 1584 void SourceGroup::Execute(Isolate* isolate) { |
1534 for (int i = begin_offset_; i < end_offset_; ++i) { | 1585 for (int i = begin_offset_; i < end_offset_; ++i) { |
1535 const char* arg = argv_[i]; | 1586 const char* arg = argv_[i]; |
1536 if (strcmp(arg, "-e") == 0 && i + 1 < end_offset_) { | 1587 if (strcmp(arg, "-e") == 0 && i + 1 < end_offset_) { |
1537 // Execute argument given to -e option directly. | 1588 // Execute argument given to -e option directly. |
1538 HandleScope handle_scope; | 1589 HandleScope handle_scope; |
1539 Handle<String> file_name = String::New("unnamed"); | 1590 Handle<String> file_name = String::New("unnamed"); |
1540 Handle<String> source = String::New(argv_[i + 1]); | 1591 Handle<String> source = String::New(argv_[i + 1]); |
1541 if (!Shell::ExecuteString(source, file_name, false, true)) { | 1592 if (!Shell::ExecuteString(source, file_name, false, true)) { |
1542 Shell::Exit(1); | 1593 Shell::Exit(1); |
1543 } | 1594 } |
1544 ++i; | 1595 ++i; |
1545 } else if (arg[0] == '-') { | 1596 } else if (arg[0] == '-') { |
1546 // Ignore other options. They have been parsed already. | 1597 // Ignore other options. They have been parsed already. |
1547 } else { | 1598 } else { |
1548 // Use all other arguments as names of files to load and run. | 1599 // Use all other arguments as names of files to load and run. |
1549 HandleScope handle_scope; | 1600 HandleScope handle_scope; |
1550 Handle<String> file_name = String::New(arg); | 1601 Handle<String> file_name = String::New(arg); |
1551 Handle<String> source = ReadFile(arg); | 1602 Handle<String> source = ReadFile(isolate, arg); |
1552 if (source.IsEmpty()) { | 1603 if (source.IsEmpty()) { |
1553 printf("Error reading '%s'\n", arg); | 1604 printf("Error reading '%s'\n", arg); |
1554 Shell::Exit(1); | 1605 Shell::Exit(1); |
1555 } | 1606 } |
1556 if (!Shell::ExecuteString(source, file_name, false, true)) { | 1607 if (!Shell::ExecuteString(source, file_name, false, true)) { |
1557 Shell::Exit(1); | 1608 Shell::Exit(1); |
1558 } | 1609 } |
1559 } | 1610 } |
1560 } | 1611 } |
1561 } | 1612 } |
1562 | 1613 |
1563 | 1614 |
1564 Handle<String> SourceGroup::ReadFile(const char* name) { | 1615 Handle<String> SourceGroup::ReadFile(Isolate* isolate, const char* name) { |
1565 int size; | 1616 int size; |
1566 char* chars = ReadChars(name, &size); | 1617 char* chars = ReadChars(isolate, name, &size); |
1567 if (chars == NULL) return Handle<String>(); | 1618 if (chars == NULL) return Handle<String>(); |
1568 Handle<String> result = String::New(chars, size); | 1619 Handle<String> result = String::New(chars, size); |
1569 delete[] chars; | 1620 delete[] chars; |
1570 return result; | 1621 return result; |
1571 } | 1622 } |
1572 | 1623 |
1573 | 1624 |
1574 #ifndef V8_SHARED | 1625 #ifndef V8_SHARED |
1575 i::Thread::Options SourceGroup::GetThreadOptions() { | 1626 i::Thread::Options SourceGroup::GetThreadOptions() { |
1576 // On some systems (OSX 10.6) the stack size default is 0.5Mb or less | 1627 // On some systems (OSX 10.6) the stack size default is 0.5Mb or less |
1577 // which is not enough to parse the big literal expressions used in tests. | 1628 // which is not enough to parse the big literal expressions used in tests. |
1578 // The stack size should be at least StackGuard::kLimitSize + some | 1629 // The stack size should be at least StackGuard::kLimitSize + some |
1579 // OS-specific padding for thread startup code. 2Mbytes seems to be enough. | 1630 // OS-specific padding for thread startup code. 2Mbytes seems to be enough. |
1580 return i::Thread::Options("IsolateThread", 2 * MB); | 1631 return i::Thread::Options("IsolateThread", 2 * MB); |
1581 } | 1632 } |
1582 | 1633 |
1583 | 1634 |
1584 void SourceGroup::ExecuteInThread() { | 1635 void SourceGroup::ExecuteInThread() { |
1585 Isolate* isolate = Isolate::New(); | 1636 Isolate* isolate = Isolate::New(); |
1586 do { | 1637 do { |
1587 if (next_semaphore_ != NULL) next_semaphore_->Wait(); | 1638 if (next_semaphore_ != NULL) next_semaphore_->Wait(); |
1588 { | 1639 { |
1589 Isolate::Scope iscope(isolate); | 1640 Isolate::Scope iscope(isolate); |
1590 Locker lock(isolate); | 1641 Locker lock(isolate); |
1591 HandleScope scope; | 1642 HandleScope scope; |
1592 Persistent<Context> context = Shell::CreateEvaluationContext(); | 1643 Symbols symbols(isolate); |
| 1644 Persistent<Context> context = Shell::CreateEvaluationContext(isolate); |
1593 { | 1645 { |
1594 Context::Scope cscope(context); | 1646 Context::Scope cscope(context); |
1595 Execute(); | 1647 Execute(isolate); |
1596 } | 1648 } |
1597 context.Dispose(); | 1649 context.Dispose(); |
1598 if (Shell::options.send_idle_notification) { | 1650 if (Shell::options.send_idle_notification) { |
1599 const int kLongIdlePauseInMs = 1000; | 1651 const int kLongIdlePauseInMs = 1000; |
1600 V8::ContextDisposedNotification(); | 1652 V8::ContextDisposedNotification(); |
1601 V8::IdleNotification(kLongIdlePauseInMs); | 1653 V8::IdleNotification(kLongIdlePauseInMs); |
1602 } | 1654 } |
1603 } | 1655 } |
1604 if (done_semaphore_ != NULL) done_semaphore_->Signal(); | 1656 if (done_semaphore_ != NULL) done_semaphore_->Signal(); |
1605 } while (!Shell::options.last_run); | 1657 } while (!Shell::options.last_run); |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1753 } else if (strncmp(argv[i], "--", 2) == 0) { | 1805 } else if (strncmp(argv[i], "--", 2) == 0) { |
1754 printf("Warning: unknown flag %s.\nTry --help for options\n", argv[i]); | 1806 printf("Warning: unknown flag %s.\nTry --help for options\n", argv[i]); |
1755 } | 1807 } |
1756 } | 1808 } |
1757 current->End(argc); | 1809 current->End(argc); |
1758 | 1810 |
1759 return true; | 1811 return true; |
1760 } | 1812 } |
1761 | 1813 |
1762 | 1814 |
1763 int Shell::RunMain(int argc, char* argv[]) { | 1815 int Shell::RunMain(Isolate* isolate, int argc, char* argv[]) { |
1764 #ifndef V8_SHARED | 1816 #ifndef V8_SHARED |
1765 i::List<i::Thread*> threads(1); | 1817 i::List<i::Thread*> threads(1); |
1766 if (options.parallel_files != NULL) { | 1818 if (options.parallel_files != NULL) { |
1767 for (int i = 0; i < options.num_parallel_files; i++) { | 1819 for (int i = 0; i < options.num_parallel_files; i++) { |
1768 char* files = NULL; | 1820 char* files = NULL; |
1769 { Locker lock(Isolate::GetCurrent()); | 1821 { Locker lock(isolate); |
1770 int size = 0; | 1822 int size = 0; |
1771 files = ReadChars(options.parallel_files[i], &size); | 1823 files = ReadChars(isolate, options.parallel_files[i], &size); |
1772 } | 1824 } |
1773 if (files == NULL) { | 1825 if (files == NULL) { |
1774 printf("File list '%s' not found\n", options.parallel_files[i]); | 1826 printf("File list '%s' not found\n", options.parallel_files[i]); |
1775 Exit(1); | 1827 Exit(1); |
1776 } | 1828 } |
1777 ShellThread* thread = new ShellThread(threads.length(), files); | 1829 ShellThread* thread = new ShellThread(isolate, threads.length(), files); |
1778 thread->Start(); | 1830 thread->Start(); |
1779 threads.Add(thread); | 1831 threads.Add(thread); |
1780 } | 1832 } |
1781 } | 1833 } |
1782 for (int i = 1; i < options.num_isolates; ++i) { | 1834 for (int i = 1; i < options.num_isolates; ++i) { |
1783 options.isolate_sources[i].StartExecuteInThread(); | 1835 options.isolate_sources[i].StartExecuteInThread(); |
1784 } | 1836 } |
1785 #endif // V8_SHARED | 1837 #endif // V8_SHARED |
1786 { // NOLINT | 1838 { // NOLINT |
1787 Locker lock; | 1839 Locker lock; |
1788 HandleScope scope; | 1840 HandleScope scope; |
1789 Persistent<Context> context = CreateEvaluationContext(); | 1841 Persistent<Context> context = CreateEvaluationContext(isolate); |
1790 if (options.last_run) { | 1842 if (options.last_run) { |
1791 // Keep using the same context in the interactive shell. | 1843 // Keep using the same context in the interactive shell. |
1792 evaluation_context_ = context; | 1844 evaluation_context_ = context; |
1793 #if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT) | 1845 #if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT) |
1794 // If the interactive debugger is enabled make sure to activate | 1846 // If the interactive debugger is enabled make sure to activate |
1795 // it before running the files passed on the command line. | 1847 // it before running the files passed on the command line. |
1796 if (i::FLAG_debugger) { | 1848 if (i::FLAG_debugger) { |
1797 InstallUtilityScript(); | 1849 InstallUtilityScript(); |
1798 } | 1850 } |
1799 #endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT | 1851 #endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT |
1800 } | 1852 } |
1801 { | 1853 { |
1802 Context::Scope cscope(context); | 1854 Context::Scope cscope(context); |
1803 options.isolate_sources[0].Execute(); | 1855 options.isolate_sources[0].Execute(isolate); |
1804 } | 1856 } |
1805 if (!options.last_run) { | 1857 if (!options.last_run) { |
1806 context.Dispose(); | 1858 context.Dispose(); |
1807 if (options.send_idle_notification) { | 1859 if (options.send_idle_notification) { |
1808 const int kLongIdlePauseInMs = 1000; | 1860 const int kLongIdlePauseInMs = 1000; |
1809 V8::ContextDisposedNotification(); | 1861 V8::ContextDisposedNotification(); |
1810 V8::IdleNotification(kLongIdlePauseInMs); | 1862 V8::IdleNotification(kLongIdlePauseInMs); |
1811 } | 1863 } |
1812 } | 1864 } |
1813 | 1865 |
(...skipping 21 matching lines...) Expand all Loading... |
1835 Locker lock; | 1887 Locker lock; |
1836 Locker::StopPreemption(); | 1888 Locker::StopPreemption(); |
1837 } | 1889 } |
1838 #endif // V8_SHARED | 1890 #endif // V8_SHARED |
1839 return 0; | 1891 return 0; |
1840 } | 1892 } |
1841 | 1893 |
1842 | 1894 |
1843 int Shell::Main(int argc, char* argv[]) { | 1895 int Shell::Main(int argc, char* argv[]) { |
1844 if (!SetOptions(argc, argv)) return 1; | 1896 if (!SetOptions(argc, argv)) return 1; |
1845 Initialize(); | 1897 int result = 0; |
| 1898 Isolate* isolate = Isolate::GetCurrent(); |
| 1899 { |
| 1900 Symbols symbols(isolate); |
| 1901 Initialize(isolate); |
1846 | 1902 |
1847 int result = 0; | 1903 if (options.stress_opt || options.stress_deopt) { |
1848 if (options.stress_opt || options.stress_deopt) { | 1904 Testing::SetStressRunType(options.stress_opt |
1849 Testing::SetStressRunType( | 1905 ? Testing::kStressTypeOpt |
1850 options.stress_opt ? Testing::kStressTypeOpt | 1906 : Testing::kStressTypeDeopt); |
1851 : Testing::kStressTypeDeopt); | 1907 int stress_runs = Testing::GetStressRuns(); |
1852 int stress_runs = Testing::GetStressRuns(); | 1908 for (int i = 0; i < stress_runs && result == 0; i++) { |
1853 for (int i = 0; i < stress_runs && result == 0; i++) { | 1909 printf("============ Stress %d/%d ============\n", i + 1, stress_runs); |
1854 printf("============ Stress %d/%d ============\n", i + 1, stress_runs); | 1910 Testing::PrepareStressRun(i); |
1855 Testing::PrepareStressRun(i); | 1911 options.last_run = (i == stress_runs - 1); |
1856 options.last_run = (i == stress_runs - 1); | 1912 result = RunMain(isolate, argc, argv); |
1857 result = RunMain(argc, argv); | 1913 } |
| 1914 printf("======== Full Deoptimization =======\n"); |
| 1915 Testing::DeoptimizeAll(); |
| 1916 #if !defined(V8_SHARED) |
| 1917 } else if (i::FLAG_stress_runs > 0) { |
| 1918 int stress_runs = i::FLAG_stress_runs; |
| 1919 for (int i = 0; i < stress_runs && result == 0; i++) { |
| 1920 printf("============ Run %d/%d ============\n", i + 1, stress_runs); |
| 1921 options.last_run = (i == stress_runs - 1); |
| 1922 result = RunMain(isolate, argc, argv); |
| 1923 } |
| 1924 #endif |
| 1925 } else { |
| 1926 result = RunMain(isolate, argc, argv); |
1858 } | 1927 } |
1859 printf("======== Full Deoptimization =======\n"); | |
1860 Testing::DeoptimizeAll(); | |
1861 #if !defined(V8_SHARED) | |
1862 } else if (i::FLAG_stress_runs > 0) { | |
1863 int stress_runs = i::FLAG_stress_runs; | |
1864 for (int i = 0; i < stress_runs && result == 0; i++) { | |
1865 printf("============ Run %d/%d ============\n", i + 1, stress_runs); | |
1866 options.last_run = (i == stress_runs - 1); | |
1867 result = RunMain(argc, argv); | |
1868 } | |
1869 #endif | |
1870 } else { | |
1871 result = RunMain(argc, argv); | |
1872 } | |
1873 | 1928 |
1874 | 1929 |
1875 #if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT) | 1930 #if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT) |
1876 // Run remote debugger if requested, but never on --test | 1931 // Run remote debugger if requested, but never on --test |
1877 if (i::FLAG_remote_debugger && !options.test_shell) { | 1932 if (i::FLAG_remote_debugger && !options.test_shell) { |
1878 InstallUtilityScript(); | 1933 InstallUtilityScript(); |
1879 RunRemoteDebugger(i::FLAG_debugger_port); | 1934 RunRemoteDebugger(i::FLAG_debugger_port); |
1880 return 0; | 1935 return 0; |
1881 } | 1936 } |
1882 #endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT | 1937 #endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT |
1883 | 1938 |
1884 // Run interactive shell if explicitly requested or if no script has been | 1939 // Run interactive shell if explicitly requested or if no script has been |
1885 // executed, but never on --test | 1940 // executed, but never on --test |
1886 | 1941 |
1887 if (( options.interactive_shell | 1942 if (( options.interactive_shell || !options.script_executed ) |
1888 || !options.script_executed ) | 1943 && !options.test_shell ) { |
1889 && !options.test_shell ) { | |
1890 #if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT) | 1944 #if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT) |
1891 if (!i::FLAG_debugger) { | 1945 if (!i::FLAG_debugger) { |
1892 InstallUtilityScript(); | 1946 InstallUtilityScript(); |
| 1947 } |
| 1948 #endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT |
| 1949 RunShell(isolate); |
1893 } | 1950 } |
1894 #endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT | |
1895 RunShell(); | |
1896 } | 1951 } |
1897 | |
1898 V8::Dispose(); | 1952 V8::Dispose(); |
1899 | 1953 |
1900 #ifndef V8_SHARED | 1954 #ifndef V8_SHARED |
1901 OnExit(); | 1955 OnExit(); |
1902 #endif // V8_SHARED | 1956 #endif // V8_SHARED |
1903 | 1957 |
1904 return result; | 1958 return result; |
1905 } | 1959 } |
1906 | 1960 |
1907 } // namespace v8 | 1961 } // namespace v8 |
1908 | 1962 |
1909 | 1963 |
1910 #ifndef GOOGLE3 | 1964 #ifndef GOOGLE3 |
1911 int main(int argc, char* argv[]) { | 1965 int main(int argc, char* argv[]) { |
1912 return v8::Shell::Main(argc, argv); | 1966 return v8::Shell::Main(argc, argv); |
1913 } | 1967 } |
1914 #endif | 1968 #endif |
OLD | NEW |