Revision: 2995 Author: [email protected] Date: Wed Sep 30 05:25:46 2009 Log: Changed structure of accessor arguments passing to allow accessor callbacks to be called directly from native code.
Review URL: http://codereview.chromium.org/242050 http://code.google.com/p/v8/source/detail?r=2995 Modified: /branches/bleeding_edge/include/v8.h /branches/bleeding_edge/src/api.cc /branches/bleeding_edge/src/arguments.h /branches/bleeding_edge/src/handles.cc /branches/bleeding_edge/src/heap.cc /branches/bleeding_edge/src/objects.cc /branches/bleeding_edge/src/objects.h /branches/bleeding_edge/src/stub-cache.cc /branches/bleeding_edge/src/v8threads.cc ======================================= --- /branches/bleeding_edge/include/v8.h Wed Sep 30 01:27:58 2009 +++ /branches/bleeding_edge/include/v8.h Wed Sep 30 05:25:46 2009 @@ -130,6 +130,7 @@ namespace internal { class Object; +class Arguments; } @@ -1408,17 +1409,13 @@ */ class V8EXPORT AccessorInfo { public: - inline AccessorInfo(Local<Object> self, - Local<Value> data, - Local<Object> holder) - : self_(self), data_(data), holder_(holder) { } + inline AccessorInfo(internal::Object** args) + : args_(args) { } inline Local<Value> Data() const; inline Local<Object> This() const; inline Local<Object> Holder() const; private: - Local<Object> self_; - Local<Value> data_; - Local<Object> holder_; + internal::Object** args_; }; @@ -2871,21 +2868,6 @@ int Arguments::Length() const { return length_; } - - -Local<Value> AccessorInfo::Data() const { - return data_; -} - - -Local<Object> AccessorInfo::This() const { - return self_; -} - - -Local<Object> AccessorInfo::Holder() const { - return holder_; -} template <class T> @@ -3083,6 +3065,21 @@ #endif return static_cast<External*>(value); } + + +Local<Value> AccessorInfo::Data() const { + return Local<Value>(reinterpret_cast<Value*>(&args_[-3])); +} + + +Local<Object> AccessorInfo::This() const { + return Local<Object>(reinterpret_cast<Object*>(&args_[0])); +} + + +Local<Object> AccessorInfo::Holder() const { + return Local<Object>(reinterpret_cast<Object*>(&args_[-1])); +} /** ======================================= --- /branches/bleeding_edge/src/api.cc Mon Sep 28 07:32:48 2009 +++ /branches/bleeding_edge/src/api.cc Wed Sep 30 05:25:46 2009 @@ -28,6 +28,7 @@ #include "v8.h" #include "api.h" +#include "arguments.h" #include "bootstrapper.h" #include "compiler.h" #include "debug.h" ======================================= --- /branches/bleeding_edge/src/arguments.h Mon May 25 03:05:56 2009 +++ /branches/bleeding_edge/src/arguments.h Wed Sep 30 05:25:46 2009 @@ -45,6 +45,9 @@ class Arguments BASE_EMBEDDED { public: + Arguments(int length, Object** arguments) + : length_(length), arguments_(arguments) { } + Object*& operator[] (int index) { ASSERT(0 <= index && index < length_); return arguments_[-index]; @@ -60,12 +63,35 @@ // Get the total number of arguments including the receiver. int length() const { return length_; } + + Object** arguments() { return arguments_; } private: int length_; Object** arguments_; }; + +// Cursom arguments replicate a small segment of stack that can be +// accessed through an Arguments object the same way the actual stack +// can. +class CustomArguments : public Relocatable { +public: + inline CustomArguments(Object *data, + JSObject *self, + JSObject *holder) { + values_[3] = self; + values_[2] = holder; + values_[1] = Smi::FromInt(0); + values_[0] = data; + } + void IterateInstance(ObjectVisitor* v); + Object** end() { return values_ + 3; } +private: + Object* values_[4]; +}; + + } } // namespace v8::internal #endif // V8_ARGUMENTS_H_ ======================================= --- /branches/bleeding_edge/src/handles.cc Mon Sep 28 05:25:21 2009 +++ /branches/bleeding_edge/src/handles.cc Wed Sep 30 05:25:46 2009 @@ -29,6 +29,7 @@ #include "accessors.h" #include "api.h" +#include "arguments.h" #include "bootstrapper.h" #include "compiler.h" #include "debug.h" @@ -477,17 +478,19 @@ return line != -1 ? line + script->line_offset()->value() : line; } + + +void CustomArguments::IterateInstance(ObjectVisitor* v) { + v->VisitPointers(values_, values_ + 4); +} // Compute the property keys from the interceptor. v8::Handle<v8::Array> GetKeysForNamedInterceptor(Handle<JSObject> receiver, Handle<JSObject> object) { Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor()); - Handle<Object> data(interceptor->data()); - v8::AccessorInfo info( - v8::Utils::ToLocal(receiver), - v8::Utils::ToLocal(data), - v8::Utils::ToLocal(object)); + CustomArguments args(interceptor->data(), *receiver, *object); + v8::AccessorInfo info(args.end()); v8::Handle<v8::Array> result; if (!interceptor->enumerator()->IsUndefined()) { v8::NamedPropertyEnumerator enum_fun = @@ -507,11 +510,8 @@ v8::Handle<v8::Array> GetKeysForIndexedInterceptor(Handle<JSObject> receiver, Handle<JSObject> object) { Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor()); - Handle<Object> data(interceptor->data()); - v8::AccessorInfo info( - v8::Utils::ToLocal(receiver), - v8::Utils::ToLocal(data), - v8::Utils::ToLocal(object)); + CustomArguments args(interceptor->data(), *receiver, *object); + v8::AccessorInfo info(args.end()); v8::Handle<v8::Array> result; if (!interceptor->enumerator()->IsUndefined()) { v8::IndexedPropertyEnumerator enum_fun = ======================================= --- /branches/bleeding_edge/src/heap.cc Mon Sep 21 03:35:47 2009 +++ /branches/bleeding_edge/src/heap.cc Wed Sep 30 05:25:46 2009 @@ -497,8 +497,8 @@ DisableAssertNoAllocation allow_allocation; GlobalHandles::PostGarbageCollectionProcessing(); } - // Update flat string readers. - FlatStringReader::PostGarbageCollectionProcessing(); + // Update relocatables. + Relocatable::PostGarbageCollectionProcessing(); } @@ -3088,6 +3088,8 @@ SYNCHRONIZE_TAG("bootstrapper"); Top::Iterate(v); SYNCHRONIZE_TAG("top"); + Relocatable::Iterate(v); + SYNCHRONIZE_TAG("relocatable"); #ifdef ENABLE_DEBUGGER_SUPPORT Debug::Iterate(v); ======================================= --- /branches/bleeding_edge/src/objects.cc Mon Sep 21 03:35:47 2009 +++ /branches/bleeding_edge/src/objects.cc Wed Sep 30 05:25:46 2009 @@ -28,6 +28,7 @@ #include "v8.h" #include "api.h" +#include "arguments.h" #include "bootstrapper.h" #include "debug.h" #include "execution.h" @@ -158,14 +159,12 @@ Object* fun_obj = data->getter(); v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj); HandleScope scope; - Handle<JSObject> self(JSObject::cast(receiver)); - Handle<JSObject> holder_handle(JSObject::cast(holder)); + JSObject* self = JSObject::cast(receiver); + JSObject* holder_handle = JSObject::cast(holder); Handle<String> key(name); - Handle<Object> fun_data(data->data()); - LOG(ApiNamedPropertyAccess("load", *self, name)); - v8::AccessorInfo info(v8::Utils::ToLocal(self), - v8::Utils::ToLocal(fun_data), - v8::Utils::ToLocal(holder_handle)); + LOG(ApiNamedPropertyAccess("load", self, name)); + CustomArguments args(data->data(), self, holder_handle); + v8::AccessorInfo info(args.end()); v8::Handle<v8::Value> result; { // Leaving JavaScript. @@ -1538,11 +1537,9 @@ Handle<Object> value_handle(value); Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); if (!interceptor->setter()->IsUndefined()) { - Handle<Object> data_handle(interceptor->data()); LOG(ApiNamedPropertyAccess("interceptor-named-set", this, name)); - v8::AccessorInfo info(v8::Utils::ToLocal(this_handle), - v8::Utils::ToLocal(data_handle), - v8::Utils::ToLocal(this_handle)); + CustomArguments args(interceptor->data(), this, this); + v8::AccessorInfo info(args.end()); v8::NamedPropertySetter setter = v8::ToCData<v8::NamedPropertySetter>(interceptor->setter()); v8::Handle<v8::Value> result; @@ -1605,14 +1602,10 @@ Object* call_obj = data->setter(); v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj); if (call_fun == NULL) return value; - Handle<JSObject> self(this); - Handle<JSObject> holder_handle(JSObject::cast(holder)); Handle<String> key(name); - Handle<Object> fun_data(data->data()); LOG(ApiNamedPropertyAccess("store", this, name)); - v8::AccessorInfo info(v8::Utils::ToLocal(self), - v8::Utils::ToLocal(fun_data), - v8::Utils::ToLocal(holder_handle)); + CustomArguments args(data->data(), this, JSObject::cast(holder)); + v8::AccessorInfo info(args.end()); { // Leaving JavaScript. VMState state(EXTERNAL); @@ -2036,10 +2029,8 @@ Handle<JSObject> receiver_handle(receiver); Handle<JSObject> holder_handle(this); Handle<String> name_handle(name); - Handle<Object> data_handle(interceptor->data()); - v8::AccessorInfo info(v8::Utils::ToLocal(receiver_handle), - v8::Utils::ToLocal(data_handle), - v8::Utils::ToLocal(holder_handle)); + CustomArguments args(interceptor->data(), receiver, this); + v8::AccessorInfo info(args.end()); if (!interceptor->query()->IsUndefined()) { v8::NamedPropertyQuery query = v8::ToCData<v8::NamedPropertyQuery>(interceptor->query()); @@ -2307,11 +2298,9 @@ if (!interceptor->deleter()->IsUndefined()) { v8::NamedPropertyDeleter deleter = v8::ToCData<v8::NamedPropertyDeleter>(interceptor->deleter()); - Handle<Object> data_handle(interceptor->data()); LOG(ApiNamedPropertyAccess("interceptor-named-delete", *this_handle, name)); - v8::AccessorInfo info(v8::Utils::ToLocal(this_handle), - v8::Utils::ToLocal(data_handle), - v8::Utils::ToLocal(this_handle)); + CustomArguments args(interceptor->data(), this, this); + v8::AccessorInfo info(args.end()); v8::Handle<v8::Boolean> result; { // Leaving JavaScript. @@ -2370,11 +2359,9 @@ v8::IndexedPropertyDeleter deleter = v8::ToCData<v8::IndexedPropertyDeleter>(interceptor->deleter()); Handle<JSObject> this_handle(this); - Handle<Object> data_handle(interceptor->data()); LOG(ApiIndexedPropertyAccess("interceptor-indexed-delete", this, index)); - v8::AccessorInfo info(v8::Utils::ToLocal(this_handle), - v8::Utils::ToLocal(data_handle), - v8::Utils::ToLocal(this_handle)); + CustomArguments args(interceptor->data(), this, this); + v8::AccessorInfo info(args.end()); v8::Handle<v8::Boolean> result; { // Leaving JavaScript. @@ -3971,35 +3958,75 @@ } -FlatStringReader* FlatStringReader::top_ = NULL; +Relocatable* Relocatable::top_ = NULL; + + +void Relocatable::PostGarbageCollectionProcessing() { + Relocatable* current = top_; + while (current != NULL) { + current->PostGarbageCollection(); + current = current->prev_; + } +} + + +// Reserve space for statics needing saving and restoring. +int Relocatable::ArchiveSpacePerThread() { + return sizeof(top_); +} + + +// Archive statics that are thread local. +char* Relocatable::ArchiveState(char* to) { + *reinterpret_cast<Relocatable**>(to) = top_; + top_ = NULL; + return to + ArchiveSpacePerThread(); +} + + +// Restore statics that are thread local. +char* Relocatable::RestoreState(char* from) { + top_ = *reinterpret_cast<Relocatable**>(from); + return from + ArchiveSpacePerThread(); +} + + +char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) { + Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage); + Iterate(v, top); + return thread_storage + ArchiveSpacePerThread(); +} + + +void Relocatable::Iterate(ObjectVisitor* v) { + Iterate(v, top_); +} + + +void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) { + Relocatable* current = top; + while (current != NULL) { + current->IterateInstance(v); + current = current->prev_; + } +} FlatStringReader::FlatStringReader(Handle<String> str) : str_(str.location()), - length_(str->length()), - prev_(top_) { - top_ = this; - RefreshState(); + length_(str->length()) { + PostGarbageCollection(); } FlatStringReader::FlatStringReader(Vector<const char> input) - : str_(NULL), + : str_(0), is_ascii_(true), length_(input.length()), - start_(input.start()), - prev_(top_) { - top_ = this; -} + start_(input.start()) { } -FlatStringReader::~FlatStringReader() { - ASSERT_EQ(top_, this); - top_ = prev_; -} - - -void FlatStringReader::RefreshState() { +void FlatStringReader::PostGarbageCollection() { if (str_ == NULL) return; Handle<String> str(str_); ASSERT(str->IsFlat()); @@ -4010,15 +4037,6 @@ start_ = str->ToUC16Vector().start(); } } - - -void FlatStringReader::PostGarbageCollectionProcessing() { - FlatStringReader* current = top_; - while (current != NULL) { - current->RefreshState(); - current = current->prev_; - } -} void StringInputBuffer::Seek(unsigned pos) { @@ -5429,10 +5447,8 @@ Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); Handle<JSObject> receiver_handle(receiver); Handle<JSObject> holder_handle(this); - Handle<Object> data_handle(interceptor->data()); - v8::AccessorInfo info(v8::Utils::ToLocal(receiver_handle), - v8::Utils::ToLocal(data_handle), - v8::Utils::ToLocal(holder_handle)); + CustomArguments args(interceptor->data(), receiver, this); + v8::AccessorInfo info(args.end()); if (!interceptor->query()->IsUndefined()) { v8::IndexedPropertyQuery query = v8::ToCData<v8::IndexedPropertyQuery>(interceptor->query()); @@ -5564,11 +5580,9 @@ if (!interceptor->setter()->IsUndefined()) { v8::IndexedPropertySetter setter = v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter()); - Handle<Object> data_handle(interceptor->data()); LOG(ApiIndexedPropertyAccess("interceptor-indexed-set", this, index)); - v8::AccessorInfo info(v8::Utils::ToLocal(this_handle), - v8::Utils::ToLocal(data_handle), - v8::Utils::ToLocal(this_handle)); + CustomArguments args(interceptor->data(), this, this); + v8::AccessorInfo info(args.end()); v8::Handle<v8::Value> result; { // Leaving JavaScript. @@ -5836,13 +5850,11 @@ Handle<JSObject> holder_handle(this); if (!interceptor->getter()->IsUndefined()) { - Handle<Object> data_handle(interceptor->data()); v8::IndexedPropertyGetter getter = v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter()); LOG(ApiIndexedPropertyAccess("interceptor-indexed-get", this, index)); - v8::AccessorInfo info(v8::Utils::ToLocal(this_handle), - v8::Utils::ToLocal(data_handle), - v8::Utils::ToLocal(holder_handle)); + CustomArguments args(interceptor->data(), receiver, this); + v8::AccessorInfo info(args.end()); v8::Handle<v8::Value> result; { // Leaving JavaScript. @@ -6074,15 +6086,13 @@ Handle<JSObject> receiver_handle(receiver); Handle<JSObject> holder_handle(this); Handle<String> name_handle(name); - Handle<Object> data_handle(interceptor->data()); if (!interceptor->getter()->IsUndefined()) { v8::NamedPropertyGetter getter = v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter()); LOG(ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name)); - v8::AccessorInfo info(v8::Utils::ToLocal(receiver_handle), - v8::Utils::ToLocal(data_handle), - v8::Utils::ToLocal(holder_handle)); + CustomArguments args(interceptor->data(), receiver, this); + v8::AccessorInfo info(args.end()); v8::Handle<v8::Value> result; { // Leaving JavaScript. ======================================= --- /branches/bleeding_edge/src/objects.h Tue Sep 29 02:21:19 2009 +++ /branches/bleeding_edge/src/objects.h Wed Sep 30 05:25:46 2009 @@ -4219,25 +4219,44 @@ }; +// Utility superclass for stack-allocated objects that must be updated +// on gc. It provides two ways for the gc to update instances, either +// iterating or updating after gc. +class Relocatable BASE_EMBEDDED { +public: + inline Relocatable() : prev_(top_) { top_ = this; } + virtual ~Relocatable() { ASSERT_EQ(top_, this); top_ = prev_; } + virtual void IterateInstance(ObjectVisitor* v) { } + virtual void PostGarbageCollection() { } + + static void PostGarbageCollectionProcessing(); + static int ArchiveSpacePerThread(); + static char* ArchiveState(char* to); + static char* RestoreState(char* from); + static void Iterate(ObjectVisitor* v); + static void Iterate(ObjectVisitor* v, Relocatable* top); + static char* Iterate(ObjectVisitor* v, char* t); +private: + static Relocatable* top_; + Relocatable* prev_; +}; + + // A flat string reader provides random access to the contents of a // string independent of the character width of the string. The handle // must be valid as long as the reader is being used. -class FlatStringReader BASE_EMBEDDED { +class FlatStringReader : public Relocatable { public: explicit FlatStringReader(Handle<String> str); explicit FlatStringReader(Vector<const char> input); - ~FlatStringReader(); - void RefreshState(); + void PostGarbageCollection(); inline uc32 Get(int index); int length() { return length_; } - static void PostGarbageCollectionProcessing(); private: String** str_; bool is_ascii_; int length_; const void* start_; - FlatStringReader* prev_; - static FlatStringReader* top_; }; ======================================= --- /branches/bleeding_edge/src/stub-cache.cc Tue Sep 1 23:55:49 2009 +++ /branches/bleeding_edge/src/stub-cache.cc Wed Sep 30 05:25:46 2009 @@ -735,28 +735,17 @@ Object* LoadCallbackProperty(Arguments args) { - Handle<JSObject> recv = args.at<JSObject>(0); - Handle<JSObject> holder = args.at<JSObject>(1); AccessorInfo* callback = AccessorInfo::cast(args[2]); - Handle<Object> data = args.at<Object>(3); Address getter_address = v8::ToCData<Address>(callback->getter()); v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address); ASSERT(fun != NULL); - Handle<String> name = args.at<String>(4); - // NOTE: If we can align the structure of an AccessorInfo with the - // locations of the arguments to this function maybe we don't have - // to explicitly create the structure but can just pass a pointer - // into the stack. - LOG(ApiNamedPropertyAccess("load", *recv, *name)); - v8::AccessorInfo info(v8::Utils::ToLocal(recv), - v8::Utils::ToLocal(data), - v8::Utils::ToLocal(holder)); + v8::AccessorInfo info(args.arguments()); HandleScope scope; v8::Handle<v8::Value> result; { // Leaving JavaScript. VMState state(EXTERNAL); - result = fun(v8::Utils::ToLocal(name), info); + result = fun(v8::Utils::ToLocal(args.at<String>(4)), info); } RETURN_IF_SCHEDULED_EXCEPTION(); if (result.IsEmpty()) return Heap::undefined_value(); @@ -765,7 +754,7 @@ Object* StoreCallbackProperty(Arguments args) { - Handle<JSObject> recv = args.at<JSObject>(0); + JSObject* recv = JSObject::cast(args[0]); AccessorInfo* callback = AccessorInfo::cast(args[1]); Address setter_address = v8::ToCData<Address>(callback->setter()); v8::AccessorSetter fun = FUNCTION_CAST<v8::AccessorSetter>(setter_address); @@ -773,11 +762,9 @@ Handle<String> name = args.at<String>(2); Handle<Object> value = args.at<Object>(3); HandleScope scope; - Handle<Object> data(callback->data()); - LOG(ApiNamedPropertyAccess("store", *recv, *name)); - v8::AccessorInfo info(v8::Utils::ToLocal(recv), - v8::Utils::ToLocal(data), - v8::Utils::ToLocal(recv)); + LOG(ApiNamedPropertyAccess("store", recv, *name)); + CustomArguments custom_args(callback->data(), recv, recv); + v8::AccessorInfo info(custom_args.end()); { // Leaving JavaScript. VMState state(EXTERNAL); @@ -795,11 +782,11 @@ * provide any value for the given name. */ Object* LoadPropertyWithInterceptorOnly(Arguments args) { - Handle<JSObject> receiver_handle = args.at<JSObject>(0); - Handle<JSObject> holder_handle = args.at<JSObject>(1); + JSObject* receiver_handle = JSObject::cast(args[0]); + JSObject* holder_handle = JSObject::cast(args[1]); Handle<String> name_handle = args.at<String>(2); Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(3); - Handle<Object> data_handle = args.at<Object>(4); + Object* data_handle = args[4]; Address getter_address = v8::ToCData<Address>(interceptor_info->getter()); v8::NamedPropertyGetter getter = @@ -808,9 +795,8 @@ { // Use the interceptor getter. - v8::AccessorInfo info(v8::Utils::ToLocal(receiver_handle), - v8::Utils::ToLocal(data_handle), - v8::Utils::ToLocal(holder_handle)); + CustomArguments args(data_handle, receiver_handle, holder_handle); + v8::AccessorInfo info(args.end()); HandleScope scope; v8::Handle<v8::Value> r; { @@ -861,9 +847,8 @@ { // Use the interceptor getter. - v8::AccessorInfo info(v8::Utils::ToLocal(receiver_handle), - v8::Utils::ToLocal(data_handle), - v8::Utils::ToLocal(holder_handle)); + CustomArguments args(*data_handle, *receiver_handle, *holder_handle); + v8::AccessorInfo info(args.end()); HandleScope scope; v8::Handle<v8::Value> r; { ======================================= --- /branches/bleeding_edge/src/v8threads.cc Mon Sep 28 05:25:21 2009 +++ /branches/bleeding_edge/src/v8threads.cc Wed Sep 30 05:25:46 2009 @@ -146,6 +146,7 @@ char* from = state->data(); from = HandleScopeImplementer::RestoreThread(from); from = Top::RestoreThread(from); + from = Relocatable::RestoreState(from); #ifdef ENABLE_DEBUGGER_SUPPORT from = Debug::RestoreDebug(from); #endif @@ -185,7 +186,8 @@ #endif StackGuard::ArchiveSpacePerThread() + RegExpStack::ArchiveSpacePerThread() + - Bootstrapper::ArchiveSpacePerThread(); + Bootstrapper::ArchiveSpacePerThread() + + Relocatable::ArchiveSpacePerThread(); } @@ -275,6 +277,7 @@ // in ThreadManager::Iterate(ObjectVisitor*). to = HandleScopeImplementer::ArchiveThread(to); to = Top::ArchiveThread(to); + to = Relocatable::ArchiveState(to); #ifdef ENABLE_DEBUGGER_SUPPORT to = Debug::ArchiveDebug(to); #endif @@ -311,6 +314,7 @@ char* data = state->data(); data = HandleScopeImplementer::Iterate(v, data); data = Top::Iterate(v, data); + data = Relocatable::Iterate(v, data); } } --~--~---------~--~----~------------~-------~--~----~ v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev -~----------~----~----~----~------~----~------~--~---
