From 7e6dd6db1e20a9550149f8fac512b613380f0fc4 Mon Sep 17 00:00:00 2001 From: "svenpanne@chromium.org" Date: Tue, 20 Nov 2012 14:47:56 +0000 Subject: [PATCH] Drastically reduce the number of created strings in d8, 2nd attempt. This also reduces the number of TLS accesses, so it is a double-win. We have 230k less TLS accesses while running Octane now, so we are down to 23% now compared to the start of these TLS-related CLs. To get things right in the presence of multiple Isolates, we have to thread the correct Isolate through several layers. This threading wasn't that bad after all, it keeps one honest about the real depdencies. The only ugly thing is that in ExternalArrayWeakCallback we have to conjure up the current Isolate from the TLS, but this is a know API deficiency. Introduced a tiny helper function for throwing on the way. Review URL: https://codereview.chromium.org/11418088 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13018 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/d8.cc | 400 +++++++++++++++++++++++++++++++++++--------------------------- src/d8.h | 27 +++-- 2 files changed, 241 insertions(+), 186 deletions(-) diff --git a/src/d8.cc b/src/d8.cc index b3b1bb8..9fc909b 100644 --- a/src/d8.cc +++ b/src/d8.cc @@ -67,6 +67,62 @@ namespace v8 { + +static Handle Throw(const char* message) { + return ThrowException(String::New(message)); +} + + +// TODO(rossberg): should replace these by proper uses of HasInstance, +// once we figure out a good way to make the templates global. +const char kArrayBufferMarkerPropName[] = "d8::_is_array_buffer_"; +const char kArrayMarkerPropName[] = "d8::_is_typed_array_"; + + +#define FOR_EACH_SYMBOL(V) \ + V(ArrayBuffer, "ArrayBuffer") \ + V(ArrayBufferMarkerPropName, kArrayBufferMarkerPropName) \ + V(ArrayMarkerPropName, kArrayMarkerPropName) \ + V(buffer, "buffer") \ + V(byteLength, "byteLength") \ + V(byteOffset, "byteOffset") \ + V(BYTES_PER_ELEMENT, "BYTES_PER_ELEMENT") \ + V(length, "length") + + +class Symbols { + public: + explicit Symbols(Isolate* isolate) : isolate_(isolate) { + HandleScope scope; +#define INIT_SYMBOL(name, value) \ + name##_ = Persistent::New(String::NewSymbol(value)); + FOR_EACH_SYMBOL(INIT_SYMBOL) +#undef INIT_SYMBOL + isolate->SetData(this); + } + + ~Symbols() { +#define DISPOSE_SYMBOL(name, value) name##_.Dispose(); + FOR_EACH_SYMBOL(DISPOSE_SYMBOL) +#undef DISPOSE_SYMBOL + isolate_->SetData(NULL); // Not really needed, just to be sure... + } + +#define DEFINE_SYMBOL_GETTER(name, value) \ + static Persistent name(Isolate* isolate) { \ + return reinterpret_cast(isolate->GetData())->name##_; \ + } + FOR_EACH_SYMBOL(DEFINE_SYMBOL_GETTER) +#undef DEFINE_SYMBOL_GETTER + + private: + Isolate* isolate_; +#define DEFINE_MEMBER(name, value) Persistent name##_; + FOR_EACH_SYMBOL(DEFINE_MEMBER) +#undef DEFINE_MEMBER +}; + + LineEditor *LineEditor::first_ = NULL; @@ -92,17 +148,17 @@ LineEditor* LineEditor::Get() { class DumbLineEditor: public LineEditor { public: - DumbLineEditor() : LineEditor(LineEditor::DUMB, "dumb") { } + explicit DumbLineEditor(Isolate* isolate) + : LineEditor(LineEditor::DUMB, "dumb"), isolate_(isolate) { } virtual Handle Prompt(const char* prompt); + private: + Isolate* isolate_; }; -static DumbLineEditor dumb_line_editor; - - Handle DumbLineEditor::Prompt(const char* prompt) { printf("%s", prompt); - return Shell::ReadFromStdin(); + return Shell::ReadFromStdin(isolate_); } @@ -115,7 +171,6 @@ i::Mutex* Shell::context_mutex_(i::OS::CreateMutex()); Persistent Shell::utility_context_; #endif // V8_SHARED -LineEditor* Shell::console = NULL; Persistent Shell::evaluation_context_; ShellOptions Shell::options; const char* Shell::kPrompt = "d8> "; @@ -232,17 +287,17 @@ Handle Shell::DisableProfiler(const Arguments& args) { Handle Shell::Read(const Arguments& args) { String::Utf8Value file(args[0]); if (*file == NULL) { - return ThrowException(String::New("Error loading file")); + return Throw("Error loading file"); } - Handle source = ReadFile(*file); + Handle source = ReadFile(args.GetIsolate(), *file); if (source.IsEmpty()) { - return ThrowException(String::New("Error loading file")); + return Throw("Error loading file"); } return source; } -Handle Shell::ReadFromStdin() { +Handle Shell::ReadFromStdin(Isolate* isolate) { static const int kBufferSize = 256; char buffer[kBufferSize]; Handle accumulator = String::New(""); @@ -253,7 +308,7 @@ Handle Shell::ReadFromStdin() { // If fgets gets an error, just give up. char* input = NULL; { // Release lock for blocking input. - Unlocker unlock(Isolate::GetCurrent()); + Unlocker unlock(isolate); input = fgets(buffer, kBufferSize, stdin); } if (input == NULL) return Handle(); @@ -277,14 +332,14 @@ Handle Shell::Load(const Arguments& args) { HandleScope handle_scope; String::Utf8Value file(args[i]); if (*file == NULL) { - return ThrowException(String::New("Error loading file")); + return Throw("Error loading file"); } - Handle source = ReadFile(*file); + Handle source = ReadFile(args.GetIsolate(), *file); if (source.IsEmpty()) { - return ThrowException(String::New("Error loading file")); + return Throw("Error loading file"); } if (!ExecuteString(source, String::New(*file), false, true)) { - return ThrowException(String::New("Error executing file")); + return Throw("Error executing file"); } } return Undefined(); @@ -314,7 +369,7 @@ static int32_t convertToUint(Local value_in, TryCatch* try_catch) { if (try_catch->HasCaught()) return 0; if (raw_value < 0) { - ThrowException(String::New("Array length must not be negative.")); + Throw("Array length must not be negative."); return 0; } @@ -323,33 +378,27 @@ static int32_t convertToUint(Local value_in, TryCatch* try_catch) { ASSERT(kMaxLength == i::ExternalArray::kMaxLength); #endif // V8_SHARED if (raw_value > static_cast(kMaxLength)) { - ThrowException( - String::New("Array length exceeds maximum length.")); + Throw("Array length exceeds maximum length."); } return raw_value; } -// TODO(rossberg): should replace these by proper uses of HasInstance, -// once we figure out a good way to make the templates global. -const char kArrayBufferMarkerPropName[] = "d8::_is_array_buffer_"; -const char kArrayMarkerPropName[] = "d8::_is_typed_array_"; - - -Handle Shell::CreateExternalArrayBuffer(Handle buffer, +Handle Shell::CreateExternalArrayBuffer(Isolate* isolate, + Handle buffer, int32_t length) { static const int32_t kMaxSize = 0x7fffffff; // Make sure the total size fits into a (signed) int. if (length < 0 || length > kMaxSize) { - return ThrowException(String::New("ArrayBuffer exceeds maximum size (2G)")); + return Throw("ArrayBuffer exceeds maximum size (2G)"); } uint8_t* data = new uint8_t[length]; if (data == NULL) { - return ThrowException(String::New("Memory allocation failed")); + return Throw("Memory allocation failed"); } memset(data, 0, length); - buffer->SetHiddenValue(String::New(kArrayBufferMarkerPropName), True()); + buffer->SetHiddenValue(Symbols::ArrayBufferMarkerPropName(isolate), True()); Persistent persistent_array = Persistent::New(buffer); persistent_array.MakeWeak(data, ExternalArrayWeakCallback); persistent_array.MarkIndependent(); @@ -357,7 +406,7 @@ Handle Shell::CreateExternalArrayBuffer(Handle buffer, buffer->SetIndexedPropertiesToExternalArrayData( data, v8::kExternalByteArray, length); - buffer->Set(String::New("byteLength"), Int32::New(length), ReadOnly); + buffer->Set(Symbols::byteLength(isolate), Int32::New(length), ReadOnly); return buffer; } @@ -373,18 +422,18 @@ Handle Shell::ArrayBuffer(const Arguments& args) { } if (args.Length() == 0) { - return ThrowException( - String::New("ArrayBuffer constructor must have one argument")); + return Throw("ArrayBuffer constructor must have one argument"); } TryCatch try_catch; int32_t length = convertToUint(args[0], &try_catch); if (try_catch.HasCaught()) return try_catch.ReThrow(); - return CreateExternalArrayBuffer(args.This(), length); + return CreateExternalArrayBuffer(args.GetIsolate(), args.This(), length); } -Handle Shell::CreateExternalArray(Handle array, +Handle Shell::CreateExternalArray(Isolate* isolate, + Handle array, Handle buffer, ExternalArrayType type, int32_t length, @@ -400,12 +449,13 @@ Handle Shell::CreateExternalArray(Handle array, array->SetIndexedPropertiesToExternalArrayData( static_cast(data) + byteOffset, type, length); - array->SetHiddenValue(String::New(kArrayMarkerPropName), Int32::New(type)); - array->Set(String::New("byteLength"), Int32::New(byteLength), ReadOnly); - array->Set(String::New("byteOffset"), Int32::New(byteOffset), ReadOnly); - array->Set(String::New("length"), Int32::New(length), ReadOnly); - array->Set(String::New("BYTES_PER_ELEMENT"), Int32::New(element_size)); - array->Set(String::New("buffer"), buffer, ReadOnly); + array->SetHiddenValue(Symbols::ArrayMarkerPropName(isolate), + Int32::New(type)); + array->Set(Symbols::byteLength(isolate), Int32::New(byteLength), ReadOnly); + array->Set(Symbols::byteOffset(isolate), Int32::New(byteOffset), ReadOnly); + array->Set(Symbols::length(isolate), Int32::New(length), ReadOnly); + array->Set(Symbols::BYTES_PER_ELEMENT(isolate), Int32::New(element_size)); + array->Set(Symbols::buffer(isolate), buffer, ReadOnly); return array; } @@ -414,6 +464,7 @@ Handle Shell::CreateExternalArray(Handle array, Handle Shell::CreateExternalArray(const Arguments& args, ExternalArrayType type, int32_t element_size) { + Isolate* isolate = args.GetIsolate(); if (!args.IsConstructCall()) { Handle* rec_args = new Handle[args.Length()]; for (int i = 0; i < args.Length(); ++i) rec_args[i] = args[i]; @@ -439,16 +490,15 @@ Handle Shell::CreateExternalArray(const Arguments& args, int32_t byteOffset; bool init_from_array = false; if (args.Length() == 0) { - return ThrowException( - String::New("Array constructor must have at least one argument")); + return Throw("Array constructor must have at least one argument"); } if (args[0]->IsObject() && !args[0]->ToObject()->GetHiddenValue( - String::New(kArrayBufferMarkerPropName)).IsEmpty()) { + Symbols::ArrayBufferMarkerPropName(isolate)).IsEmpty()) { // Construct from ArrayBuffer. buffer = args[0]->ToObject(); int32_t bufferLength = - convertToUint(buffer->Get(String::New("byteLength")), &try_catch); + convertToUint(buffer->Get(Symbols::byteLength(isolate)), &try_catch); if (try_catch.HasCaught()) return try_catch.ReThrow(); if (args.Length() < 2 || args[1]->IsUndefined()) { @@ -457,11 +507,10 @@ Handle Shell::CreateExternalArray(const Arguments& args, byteOffset = convertToUint(args[1], &try_catch); if (try_catch.HasCaught()) return try_catch.ReThrow(); if (byteOffset > bufferLength) { - return ThrowException(String::New("byteOffset out of bounds")); + return Throw("byteOffset out of bounds"); } if (byteOffset % element_size != 0) { - return ThrowException( - String::New("byteOffset must be multiple of element size")); + return Throw("byteOffset must be multiple of element size"); } } @@ -469,23 +518,22 @@ Handle Shell::CreateExternalArray(const Arguments& args, byteLength = bufferLength - byteOffset; length = byteLength / element_size; if (byteLength % element_size != 0) { - return ThrowException( - String::New("buffer size must be multiple of element size")); + return Throw("buffer size must be multiple of element size"); } } else { length = convertToUint(args[2], &try_catch); if (try_catch.HasCaught()) return try_catch.ReThrow(); byteLength = length * element_size; if (byteOffset + byteLength > bufferLength) { - return ThrowException(String::New("length out of bounds")); + return Throw("length out of bounds"); } } } else { if (args[0]->IsObject() && - args[0]->ToObject()->Has(String::New("length"))) { + args[0]->ToObject()->Has(Symbols::length(isolate))) { // Construct from array. length = convertToUint( - args[0]->ToObject()->Get(String::New("length")), &try_catch); + args[0]->ToObject()->Get(Symbols::length(isolate)), &try_catch); if (try_catch.HasCaught()) return try_catch.ReThrow(); init_from_array = true; } else { @@ -497,7 +545,7 @@ Handle Shell::CreateExternalArray(const Arguments& args, byteOffset = 0; Handle global = Context::GetCurrent()->Global(); - Handle array_buffer = global->Get(String::New("ArrayBuffer")); + Handle array_buffer = global->Get(Symbols::ArrayBuffer(isolate)); ASSERT(!try_catch.HasCaught() && array_buffer->IsFunction()); Handle buffer_args[] = { Uint32::New(byteLength) }; Handle result = Handle::Cast(array_buffer)->NewInstance( @@ -506,8 +554,9 @@ Handle Shell::CreateExternalArray(const Arguments& args, buffer = result->ToObject(); } - Handle array = CreateExternalArray( - args.This(), buffer, type, length, byteLength, byteOffset, element_size); + Handle array = + CreateExternalArray(isolate, args.This(), buffer, type, length, + byteLength, byteOffset, element_size); if (init_from_array) { Handle init = args[0]->ToObject(); @@ -522,25 +571,23 @@ Handle Shell::ArrayBufferSlice(const Arguments& args) { TryCatch try_catch; if (!args.This()->IsObject()) { - return ThrowException( - String::New("'slice' invoked on non-object receiver")); + return Throw("'slice' invoked on non-object receiver"); } + Isolate* isolate = args.GetIsolate(); Local self = args.This(); Local marker = - self->GetHiddenValue(String::New(kArrayBufferMarkerPropName)); + self->GetHiddenValue(Symbols::ArrayBufferMarkerPropName(isolate)); if (marker.IsEmpty()) { - return ThrowException( - String::New("'slice' invoked on wrong receiver type")); + return Throw("'slice' invoked on wrong receiver type"); } int32_t length = - convertToUint(self->Get(String::New("byteLength")), &try_catch); + convertToUint(self->Get(Symbols::byteLength(isolate)), &try_catch); if (try_catch.HasCaught()) return try_catch.ReThrow(); if (args.Length() == 0) { - return ThrowException( - String::New("'slice' must have at least one argument")); + return Throw("'slice' must have at least one argument"); } int32_t begin = convertToInt(args[0], &try_catch); if (try_catch.HasCaught()) return try_catch.ReThrow(); @@ -579,32 +626,31 @@ Handle Shell::ArraySubArray(const Arguments& args) { TryCatch try_catch; if (!args.This()->IsObject()) { - return ThrowException( - String::New("'subarray' invoked on non-object receiver")); + return Throw("'subarray' invoked on non-object receiver"); } + Isolate* isolate = args.GetIsolate(); Local self = args.This(); - Local marker = self->GetHiddenValue(String::New(kArrayMarkerPropName)); + Local marker = + self->GetHiddenValue(Symbols::ArrayMarkerPropName(isolate)); if (marker.IsEmpty()) { - return ThrowException( - String::New("'subarray' invoked on wrong receiver type")); + return Throw("'subarray' invoked on wrong receiver type"); } - Handle buffer = self->Get(String::New("buffer"))->ToObject(); + Handle buffer = self->Get(Symbols::buffer(isolate))->ToObject(); if (try_catch.HasCaught()) return try_catch.ReThrow(); int32_t length = - convertToUint(self->Get(String::New("length")), &try_catch); + convertToUint(self->Get(Symbols::length(isolate)), &try_catch); if (try_catch.HasCaught()) return try_catch.ReThrow(); int32_t byteOffset = - convertToUint(self->Get(String::New("byteOffset")), &try_catch); + convertToUint(self->Get(Symbols::byteOffset(isolate)), &try_catch); if (try_catch.HasCaught()) return try_catch.ReThrow(); int32_t element_size = - convertToUint(self->Get(String::New("BYTES_PER_ELEMENT")), &try_catch); + convertToUint(self->Get(Symbols::BYTES_PER_ELEMENT(isolate)), &try_catch); if (try_catch.HasCaught()) return try_catch.ReThrow(); if (args.Length() == 0) { - return ThrowException( - String::New("'subarray' must have at least one argument")); + return Throw("'subarray' must have at least one argument"); } int32_t begin = convertToInt(args[0], &try_catch); if (try_catch.HasCaught()) return try_catch.ReThrow(); @@ -639,35 +685,33 @@ Handle Shell::ArraySet(const Arguments& args) { TryCatch try_catch; if (!args.This()->IsObject()) { - return ThrowException( - String::New("'set' invoked on non-object receiver")); + return Throw("'set' invoked on non-object receiver"); } + Isolate* isolate = args.GetIsolate(); Local self = args.This(); - Local marker = self->GetHiddenValue(String::New(kArrayMarkerPropName)); + Local marker = + self->GetHiddenValue(Symbols::ArrayMarkerPropName(isolate)); if (marker.IsEmpty()) { - return ThrowException( - String::New("'set' invoked on wrong receiver type")); + return Throw("'set' invoked on wrong receiver type"); } int32_t length = - convertToUint(self->Get(String::New("length")), &try_catch); + convertToUint(self->Get(Symbols::length(isolate)), &try_catch); if (try_catch.HasCaught()) return try_catch.ReThrow(); int32_t element_size = - convertToUint(self->Get(String::New("BYTES_PER_ELEMENT")), &try_catch); + convertToUint(self->Get(Symbols::BYTES_PER_ELEMENT(isolate)), &try_catch); if (try_catch.HasCaught()) return try_catch.ReThrow(); if (args.Length() == 0) { - return ThrowException( - String::New("'set' must have at least one argument")); + return Throw("'set' must have at least one argument"); } if (!args[0]->IsObject() || - !args[0]->ToObject()->Has(String::New("length"))) { - return ThrowException( - String::New("'set' invoked with non-array argument")); + !args[0]->ToObject()->Has(Symbols::length(isolate))) { + return Throw("'set' invoked with non-array argument"); } Handle source = args[0]->ToObject(); int32_t source_length = - convertToUint(source->Get(String::New("length")), &try_catch); + convertToUint(source->Get(Symbols::length(isolate)), &try_catch); if (try_catch.HasCaught()) return try_catch.ReThrow(); int32_t offset; @@ -678,31 +722,32 @@ Handle Shell::ArraySet(const Arguments& args) { if (try_catch.HasCaught()) return try_catch.ReThrow(); } if (offset + source_length > length) { - return ThrowException(String::New("offset or source length out of bounds")); + return Throw("offset or source length out of bounds"); } int32_t source_element_size; - if (source->GetHiddenValue(String::New(kArrayMarkerPropName)).IsEmpty()) { + if (source->GetHiddenValue(Symbols::ArrayMarkerPropName(isolate)).IsEmpty()) { source_element_size = 0; } else { source_element_size = - convertToUint(source->Get(String::New("BYTES_PER_ELEMENT")), &try_catch); + convertToUint(source->Get(Symbols::BYTES_PER_ELEMENT(isolate)), + &try_catch); if (try_catch.HasCaught()) return try_catch.ReThrow(); } if (element_size == source_element_size && self->GetConstructor()->StrictEquals(source->GetConstructor())) { // Use memmove on the array buffers. - Handle buffer = self->Get(String::New("buffer"))->ToObject(); + Handle buffer = self->Get(Symbols::buffer(isolate))->ToObject(); if (try_catch.HasCaught()) return try_catch.ReThrow(); Handle source_buffer = - source->Get(String::New("buffer"))->ToObject(); + source->Get(Symbols::buffer(isolate))->ToObject(); if (try_catch.HasCaught()) return try_catch.ReThrow(); int32_t byteOffset = - convertToUint(self->Get(String::New("byteOffset")), &try_catch); + convertToUint(self->Get(Symbols::byteOffset(isolate)), &try_catch); if (try_catch.HasCaught()) return try_catch.ReThrow(); int32_t source_byteOffset = - convertToUint(source->Get(String::New("byteOffset")), &try_catch); + convertToUint(source->Get(Symbols::byteOffset(isolate)), &try_catch); if (try_catch.HasCaught()) return try_catch.ReThrow(); uint8_t* dest = byteOffset + offset * element_size + static_cast( @@ -718,10 +763,10 @@ Handle Shell::ArraySet(const Arguments& args) { } } else { // Need to copy element-wise to make the right conversions. - Handle buffer = self->Get(String::New("buffer"))->ToObject(); + Handle buffer = self->Get(Symbols::buffer(isolate))->ToObject(); if (try_catch.HasCaught()) return try_catch.ReThrow(); Handle source_buffer = - source->Get(String::New("buffer"))->ToObject(); + source->Get(Symbols::buffer(isolate))->ToObject(); if (try_catch.HasCaught()) return try_catch.ReThrow(); if (buffer->StrictEquals(source_buffer)) { @@ -729,10 +774,10 @@ Handle Shell::ArraySet(const Arguments& args) { // This gets a bit tricky in the case of different element sizes // (which, of course, is extremely unlikely to ever occur in practice). int32_t byteOffset = - convertToUint(self->Get(String::New("byteOffset")), &try_catch); + convertToUint(self->Get(Symbols::byteOffset(isolate)), &try_catch); if (try_catch.HasCaught()) return try_catch.ReThrow(); int32_t source_byteOffset = - convertToUint(source->Get(String::New("byteOffset")), &try_catch); + convertToUint(source->Get(Symbols::byteOffset(isolate)), &try_catch); if (try_catch.HasCaught()) return try_catch.ReThrow(); // Copy as much as we can from left to right. @@ -778,8 +823,9 @@ Handle Shell::ArraySet(const Arguments& args) { void Shell::ExternalArrayWeakCallback(Persistent object, void* data) { HandleScope scope; + Isolate* isolate = Isolate::GetCurrent(); int32_t length = - object->ToObject()->Get(String::New("byteLength"))->Uint32Value(); + object->ToObject()->Get(Symbols::byteLength(isolate))->Uint32Value(); V8::AdjustAmountOfExternalAllocatedMemory(-length); delete[] static_cast(data); object.Dispose(); @@ -1145,7 +1191,7 @@ Handle Shell::CreateArrayTemplate(InvocationCallback fun) { } -Handle Shell::CreateGlobalTemplate() { +Handle Shell::CreateGlobalTemplate(Isolate* isolate) { Handle global_template = ObjectTemplate::New(); global_template->Set(String::New("print"), FunctionTemplate::New(Print)); global_template->Set(String::New("write"), FunctionTemplate::New(Write)); @@ -1165,7 +1211,7 @@ Handle Shell::CreateGlobalTemplate() { // Bind the handlers for external arrays. PropertyAttribute attr = static_cast(ReadOnly | DontDelete); - global_template->Set(String::New("ArrayBuffer"), + global_template->Set(Symbols::ArrayBuffer(isolate), CreateArrayBufferTemplate(ArrayBuffer), attr); global_template->Set(String::New("Int8Array"), CreateArrayTemplate(Int8Array), attr); @@ -1202,7 +1248,7 @@ Handle Shell::CreateGlobalTemplate() { } -void Shell::Initialize() { +void Shell::Initialize(Isolate* isolate) { #ifdef COMPRESS_STARTUP_DATA_BZ2 BZip2Decompressor startup_data_decompressor; int bz2_result = startup_data_decompressor.Decompress(); @@ -1228,7 +1274,7 @@ void Shell::Initialize() { #ifndef V8_SHARED Locker lock; HandleScope scope; - Handle global_template = CreateGlobalTemplate(); + Handle global_template = CreateGlobalTemplate(isolate); utility_context_ = Context::New(NULL, global_template); #ifdef ENABLE_DEBUGGER_SUPPORT @@ -1242,13 +1288,13 @@ void Shell::Initialize() { } -Persistent Shell::CreateEvaluationContext() { +Persistent Shell::CreateEvaluationContext(Isolate* isolate) { #ifndef V8_SHARED // This needs to be a critical section since this is not thread-safe i::ScopedLock lock(context_mutex_); #endif // V8_SHARED // Initialize the global objects - Handle global_template = CreateGlobalTemplate(); + Handle global_template = CreateGlobalTemplate(isolate); Persistent context = Context::New(NULL, global_template); ASSERT(!context.IsEmpty()); Context::Scope scope(context); @@ -1294,7 +1340,6 @@ int CompareKeys(const void* a, const void* b) { void Shell::OnExit() { - if (console != NULL) console->Close(); if (i::FLAG_dump_counters) { int number_of_counters = 0; for (CounterMap::Iterator i(counter_map_); i.More(); i.Next()) { @@ -1354,9 +1399,9 @@ static FILE* FOpen(const char* path, const char* mode) { } -static char* ReadChars(const char* name, int* size_out) { +static char* ReadChars(Isolate* isolate, const char* name, int* size_out) { // Release the V8 lock while reading files. - v8::Unlocker unlocker(Isolate::GetCurrent()); + v8::Unlocker unlocker(isolate); FILE* file = FOpen(name, "rb"); if (file == NULL) return NULL; @@ -1381,15 +1426,17 @@ Handle Shell::ReadBuffer(const Arguments& args) { String::Utf8Value filename(args[0]); int length; if (*filename == NULL) { - return ThrowException(String::New("Error loading file")); + return Throw("Error loading file"); } - uint8_t* data = reinterpret_cast(ReadChars(*filename, &length)); + uint8_t* data = reinterpret_cast( + ReadChars(args.GetIsolate(), *filename, &length)); if (data == NULL) { - return ThrowException(String::New("Error reading file")); + return Throw("Error reading file"); } + Isolate* isolate = args.GetIsolate(); Handle buffer = Object::New(); - buffer->SetHiddenValue(String::New(kArrayBufferMarkerPropName), True()); + buffer->SetHiddenValue(Symbols::ArrayBufferMarkerPropName(isolate), True()); Persistent persistent_buffer = Persistent::New(buffer); persistent_buffer.MakeWeak(data, ExternalArrayWeakCallback); persistent_buffer.MarkIndependent(); @@ -1397,7 +1444,7 @@ Handle Shell::ReadBuffer(const Arguments& args) { buffer->SetIndexedPropertiesToExternalArrayData( data, kExternalUnsignedByteArray, length); - buffer->Set(String::New("byteLength"), + buffer->Set(Symbols::byteLength(isolate), Int32::New(static_cast(length)), ReadOnly); return buffer; } @@ -1427,9 +1474,9 @@ static char* ReadWord(char* data) { // Reads a file into a v8 string. -Handle Shell::ReadFile(const char* name) { +Handle Shell::ReadFile(Isolate* isolate, const char* name) { int size = 0; - char* chars = ReadChars(name, &size); + char* chars = ReadChars(isolate, name, &size); if (chars == NULL) return Handle(); Handle result = String::New(chars); delete[] chars; @@ -1437,12 +1484,13 @@ Handle Shell::ReadFile(const char* name) { } -void Shell::RunShell() { +void Shell::RunShell(Isolate* isolate) { Locker locker; Context::Scope context_scope(evaluation_context_); HandleScope outer_scope; Handle name = String::New("(d8)"); - console = LineEditor::Get(); + DumbLineEditor dumb_line_editor(isolate); + LineEditor* console = LineEditor::Get(); printf("V8 version %s [console: %s]\n", V8::GetVersion(), console->name()); console->Open(); while (true) { @@ -1452,6 +1500,7 @@ void Shell::RunShell() { ExecuteString(input, name, true, true); } printf("\n"); + console->Close(); } @@ -1459,9 +1508,9 @@ void Shell::RunShell() { class ShellThread : public i::Thread { public: // Takes ownership of the underlying char array of |files|. - ShellThread(int no, char* files) + ShellThread(Isolate* isolate, int no, char* files) : Thread("d8:ShellThread"), - no_(no), files_(files) { } + isolate_(isolate), no_(no), files_(files) { } ~ShellThread() { delete[] files_; @@ -1469,6 +1518,7 @@ class ShellThread : public i::Thread { virtual void Run(); private: + Isolate* isolate_; int no_; char* files_; }; @@ -1489,7 +1539,8 @@ void ShellThread::Run() { // Prepare the context for this thread. Locker locker; HandleScope outer_scope; - Persistent thread_context = Shell::CreateEvaluationContext(); + Persistent thread_context = + Shell::CreateEvaluationContext(isolate_); Context::Scope context_scope(thread_context); while ((ptr != NULL) && (*ptr != '\0')) { @@ -1502,7 +1553,7 @@ void ShellThread::Run() { continue; } - Handle str = Shell::ReadFile(filename); + Handle str = Shell::ReadFile(isolate_, filename); if (str.IsEmpty()) { printf("File '%s' not found\n", filename); Shell::Exit(1); @@ -1530,7 +1581,7 @@ SourceGroup::~SourceGroup() { } -void SourceGroup::Execute() { +void SourceGroup::Execute(Isolate* isolate) { for (int i = begin_offset_; i < end_offset_; ++i) { const char* arg = argv_[i]; if (strcmp(arg, "-e") == 0 && i + 1 < end_offset_) { @@ -1548,7 +1599,7 @@ void SourceGroup::Execute() { // Use all other arguments as names of files to load and run. HandleScope handle_scope; Handle file_name = String::New(arg); - Handle source = ReadFile(arg); + Handle source = ReadFile(isolate, arg); if (source.IsEmpty()) { printf("Error reading '%s'\n", arg); Shell::Exit(1); @@ -1561,9 +1612,9 @@ void SourceGroup::Execute() { } -Handle SourceGroup::ReadFile(const char* name) { +Handle SourceGroup::ReadFile(Isolate* isolate, const char* name) { int size; - char* chars = ReadChars(name, &size); + char* chars = ReadChars(isolate, name, &size); if (chars == NULL) return Handle(); Handle result = String::New(chars, size); delete[] chars; @@ -1589,10 +1640,11 @@ void SourceGroup::ExecuteInThread() { Isolate::Scope iscope(isolate); Locker lock(isolate); HandleScope scope; - Persistent context = Shell::CreateEvaluationContext(); + Symbols symbols(isolate); + Persistent context = Shell::CreateEvaluationContext(isolate); { Context::Scope cscope(context); - Execute(); + Execute(isolate); } context.Dispose(); if (Shell::options.send_idle_notification) { @@ -1760,21 +1812,21 @@ bool Shell::SetOptions(int argc, char* argv[]) { } -int Shell::RunMain(int argc, char* argv[]) { +int Shell::RunMain(Isolate* isolate, int argc, char* argv[]) { #ifndef V8_SHARED i::List threads(1); if (options.parallel_files != NULL) { for (int i = 0; i < options.num_parallel_files; i++) { char* files = NULL; - { Locker lock(Isolate::GetCurrent()); + { Locker lock(isolate); int size = 0; - files = ReadChars(options.parallel_files[i], &size); + files = ReadChars(isolate, options.parallel_files[i], &size); } if (files == NULL) { printf("File list '%s' not found\n", options.parallel_files[i]); Exit(1); } - ShellThread* thread = new ShellThread(threads.length(), files); + ShellThread* thread = new ShellThread(isolate, threads.length(), files); thread->Start(); threads.Add(thread); } @@ -1786,7 +1838,7 @@ int Shell::RunMain(int argc, char* argv[]) { { // NOLINT Locker lock; HandleScope scope; - Persistent context = CreateEvaluationContext(); + Persistent context = CreateEvaluationContext(isolate); if (options.last_run) { // Keep using the same context in the interactive shell. evaluation_context_ = context; @@ -1800,7 +1852,7 @@ int Shell::RunMain(int argc, char* argv[]) { } { Context::Scope cscope(context); - options.isolate_sources[0].Execute(); + options.isolate_sources[0].Execute(isolate); } if (!options.last_run) { context.Dispose(); @@ -1842,59 +1894,61 @@ int Shell::RunMain(int argc, char* argv[]) { int Shell::Main(int argc, char* argv[]) { if (!SetOptions(argc, argv)) return 1; - Initialize(); - int result = 0; - if (options.stress_opt || options.stress_deopt) { - Testing::SetStressRunType( - options.stress_opt ? Testing::kStressTypeOpt - : Testing::kStressTypeDeopt); - int stress_runs = Testing::GetStressRuns(); - for (int i = 0; i < stress_runs && result == 0; i++) { - printf("============ Stress %d/%d ============\n", i + 1, stress_runs); - Testing::PrepareStressRun(i); - options.last_run = (i == stress_runs - 1); - result = RunMain(argc, argv); - } - printf("======== Full Deoptimization =======\n"); - Testing::DeoptimizeAll(); + Isolate* isolate = Isolate::GetCurrent(); + { + Symbols symbols(isolate); + Initialize(isolate); + + if (options.stress_opt || options.stress_deopt) { + Testing::SetStressRunType(options.stress_opt + ? Testing::kStressTypeOpt + : Testing::kStressTypeDeopt); + int stress_runs = Testing::GetStressRuns(); + for (int i = 0; i < stress_runs && result == 0; i++) { + printf("============ Stress %d/%d ============\n", i + 1, stress_runs); + Testing::PrepareStressRun(i); + options.last_run = (i == stress_runs - 1); + result = RunMain(isolate, argc, argv); + } + printf("======== Full Deoptimization =======\n"); + Testing::DeoptimizeAll(); #if !defined(V8_SHARED) - } else if (i::FLAG_stress_runs > 0) { - int stress_runs = i::FLAG_stress_runs; - for (int i = 0; i < stress_runs && result == 0; i++) { - printf("============ Run %d/%d ============\n", i + 1, stress_runs); - options.last_run = (i == stress_runs - 1); - result = RunMain(argc, argv); - } + } else if (i::FLAG_stress_runs > 0) { + int stress_runs = i::FLAG_stress_runs; + for (int i = 0; i < stress_runs && result == 0; i++) { + printf("============ Run %d/%d ============\n", i + 1, stress_runs); + options.last_run = (i == stress_runs - 1); + result = RunMain(isolate, argc, argv); + } #endif - } else { - result = RunMain(argc, argv); - } + } else { + result = RunMain(isolate, argc, argv); + } #if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT) - // Run remote debugger if requested, but never on --test - if (i::FLAG_remote_debugger && !options.test_shell) { - InstallUtilityScript(); - RunRemoteDebugger(i::FLAG_debugger_port); - return 0; - } + // Run remote debugger if requested, but never on --test + if (i::FLAG_remote_debugger && !options.test_shell) { + InstallUtilityScript(); + RunRemoteDebugger(i::FLAG_debugger_port); + return 0; + } #endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT - // Run interactive shell if explicitly requested or if no script has been - // executed, but never on --test + // Run interactive shell if explicitly requested or if no script has been + // executed, but never on --test - if (( options.interactive_shell - || !options.script_executed ) - && !options.test_shell ) { + if (( options.interactive_shell || !options.script_executed ) + && !options.test_shell ) { #if !defined(V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT) - if (!i::FLAG_debugger) { - InstallUtilityScript(); - } + if (!i::FLAG_debugger) { + InstallUtilityScript(); + } #endif // !V8_SHARED && ENABLE_DEBUGGER_SUPPORT - RunShell(); + RunShell(isolate); + } } - V8::Dispose(); #ifndef V8_SHARED diff --git a/src/d8.h b/src/d8.h index a62a81f..b87b404 100644 --- a/src/d8.h +++ b/src/d8.h @@ -158,7 +158,7 @@ class SourceGroup { void End(int offset) { end_offset_ = offset; } - void Execute(); + void Execute(Isolate* isolate); #ifndef V8_SHARED void StartExecuteInThread(); @@ -187,7 +187,7 @@ class SourceGroup { #endif // V8_SHARED void ExitShell(int exit_code); - Handle ReadFile(const char* name); + Handle ReadFile(Isolate* isolate, const char* name); const char** argv_; int begin_offset_; @@ -272,9 +272,9 @@ class Shell : public i::AllStatic { bool report_exceptions); static const char* ToCString(const v8::String::Utf8Value& value); static void ReportException(TryCatch* try_catch); - static Handle ReadFile(const char* name); - static Persistent CreateEvaluationContext(); - static int RunMain(int argc, char* argv[]); + static Handle ReadFile(Isolate* isolate, const char* name); + static Persistent CreateEvaluationContext(Isolate* isolate); + static int RunMain(Isolate* isolate, int argc, char* argv[]); static int Main(int argc, char* argv[]); static void Exit(int exit_code); @@ -310,9 +310,9 @@ class Shell : public i::AllStatic { static Handle DisableProfiler(const Arguments& args); static Handle Read(const Arguments& args); static Handle ReadBuffer(const Arguments& args); - static Handle ReadFromStdin(); + static Handle ReadFromStdin(Isolate* isolate); static Handle ReadLine(const Arguments& args) { - return ReadFromStdin(); + return ReadFromStdin(args.GetIsolate()); } static Handle Load(const Arguments& args); static Handle ArrayBuffer(const Arguments& args); @@ -365,7 +365,6 @@ class Shell : public i::AllStatic { static void AddOSMethods(Handle os_template); - static LineEditor* console; static const char* kPrompt; static ShellOptions options; @@ -384,15 +383,17 @@ class Shell : public i::AllStatic { static Counter* GetCounter(const char* name, bool is_histogram); static void InstallUtilityScript(); #endif // V8_SHARED - static void Initialize(); - static void RunShell(); + static void Initialize(Isolate* isolate); + static void RunShell(Isolate* isolate); static bool SetOptions(int argc, char* argv[]); - static Handle CreateGlobalTemplate(); + static Handle CreateGlobalTemplate(Isolate* isolate); static Handle CreateArrayBufferTemplate(InvocationCallback); static Handle CreateArrayTemplate(InvocationCallback); - static Handle CreateExternalArrayBuffer(Handle buffer, + static Handle CreateExternalArrayBuffer(Isolate* isolate, + Handle buffer, int32_t size); - static Handle CreateExternalArray(Handle array, + static Handle CreateExternalArray(Isolate* isolate, + Handle array, Handle buffer, ExternalArrayType type, int32_t length, -- 2.7.4