namespace internal {
class Object;
+class Arguments;
}
*/
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_;
};
}
-Local<Value> AccessorInfo::Data() const {
- return data_;
-}
-
-
-Local<Object> AccessorInfo::This() const {
- return self_;
-}
-
-
-Local<Object> AccessorInfo::Holder() const {
- return holder_;
-}
-
-
template <class T>
Local<T> HandleScope::Close(Handle<T> value) {
internal::Object** before = reinterpret_cast<internal::Object**>(*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]));
+}
+
+
/**
* \example shell.cc
* A simple shell that takes a list of expressions on the
#include "v8.h"
#include "api.h"
+#include "arguments.h"
#include "bootstrapper.h"
#include "compiler.h"
#include "debug.h"
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];
// 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_
#include "accessors.h"
#include "api.h"
+#include "arguments.h"
#include "bootstrapper.h"
#include "compiler.h"
#include "debug.h"
}
+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 =
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 =
DisableAssertNoAllocation allow_allocation;
GlobalHandles::PostGarbageCollectionProcessing();
}
- // Update flat string readers.
- FlatStringReader::PostGarbageCollectionProcessing();
+ // Update relocatables.
+ Relocatable::PostGarbageCollectionProcessing();
}
SYNCHRONIZE_TAG("bootstrapper");
Top::Iterate(v);
SYNCHRONIZE_TAG("top");
+ Relocatable::Iterate(v);
+ SYNCHRONIZE_TAG("relocatable");
#ifdef ENABLE_DEBUGGER_SUPPORT
Debug::Iterate(v);
#include "v8.h"
#include "api.h"
+#include "arguments.h"
#include "bootstrapper.h"
#include "debug.h"
#include "execution.h"
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.
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;
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);
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());
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.
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.
}
-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());
}
-void FlatStringReader::PostGarbageCollectionProcessing() {
- FlatStringReader* current = top_;
- while (current != NULL) {
- current->RefreshState();
- current = current->prev_;
- }
-}
-
-
void StringInputBuffer::Seek(unsigned pos) {
Reset(pos, input_);
}
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());
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.
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.
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.
};
+// 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_;
};
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();
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);
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);
* 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 =
{
// 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;
{
{
// 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;
{
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
#endif
StackGuard::ArchiveSpacePerThread() +
RegExpStack::ArchiveSpacePerThread() +
- Bootstrapper::ArchiveSpacePerThread();
+ Bootstrapper::ArchiveSpacePerThread() +
+ Relocatable::ArchiveSpacePerThread();
}
// 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
char* data = state->data();
data = HandleScopeImplementer::Iterate(v, data);
data = Top::Iterate(v, data);
+ data = Relocatable::Iterate(v, data);
}
}