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