diff options
Diffstat (limited to 'deps/v8/src/api.cc')
-rw-r--r-- | deps/v8/src/api.cc | 243 |
1 files changed, 198 insertions, 45 deletions
diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index 0d88047aa2..dcbc894574 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -33,6 +33,7 @@ #include "../include/v8-profiler.h" #include "../include/v8-testing.h" #include "bootstrapper.h" +#include "code-stubs.h" #include "compiler.h" #include "conversions-inl.h" #include "counters.h" @@ -540,7 +541,9 @@ Extension::Extension(const char* name, source_(source, source_length_), dep_count_(dep_count), deps_(deps), - auto_enable_(false) { } + auto_enable_(false) { + CHECK(source != NULL || source_length_ == 0); +} v8::Handle<Primitive> Undefined() { @@ -767,8 +770,8 @@ void Context::SetData(v8::Handle<String> data) { i::Isolate* isolate = env->GetIsolate(); if (IsDeadCheck(isolate, "v8::Context::SetData()")) return; i::Handle<i::Object> raw_data = Utils::OpenHandle(*data); - ASSERT(env->IsGlobalContext()); - if (env->IsGlobalContext()) { + ASSERT(env->IsNativeContext()); + if (env->IsNativeContext()) { env->set_data(*raw_data); } } @@ -781,8 +784,8 @@ v8::Local<v8::Value> Context::GetData() { return v8::Local<Value>(); } i::Object* raw_result = NULL; - ASSERT(env->IsGlobalContext()); - if (env->IsGlobalContext()) { + ASSERT(env->IsNativeContext()); + if (env->IsNativeContext()) { raw_result = env->data(); } else { return Local<Value>(); @@ -1066,7 +1069,6 @@ static i::Handle<i::AccessorInfo> MakeAccessorInfo( v8::PropertyAttribute attributes, v8::Handle<AccessorSignature> signature) { i::Handle<i::AccessorInfo> obj = FACTORY->NewAccessorInfo(); - ASSERT(getter != NULL); SET_FIELD_WRAPPED(obj, set_getter, getter); SET_FIELD_WRAPPED(obj, set_setter, setter); if (data.IsEmpty()) data = v8::Undefined(); @@ -1537,9 +1539,10 @@ Local<Script> Script::New(v8::Handle<String> source, name_obj, line_offset, column_offset, + isolate->global_context(), NULL, pre_data_impl, - Utils::OpenHandle(*script_data), + Utils::OpenHandle(*script_data, true), i::NOT_NATIVES_CODE); has_pending_exception = result.is_null(); EXCEPTION_BAILOUT_CHECK(isolate, Local<Script>()); @@ -3031,6 +3034,17 @@ Local<String> v8::Object::ObjectProtoToString() { } +Local<Value> v8::Object::GetConstructor() { + i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); + ON_BAILOUT(isolate, "v8::Object::GetConstructor()", + return Local<v8::Function>()); + ENTER_V8(isolate); + i::Handle<i::JSObject> self = Utils::OpenHandle(this); + i::Handle<i::Object> constructor(self->GetConstructor()); + return Utils::ToLocal(constructor); +} + + Local<String> v8::Object::GetConstructorName() { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ON_BAILOUT(isolate, "v8::Object::GetConstructorName()", @@ -3223,7 +3237,7 @@ void v8::Object::TurnOnAccessCheck() { i::Deoptimizer::DeoptimizeGlobalObject(*obj); i::Handle<i::Map> new_map = - isolate->factory()->CopyMapDropTransitions(i::Handle<i::Map>(obj->map())); + isolate->factory()->CopyMap(i::Handle<i::Map>(obj->map())); new_map->set_is_access_check_needed(true); obj->set_map(*new_map); } @@ -3258,7 +3272,7 @@ static i::Context* GetCreationContext(i::JSObject* object) { } else { function = i::JSFunction::cast(constructor); } - return function->context()->global_context(); + return function->context()->native_context(); } @@ -3287,13 +3301,15 @@ bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key, v8::Handle<v8::Value> value) { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ON_BAILOUT(isolate, "v8::Object::SetHiddenValue()", return false); + if (value.IsEmpty()) return DeleteHiddenValue(key); ENTER_V8(isolate); i::HandleScope scope(isolate); i::Handle<i::JSObject> self = Utils::OpenHandle(this); i::Handle<i::String> key_obj = Utils::OpenHandle(*key); + i::Handle<i::String> key_symbol = FACTORY->LookupSymbol(key_obj); i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); i::Handle<i::Object> result = - i::JSObject::SetHiddenProperty(self, key_obj, value_obj); + i::JSObject::SetHiddenProperty(self, key_symbol, value_obj); return *result == *self; } @@ -3305,7 +3321,8 @@ v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) { ENTER_V8(isolate); i::Handle<i::JSObject> self = Utils::OpenHandle(this); i::Handle<i::String> key_obj = Utils::OpenHandle(*key); - i::Handle<i::Object> result(self->GetHiddenProperty(*key_obj)); + i::Handle<i::String> key_symbol = FACTORY->LookupSymbol(key_obj); + i::Handle<i::Object> result(self->GetHiddenProperty(*key_symbol)); if (result->IsUndefined()) return v8::Local<v8::Value>(); return Utils::ToLocal(result); } @@ -3318,7 +3335,8 @@ bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) { i::HandleScope scope(isolate); i::Handle<i::JSObject> self = Utils::OpenHandle(this); i::Handle<i::String> key_obj = Utils::OpenHandle(*key); - self->DeleteHiddenProperty(*key_obj); + i::Handle<i::String> key_symbol = FACTORY->LookupSymbol(key_obj); + self->DeleteHiddenProperty(*key_symbol); return true; } @@ -3386,7 +3404,7 @@ void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) { ON_BAILOUT(isolate, "v8::SetElementsToPixelData()", return); ENTER_V8(isolate); i::HandleScope scope(isolate); - if (!ApiCheck(length <= i::ExternalPixelArray::kMaxLength, + if (!ApiCheck(length >= 0 && length <= i::ExternalPixelArray::kMaxLength, "v8::Object::SetIndexedPropertiesToPixelData()", "length exceeds max acceptable value")) { return; @@ -3442,7 +3460,7 @@ void v8::Object::SetIndexedPropertiesToExternalArrayData( ON_BAILOUT(isolate, "v8::SetIndexedPropertiesToExternalArrayData()", return); ENTER_V8(isolate); i::HandleScope scope(isolate); - if (!ApiCheck(length <= i::ExternalArray::kMaxLength, + if (!ApiCheck(length >= 0 && length <= i::ExternalArray::kMaxLength, "v8::Object::SetIndexedPropertiesToExternalArrayData()", "length exceeds max acceptable value")) { return; @@ -3835,6 +3853,9 @@ int String::WriteUtf8(char* buffer, LOG_API(isolate, "String::WriteUtf8"); ENTER_V8(isolate); i::Handle<i::String> str = Utils::OpenHandle(this); + if (options & HINT_MANY_WRITES_EXPECTED) { + FlattenString(str); // Flatten the string for efficiency. + } int string_length = str->length(); if (str->IsAsciiRepresentation()) { int len; @@ -3891,11 +3912,7 @@ int String::WriteUtf8(char* buffer, // Slow case. i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer(); isolate->string_tracker()->RecordWrite(str); - if (options & HINT_MANY_WRITES_EXPECTED) { - // Flatten the string for efficiency. This applies whether we are - // using StringInputBuffer or Get(i) to access the characters. - FlattenString(str); - } + write_input_buffer.Reset(0, *str); int len = str->length(); // Encode the first K - 3 bytes directly into the buffer since we @@ -3937,8 +3954,9 @@ int String::WriteUtf8(char* buffer, c, unibrow::Utf16::kNoPreviousCharacter); if (pos + written <= capacity) { - for (int j = 0; j < written; j++) + for (int j = 0; j < written; j++) { buffer[pos + j] = intermediate[j]; + } pos += written; nchars++; } else { @@ -3951,8 +3969,9 @@ int String::WriteUtf8(char* buffer, } if (nchars_ref != NULL) *nchars_ref = nchars; if (!(options & NO_NULL_TERMINATION) && - (i == len && (capacity == -1 || pos < capacity))) + (i == len && (capacity == -1 || pos < capacity))) { buffer[pos++] = '\0'; + } return pos; } @@ -3965,28 +3984,45 @@ int String::WriteAscii(char* buffer, if (IsDeadCheck(isolate, "v8::String::WriteAscii()")) return 0; LOG_API(isolate, "String::WriteAscii"); ENTER_V8(isolate); - i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer(); ASSERT(start >= 0 && length >= -1); i::Handle<i::String> str = Utils::OpenHandle(this); isolate->string_tracker()->RecordWrite(str); if (options & HINT_MANY_WRITES_EXPECTED) { - // Flatten the string for efficiency. This applies whether we are - // using StringInputBuffer or Get(i) to access the characters. - str->TryFlatten(); + FlattenString(str); // Flatten the string for efficiency. } + + if (str->IsAsciiRepresentation()) { + // WriteToFlat is faster than using the StringInputBuffer. + if (length == -1) length = str->length() + 1; + int len = i::Min(length, str->length() - start); + i::String::WriteToFlat(*str, buffer, start, start + len); + if (!(options & PRESERVE_ASCII_NULL)) { + for (int i = 0; i < len; i++) { + if (buffer[i] == '\0') buffer[i] = ' '; + } + } + if (!(options & NO_NULL_TERMINATION) && length > len) { + buffer[len] = '\0'; + } + return len; + } + + i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer(); int end = length; - if ( (length == -1) || (length > str->length() - start) ) + if ((length == -1) || (length > str->length() - start)) { end = str->length() - start; + } if (end < 0) return 0; write_input_buffer.Reset(start, *str); int i; for (i = 0; i < end; i++) { char c = static_cast<char>(write_input_buffer.GetNext()); - if (c == '\0') c = ' '; + if (c == '\0' && !(options & PRESERVE_ASCII_NULL)) c = ' '; buffer[i] = c; } - if (!(options & NO_NULL_TERMINATION) && (length == -1 || i < length)) + if (!(options & NO_NULL_TERMINATION) && (length == -1 || i < length)) { buffer[i] = '\0'; + } return i; } @@ -4005,7 +4041,7 @@ int String::Write(uint16_t* buffer, if (options & HINT_MANY_WRITES_EXPECTED) { // Flatten the string for efficiency. This applies whether we are // using StringInputBuffer or Get(i) to access the characters. - str->TryFlatten(); + FlattenString(str); } int end = start + length; if ((length == -1) || (length > str->length() - start) ) @@ -4191,8 +4227,9 @@ void v8::Object::SetPointerInInternalField(int index, void* value) { i::Handle<i::Foreign> foreign = isolate->factory()->NewForeign( reinterpret_cast<i::Address>(value), i::TENURED); - if (!foreign.is_null()) - Utils::OpenHandle(this)->SetInternalField(index, *foreign); + if (!foreign.is_null()) { + Utils::OpenHandle(this)->SetInternalField(index, *foreign); + } } ASSERT_EQ(value, GetPointerFromInternalField(index)); } @@ -4221,6 +4258,20 @@ void v8::V8::SetReturnAddressLocationResolver( } +bool v8::V8::SetFunctionEntryHook(FunctionEntryHook entry_hook) { + return i::ProfileEntryHookStub::SetFunctionEntryHook(entry_hook); +} + + +void v8::V8::SetJitCodeEventHandler( + JitCodeEventOptions options, JitCodeEventHandler event_handler) { + i::Isolate* isolate = i::Isolate::Current(); + // Ensure that logging is initialized for our isolate. + isolate->InitializeLoggingAndCounters(); + isolate->logger()->SetCodeEventHandler(options, event_handler); +} + + bool v8::V8::Dispose() { i::Isolate* isolate = i::Isolate::Current(); if (!ApiCheck(isolate != NULL && isolate->IsDefaultIsolate(), @@ -4355,7 +4406,7 @@ Persistent<Context> v8::Context::New( // Create the environment. env = isolate->bootstrapper()->CreateEnvironment( isolate, - Utils::OpenHandle(*global_object), + Utils::OpenHandle(*global_object, true), proxy_template, extensions); @@ -4399,7 +4450,7 @@ void v8::Context::UseDefaultSecurityToken() { } ENTER_V8(isolate); i::Handle<i::Context> env = Utils::OpenHandle(this); - env->set_security_token(env->global()); + env->set_security_token(env->global_object()); } @@ -4444,7 +4495,7 @@ v8::Local<v8::Context> Context::GetCurrent() { if (IsDeadCheck(isolate, "v8::Context::GetCurrent()")) { return Local<Context>(); } - i::Handle<i::Object> current = isolate->global_context(); + i::Handle<i::Object> current = isolate->native_context(); if (current.is_null()) return Local<Context>(); i::Handle<i::Context> context = i::Handle<i::Context>::cast(current); return Utils::ToLocal(context); @@ -4457,7 +4508,7 @@ v8::Local<v8::Context> Context::GetCalling() { return Local<Context>(); } i::Handle<i::Object> calling = - isolate->GetCallingGlobalContext(); + isolate->GetCallingNativeContext(); if (calling.is_null()) return Local<Context>(); i::Handle<i::Context> context = i::Handle<i::Context>::cast(calling); return Utils::ToLocal(context); @@ -4494,9 +4545,9 @@ void Context::ReattachGlobal(Handle<Object> global_object) { i::Object** ctx = reinterpret_cast<i::Object**>(this); i::Handle<i::Context> context = i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx)); - isolate->bootstrapper()->ReattachGlobal( - context, - Utils::OpenHandle(*global_object)); + i::Handle<i::JSGlobalProxy> global_proxy = + i::Handle<i::JSGlobalProxy>::cast(Utils::OpenHandle(*global_object)); + isolate->bootstrapper()->ReattachGlobal(context, global_proxy); } @@ -4750,6 +4801,7 @@ Local<String> v8::String::NewExternal( EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()"); LOG_API(isolate, "String::NewExternal"); ENTER_V8(isolate); + CHECK(resource && resource->data()); i::Handle<i::String> result = NewExternalStringHandle(isolate, resource); isolate->heap()->external_string_table()->AddString(*result); return Utils::ToLocal(result); @@ -4770,6 +4822,7 @@ bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) { if (isolate->heap()->IsInGCPostProcessing()) { return false; } + CHECK(resource && resource->data()); bool result = obj->MakeExternal(resource); if (result && !obj->IsSymbol()) { isolate->heap()->external_string_table()->AddString(*obj); @@ -4784,6 +4837,7 @@ Local<String> v8::String::NewExternal( EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()"); LOG_API(isolate, "String::NewExternal"); ENTER_V8(isolate); + CHECK(resource && resource->data()); i::Handle<i::String> result = NewExternalAsciiStringHandle(isolate, resource); isolate->heap()->external_string_table()->AddString(*result); return Utils::ToLocal(result); @@ -4805,6 +4859,7 @@ bool v8::String::MakeExternal( if (isolate->heap()->IsInGCPostProcessing()) { return false; } + CHECK(resource && resource->data()); bool result = obj->MakeExternal(resource); if (result && !obj->IsSymbol()) { isolate->heap()->external_string_table()->AddString(*obj); @@ -5184,6 +5239,8 @@ void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) { i::Isolate* isolate = EnterIsolateIfNeeded(); if (IsDeadCheck(isolate, "v8::V8::SetCreateHistogramFunction()")) return; isolate->stats_table()->SetCreateHistogramFunction(callback); + isolate->InitializeLoggingAndCounters(); + isolate->counters()->ResetHistograms(); } void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) { @@ -5233,8 +5290,9 @@ void V8::AddImplicitReferences(Persistent<Object> parent, intptr_t V8::AdjustAmountOfExternalAllocatedMemory(intptr_t change_in_bytes) { - i::Isolate* isolate = i::Isolate::Current(); - if (IsDeadCheck(isolate, "v8::V8::AdjustAmountOfExternalAllocatedMemory()")) { + i::Isolate* isolate = i::Isolate::UncheckedCurrent(); + if (isolate == NULL || !isolate->IsInitialized() || + IsDeadCheck(isolate, "v8::V8::AdjustAmountOfExternalAllocatedMemory()")) { return 0; } return isolate->heap()->AdjustAmountOfExternalAllocatedMemory( @@ -5586,7 +5644,8 @@ bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) { foreign = isolate->factory()->NewForeign(FUNCTION_ADDR(EventCallbackWrapper)); } - isolate->debugger()->SetEventListener(foreign, Utils::OpenHandle(*data)); + isolate->debugger()->SetEventListener(foreign, + Utils::OpenHandle(*data, true)); return true; } @@ -5601,7 +5660,8 @@ bool Debug::SetDebugEventListener2(EventCallback2 that, Handle<Value> data) { if (that != NULL) { foreign = isolate->factory()->NewForeign(FUNCTION_ADDR(that)); } - isolate->debugger()->SetEventListener(foreign, Utils::OpenHandle(*data)); + isolate->debugger()->SetEventListener(foreign, + Utils::OpenHandle(*data, true)); return true; } @@ -5612,7 +5672,7 @@ bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that, ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener()", return false); ENTER_V8(isolate); isolate->debugger()->SetEventListener(Utils::OpenHandle(*that), - Utils::OpenHandle(*data)); + Utils::OpenHandle(*data, true)); return true; } @@ -5751,7 +5811,7 @@ Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) { v8::HandleScope scope; i::Debug* isolate_debug = isolate->debug(); isolate_debug->Load(); - i::Handle<i::JSObject> debug(isolate_debug->debug_context()->global()); + i::Handle<i::JSObject> debug(isolate_debug->debug_context()->global_object()); i::Handle<i::String> name = isolate->factory()->LookupAsciiSymbol("MakeMirror"); i::Handle<i::Object> fun_obj = i::GetProperty(debug, name); @@ -5783,6 +5843,7 @@ void Debug::ProcessDebugMessages() { i::Execution::ProcessDebugMessages(true); } + Local<Context> Debug::GetDebugContext() { i::Isolate* isolate = i::Isolate::Current(); EnsureInitializedForIsolate(isolate, "v8::Debug::GetDebugContext()"); @@ -5790,6 +5851,20 @@ Local<Context> Debug::GetDebugContext() { return Utils::ToLocal(i::Isolate::Current()->debugger()->GetDebugContext()); } + +void Debug::SetLiveEditEnabled(bool enable, Isolate* isolate) { + // If no isolate is supplied, use the default isolate. + i::Debugger* debugger; + if (isolate != NULL) { + i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); + debugger = internal_isolate->debugger(); + } else { + debugger = i::Isolate::GetDefaultIsolateDebugger(); + } + debugger->set_live_edit_enabled(enable); +} + + #endif // ENABLE_DEBUGGER_SUPPORT @@ -6374,12 +6449,28 @@ char* HandleScopeImplementer::RestoreThread(char* storage) { void HandleScopeImplementer::IterateThis(ObjectVisitor* v) { +#ifdef DEBUG + bool found_block_before_deferred = false; +#endif // Iterate over all handles in the blocks except for the last. for (int i = blocks()->length() - 2; i >= 0; --i) { Object** block = blocks()->at(i); - v->VisitPointers(block, &block[kHandleBlockSize]); + if (last_handle_before_deferred_block_ != NULL && + (last_handle_before_deferred_block_ < &block[kHandleBlockSize]) && + (last_handle_before_deferred_block_ >= block)) { + v->VisitPointers(block, last_handle_before_deferred_block_); + ASSERT(!found_block_before_deferred); +#ifdef DEBUG + found_block_before_deferred = true; +#endif + } else { + v->VisitPointers(block, &block[kHandleBlockSize]); + } } + ASSERT(last_handle_before_deferred_block_ == NULL || + found_block_before_deferred); + // Iterate over live handles in the last block (if any). if (!blocks()->is_empty()) { v->VisitPointers(blocks()->last(), handle_scope_data_.next); @@ -6407,4 +6498,66 @@ char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) { return storage + ArchiveSpacePerThread(); } + +DeferredHandles* HandleScopeImplementer::Detach(Object** prev_limit) { + DeferredHandles* deferred = + new DeferredHandles(isolate()->handle_scope_data()->next, isolate()); + + while (!blocks_.is_empty()) { + Object** block_start = blocks_.last(); + Object** block_limit = &block_start[kHandleBlockSize]; + // We should not need to check for NoHandleAllocation here. Assert + // this. + ASSERT(prev_limit == block_limit || + !(block_start <= prev_limit && prev_limit <= block_limit)); + if (prev_limit == block_limit) break; + deferred->blocks_.Add(blocks_.last()); + blocks_.RemoveLast(); + } + + // deferred->blocks_ now contains the blocks installed on the + // HandleScope stack since BeginDeferredScope was called, but in + // reverse order. + + ASSERT(prev_limit == NULL || !blocks_.is_empty()); + + ASSERT(!blocks_.is_empty() && prev_limit != NULL); + ASSERT(last_handle_before_deferred_block_ != NULL); + last_handle_before_deferred_block_ = NULL; + return deferred; +} + + +void HandleScopeImplementer::BeginDeferredScope() { + ASSERT(last_handle_before_deferred_block_ == NULL); + last_handle_before_deferred_block_ = isolate()->handle_scope_data()->next; +} + + +DeferredHandles::~DeferredHandles() { + isolate_->UnlinkDeferredHandles(this); + + for (int i = 0; i < blocks_.length(); i++) { +#ifdef DEBUG + HandleScope::ZapRange(blocks_[i], &blocks_[i][kHandleBlockSize]); +#endif + isolate_->handle_scope_implementer()->ReturnBlock(blocks_[i]); + } +} + + +void DeferredHandles::Iterate(ObjectVisitor* v) { + ASSERT(!blocks_.is_empty()); + + ASSERT((first_block_limit_ >= blocks_.first()) && + (first_block_limit_ <= &(blocks_.first())[kHandleBlockSize])); + + v->VisitPointers(blocks_.first(), first_block_limit_); + + for (int i = 1; i < blocks_.length(); i++) { + v->VisitPointers(blocks_[i], &blocks_[i][kHandleBlockSize]); + } +} + + } } // namespace v8::internal |