Author: [email protected]
Date: Wed Mar 18 11:50:35 2009
New Revision: 1539
Modified:
branches/bleeding_edge/src/handles.cc
branches/bleeding_edge/src/handles.h
branches/bleeding_edge/src/stub-cache.cc
Log:
Inline the fast path for handle creation.
Simplify the interceptor IC code by using raw pointers instead of handles.
Review URL: http://codereview.chromium.org/49001
Modified: branches/bleeding_edge/src/handles.cc
==============================================================================
--- branches/bleeding_edge/src/handles.cc (original)
+++ branches/bleeding_edge/src/handles.cc Wed Mar 18 11:50:35 2009
@@ -52,44 +52,39 @@
}
-void** HandleScope::CreateHandle(void* value) {
+void** HandleScope::Extend() {
void** result = current_.next;
- if (result == current_.limit) {
- // Make sure there's at least one scope on the stack and that the
- // top of the scope stack isn't a barrier.
- if (current_.extensions < 0) {
- Utils::ReportApiFailure("v8::HandleScope::CreateHandle()",
- "Cannot create a handle without a
HandleScope");
- return NULL;
- }
- HandleScopeImplementer* impl = HandleScopeImplementer::instance();
- // If there's more room in the last block, we use that. This is used
- // for fast creation of scopes after scope barriers.
- if (!impl->Blocks()->is_empty()) {
- void** limit = &impl->Blocks()->last()[kHandleBlockSize];
- if (current_.limit != limit) {
- current_.limit = limit;
- }
- }
- // If we still haven't found a slot for the handle, we extend the
- // current handle scope by allocating a new handle block.
- if (result == current_.limit) {
- // If there's a spare block, use it for growing the current scope.
- result = impl->GetSpareOrNewBlock();
- // Add the extension to the global list of blocks, but count the
- // extension as part of the current scope.
- impl->Blocks()->Add(result);
- current_.extensions++;
- current_.limit = &result[kHandleBlockSize];
+ ASSERT(result == current_.limit);
+ // Make sure there's at least one scope on the stack and that the
+ // top of the scope stack isn't a barrier.
+ if (current_.extensions < 0) {
+ Utils::ReportApiFailure("v8::HandleScope::CreateHandle()",
+ "Cannot create a handle without a
HandleScope");
+ return NULL;
+ }
+ HandleScopeImplementer* impl = HandleScopeImplementer::instance();
+ // If there's more room in the last block, we use that. This is used
+ // for fast creation of scopes after scope barriers.
+ if (!impl->Blocks()->is_empty()) {
+ void** limit = &impl->Blocks()->last()[kHandleBlockSize];
+ if (current_.limit != limit) {
+ current_.limit = limit;
}
}
+
+ // If we still haven't found a slot for the handle, we extend the
+ // current handle scope by allocating a new handle block.
+ if (result == current_.limit) {
+ // If there's a spare block, use it for growing the current scope.
+ result = impl->GetSpareOrNewBlock();
+ // Add the extension to the global list of blocks, but count the
+ // extension as part of the current scope.
+ impl->Blocks()->Add(result);
+ current_.extensions++;
+ current_.limit = &result[kHandleBlockSize];
+ }
- // Update the current next field, set the value in the created
- // handle, and return the result.
- ASSERT(result < current_.limit);
- current_.next = result + 1;
- *result = value;
return result;
}
Modified: branches/bleeding_edge/src/handles.h
==============================================================================
--- branches/bleeding_edge/src/handles.h (original)
+++ branches/bleeding_edge/src/handles.h Wed Mar 18 11:50:35 2009
@@ -118,7 +118,16 @@
static int NumberOfHandles();
// Creates a new handle with the given value.
- static void** CreateHandle(void* value);
+ static inline void** CreateHandle(void* value) {
+ void** result = current_.next;
+ if (result == current_.limit) result = Extend();
+ // Update the current next field, set the value in the created
+ // handle, and return the result.
+ ASSERT(result < current_.limit);
+ current_.next = result + 1;
+ *result = value;
+ return result;
+ }
private:
// Prevent heap allocation or illegal handle scopes.
@@ -149,6 +158,9 @@
ZapRange(current_.next, current_.limit);
#endif
}
+
+ // Extend the handle scope making room for more handles.
+ static void** Extend();
// Deallocates any extensions used by the current scope.
static void DeleteExtensions();
Modified: branches/bleeding_edge/src/stub-cache.cc
==============================================================================
--- branches/bleeding_edge/src/stub-cache.cc (original)
+++ branches/bleeding_edge/src/stub-cache.cc Wed Mar 18 11:50:35 2009
@@ -656,9 +656,8 @@
Object* LoadCallbackProperty(Arguments args) {
Handle<JSObject> recv = args.at<JSObject>(0);
AccessorInfo* callback = AccessorInfo::cast(args[1]);
- v8::AccessorGetter fun =
- FUNCTION_CAST<v8::AccessorGetter>(
- v8::ToCData<Address>(callback->getter()));
+ 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>(2);
Handle<JSObject> holder = args.at<JSObject>(3);
@@ -669,10 +668,9 @@
// 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.
- v8::AccessorInfo info(
- v8::Utils::ToLocal(recv),
- v8::Utils::ToLocal(data),
- v8::Utils::ToLocal(holder));
+ v8::AccessorInfo info(v8::Utils::ToLocal(recv),
+ v8::Utils::ToLocal(data),
+ v8::Utils::ToLocal(holder));
v8::Handle<v8::Value> result;
{
// Leaving JavaScript.
@@ -680,30 +678,25 @@
result = fun(v8::Utils::ToLocal(name), info);
}
RETURN_IF_SCHEDULED_EXCEPTION();
- if (result.IsEmpty()) {
- return Heap::undefined_value();
- } else {
- return *v8::Utils::OpenHandle(*result);
- }
+ if (result.IsEmpty()) return Heap::undefined_value();
+ return *v8::Utils::OpenHandle(*result);
}
Object* StoreCallbackProperty(Arguments args) {
Handle<JSObject> recv = args.at<JSObject>(0);
AccessorInfo* callback = AccessorInfo::cast(args[1]);
- v8::AccessorSetter fun =
- FUNCTION_CAST<v8::AccessorSetter>(
- v8::ToCData<Address>(callback->setter()));
+ Address setter_address = v8::ToCData<Address>(callback->setter());
+ v8::AccessorSetter fun =
FUNCTION_CAST<v8::AccessorSetter>(setter_address);
ASSERT(fun != NULL);
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));
+ v8::AccessorInfo info(v8::Utils::ToLocal(recv),
+ v8::Utils::ToLocal(data),
+ v8::Utils::ToLocal(recv));
{
// Leaving JavaScript.
VMState state(OTHER);
@@ -715,28 +708,17 @@
Object* LoadInterceptorProperty(Arguments args) {
- HandleScope scope;
- Handle<JSObject> recv = args.at<JSObject>(0);
- Handle<JSObject> holder = args.at<JSObject>(1);
- Handle<String> name = args.at<String>(2);
+ JSObject* recv = JSObject::cast(args[0]);
+ JSObject* holder = JSObject::cast(args[1]);
+ String* name = String::cast(args[2]);
ASSERT(holder->HasNamedInterceptor());
PropertyAttributes attr = NONE;
- Handle<Object> result = GetPropertyWithInterceptor(recv, holder, name,
&attr);
+ Object* result = holder->GetPropertyWithInterceptor(recv, name, &attr);
- // GetPropertyWithInterceptor already converts a scheduled exception
- // to a pending one if any. Don't use RETURN_IF_SCHEDULED_EXCEPTION()
here.
-
- // Make sure to propagate exceptions.
- if (result.is_null()) {
- // Failure::Exception is converted to a null handle in the
- // handle-based methods such as SetProperty. We therefore need
- // to convert null handles back to exceptions.
- ASSERT(Top::has_pending_exception());
- return Failure::Exception();
- }
+ if (result->IsFailure()) return result;
// If the property is present, return it.
- if (attr != ABSENT) return *result;
+ if (attr != ABSENT) return result;
// If the top frame is an internal frame, this is really a call
// IC. In this case, we simply return the undefined result which
@@ -744,43 +726,38 @@
// function.
StackFrameIterator it;
it.Advance(); // skip exit frame
- if (it.frame()->is_internal()) return *result;
+ if (it.frame()->is_internal()) return result;
// If the load is non-contextual, just return the undefined result.
// Note that both keyed and non-keyed loads may end up here, so we
// can't use either LoadIC or KeyedLoadIC constructors.
IC ic(IC::NO_EXTRA_FRAME);
ASSERT(ic.target()->is_load_stub() || ic.target()->is_keyed_load_stub());
- if (!ic.is_contextual()) return *result;
+ if (!ic.is_contextual()) return result;
// Throw a reference error.
- Handle<Object> error =
- Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
- return Top::Throw(*error);
+ {
+ HandleScope scope;
+ // We cannot use the raw name pointer here since getting the
+ // property might cause a GC. However, we can get the name from
+ // the stack using the arguments object.
+ Handle<String> name_handle = args.at<String>(2);
+ Handle<Object> error =
+ Factory::NewReferenceError("not_defined",
+ HandleVector(&name_handle, 1));
+ return Top::Throw(*error);
+ }
}
Object* StoreInterceptorProperty(Arguments args) {
- HandleScope scope;
- Handle<JSObject> recv = args.at<JSObject>(0);
- Handle<String> name = args.at<String>(1);
- Handle<Object> value = args.at<Object>(2);
+ JSObject* recv = JSObject::cast(args[0]);
+ String* name = String::cast(args[1]);
+ Object* value = args[2];
ASSERT(recv->HasNamedInterceptor());
PropertyAttributes attr = NONE;
- Handle<Object> result = SetPropertyWithInterceptor(recv, name, value,
attr);
-
- // SetPropertyWithInterceptor already converts a scheduled exception
- // to a pending one if any. Don't use RETURN_IF_SCHEDULED_EXCEPTION()
here.
-
- // Make sure to propagate exceptions.
- if (result.is_null()) {
- // Failure::Exception is converted to a null handle in the
- // handle-based methods such as SetProperty. We therefore need
- // to convert null handles back to exceptions.
- ASSERT(Top::has_pending_exception());
- return Failure::Exception();
- }
- return *result;
+ Object* result = recv->SetPropertyWithInterceptor(name, value, attr);
+ return result;
}
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---