Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Commit

Permalink
node, async-wrap: remove MakeDomainCallback
Browse files Browse the repository at this point in the history
C++ won't deoptimize like JS if specific conditional branches are
sporadically met in the future. Combined with the amount of code
duplication removal and simplified maintenance complexity, it makes more
sense to merge MakeCallback and MakeDomainCallback.

Additionally, type casting in V8 before verifying what that type is will
cause V8 to abort in debug mode if that type isn't what was expected.
Fix this by first checking the v8::Value before casting.

PR-URL: #8110
Signed-off-by: Trevor Norris <trev.norris@gmail.com>
Reviewed-by: Fedor Indutny <fedor@indutny.com>
Reviewed-by: Alexis Campailla <alexis@janeasystems.com>
Reviewed-by: Julien Gilli <julien.gilli@joyent.com>
  • Loading branch information
trevnorris committed Dec 5, 2014
1 parent 2593c14 commit 42df679
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 187 deletions.
14 changes: 5 additions & 9 deletions src/async-wrap-inl.h
Expand Up @@ -31,7 +31,6 @@
#include "util-inl.h"

#include "v8.h"
#include <assert.h>

namespace node {

Expand All @@ -46,6 +45,7 @@ inline AsyncWrap::AsyncWrap(Environment* env,
inline AsyncWrap::~AsyncWrap() {
}


inline uint32_t AsyncWrap::provider_type() const {
return provider_type_;
}
Expand All @@ -56,10 +56,8 @@ inline v8::Handle<v8::Value> AsyncWrap::MakeCallback(
int argc,
v8::Handle<v8::Value>* argv) {
v8::Local<v8::Value> cb_v = object()->Get(symbol);
v8::Local<v8::Function> cb = cb_v.As<v8::Function>();
assert(cb->IsFunction());

return MakeCallback(cb, argc, argv);
ASSERT(cb_v->IsFunction());
return MakeCallback(cb_v.As<v8::Function>(), argc, argv);
}


Expand All @@ -68,10 +66,8 @@ inline v8::Handle<v8::Value> AsyncWrap::MakeCallback(
int argc,
v8::Handle<v8::Value>* argv) {
v8::Local<v8::Value> cb_v = object()->Get(index);
v8::Local<v8::Function> cb = cb_v.As<v8::Function>();
assert(cb->IsFunction());

return MakeCallback(cb, argc, argv);
ASSERT(cb_v->IsFunction());
return MakeCallback(cb_v.As<v8::Function>(), argc, argv);
}

} // namespace node
Expand Down
88 changes: 20 additions & 68 deletions src/async-wrap.cc
Expand Up @@ -37,30 +37,33 @@ using v8::Value;

namespace node {

Handle<Value> AsyncWrap::MakeDomainCallback(const Handle<Function> cb,
int argc,
Handle<Value>* argv) {
Handle<Value> AsyncWrap::MakeCallback(const Handle<Function> cb,
int argc,
Handle<Value>* argv) {
CHECK(env()->context() == env()->isolate()->GetCurrentContext());

Local<Object> context = object();
Local<Object> process = env()->process_object();
Local<Value> domain_v = context->Get(env()->domain_string());
Local<Object> domain;
bool has_domain = false;

if (env()->using_domains()) {
Local<Value> domain_v = context->Get(env()->domain_string());
has_domain = domain_v->IsObject();
if (has_domain) {
domain = domain_v.As<Object>();
if (domain->Get(env()->disposed_string())->IsTrue())
return Undefined(env()->isolate());
}
}

TryCatch try_catch;
try_catch.SetVerbose(true);

bool has_domain = domain_v->IsObject();
if (has_domain) {
domain = domain_v.As<Object>();

if (domain->Get(env()->disposed_string())->IsTrue())
return Undefined(env()->isolate());

Local<Function> enter =
domain->Get(env()->enter_string()).As<Function>();
if (enter->IsFunction()) {
enter->Call(domain, 0, NULL);
Local<Value> enter_v = domain->Get(env()->enter_string());
if (enter_v->IsFunction()) {
enter_v.As<Function>()->Call(domain, 0, NULL);
if (try_catch.HasCaught())
return Undefined(env()->isolate());
}
Expand All @@ -73,10 +76,9 @@ Handle<Value> AsyncWrap::MakeDomainCallback(const Handle<Function> cb,
}

if (has_domain) {
Local<Function> exit =
domain->Get(env()->exit_string()).As<Function>();
if (exit->IsFunction()) {
exit->Call(domain, 0, NULL);
Local<Value> exit_v = domain->Get(env()->exit_string());
if (exit_v->IsFunction()) {
exit_v.As<Function>()->Call(domain, 0, NULL);
if (try_catch.HasCaught())
return Undefined(env()->isolate());
}
Expand Down Expand Up @@ -111,54 +113,4 @@ Handle<Value> AsyncWrap::MakeDomainCallback(const Handle<Function> cb,
return ret;
}


Handle<Value> AsyncWrap::MakeCallback(const Handle<Function> cb,
int argc,
Handle<Value>* argv) {
if (env()->using_domains())
return MakeDomainCallback(cb, argc, argv);

CHECK(env()->context() == env()->isolate()->GetCurrentContext());

Local<Object> context = object();
Local<Object> process = env()->process_object();

TryCatch try_catch;
try_catch.SetVerbose(true);

Local<Value> ret = cb->Call(context, argc, argv);

if (try_catch.HasCaught()) {
return Undefined(env()->isolate());
}

Environment::TickInfo* tick_info = env()->tick_info();

if (tick_info->in_tick()) {
return ret;
}

if (tick_info->length() == 0) {
env()->isolate()->RunMicrotasks();
}

if (tick_info->length() == 0) {
tick_info->set_index(0);
return ret;
}

tick_info->set_in_tick(true);

env()->tick_callback_function()->Call(process, 0, NULL);

tick_info->set_in_tick(false);

if (try_catch.HasCaught()) {
tick_info->set_last_threw(true);
return Undefined(env()->isolate());
}

return ret;
}

} // namespace node
7 changes: 0 additions & 7 deletions src/async-wrap.h
Expand Up @@ -74,13 +74,6 @@ class AsyncWrap : public BaseObject {
private:
inline AsyncWrap();

// TODO(trevnorris): BURN IN FIRE! Remove this as soon as a suitable
// replacement is committed.
v8::Handle<v8::Value> MakeDomainCallback(
const v8::Handle<v8::Function> cb,
int argc,
v8::Handle<v8::Value>* argv);

uint32_t provider_type_;
};

Expand Down
133 changes: 30 additions & 103 deletions src/node.cc
Expand Up @@ -978,111 +978,53 @@ void SetupNextTick(const FunctionCallbackInfo<Value>& args) {
}


Handle<Value> MakeDomainCallback(Environment* env,
Handle<Value> recv,
const Handle<Function> callback,
int argc,
Handle<Value> argv[]) {
Handle<Value> MakeCallback(Environment* env,
Handle<Value> recv,
const Handle<Function> callback,
int argc,
Handle<Value> argv[]) {
// If you hit this assertion, you forgot to enter the v8::Context first.
assert(env->context() == env->isolate()->GetCurrentContext());
CHECK(env->context() == env->isolate()->GetCurrentContext());

Local<Object> process = env->process_object();
Local<Object> object, domain;
Local<Value> domain_v;

TryCatch try_catch;
try_catch.SetVerbose(true);

bool has_domain = false;

if (!object.IsEmpty()) {
domain_v = object->Get(env->domain_string());
if (env->using_domains()) {
CHECK(recv->IsObject());
object = recv.As<Object>();
Local<Value> domain_v = object->Get(env->domain_string());
has_domain = domain_v->IsObject();
if (has_domain) {
domain = domain_v.As<Object>();

if (domain->Get(env->disposed_string())->IsTrue()) {
// domain has been disposed of.
if (domain->Get(env->disposed_string())->IsTrue())
return Undefined(env->isolate());
}

Local<Function> enter = domain->Get(env->enter_string()).As<Function>();
if (enter->IsFunction()) {
enter->Call(domain, 0, NULL);
if (try_catch.HasCaught())
return Undefined(env->isolate());
}
}
}

Local<Value> ret = callback->Call(recv, argc, argv);

if (try_catch.HasCaught()) {
return Undefined(env->isolate());
}
TryCatch try_catch;
try_catch.SetVerbose(true);

if (has_domain) {
Local<Function> exit = domain->Get(env->exit_string()).As<Function>();
if (exit->IsFunction()) {
exit->Call(domain, 0, NULL);
Local<Value> enter_v = domain->Get(env->enter_string());
if (enter_v->IsFunction()) {
enter_v.As<Function>()->Call(domain, 0, NULL);
if (try_catch.HasCaught())
return Undefined(env->isolate());
}
}

Environment::TickInfo* tick_info = env->tick_info();

if (tick_info->last_threw() == 1) {
tick_info->set_last_threw(0);
return ret;
}

if (tick_info->in_tick()) {
return ret;
}

if (tick_info->length() == 0) {
env->isolate()->RunMicrotasks();
}

if (tick_info->length() == 0) {
tick_info->set_index(0);
return ret;
}

tick_info->set_in_tick(true);

env->tick_callback_function()->Call(process, 0, NULL);

tick_info->set_in_tick(false);
Local<Value> ret = callback->Call(recv, argc, argv);

if (try_catch.HasCaught()) {
tick_info->set_last_threw(true);
return Undefined(env->isolate());
if (has_domain) {
Local<Value> exit_v = domain->Get(env->exit_string());
if (exit_v->IsFunction()) {
exit_v.As<Function>()->Call(domain, 0, NULL);
if (try_catch.HasCaught())
return Undefined(env->isolate());
}
}

return ret;
}


Handle<Value> MakeCallback(Environment* env,
Handle<Value> recv,
const Handle<Function> callback,
int argc,
Handle<Value> argv[]) {
if (env->using_domains())
return MakeDomainCallback(env, recv, callback, argc, argv);

// If you hit this assertion, you forgot to enter the v8::Context first.
assert(env->context() == env->isolate()->GetCurrentContext());

Local<Object> process = env->process_object();

TryCatch try_catch;
try_catch.SetVerbose(true);

Local<Value> ret = callback->Call(recv, argc, argv);

if (try_catch.HasCaught()) {
return Undefined(env->isolate());
}
Expand Down Expand Up @@ -1124,10 +1066,9 @@ Handle<Value> MakeCallback(Environment* env,
uint32_t index,
int argc,
Handle<Value> argv[]) {
Local<Function> callback = recv->Get(index).As<Function>();
assert(callback->IsFunction());

return MakeCallback(env, recv.As<Value>(), callback, argc, argv);
Local<Value> cb_v = recv->Get(index);
CHECK(cb_v->IsFunction());
return MakeCallback(env, recv.As<Value>(), cb_v.As<Function>(), argc, argv);
}


Expand All @@ -1136,9 +1077,9 @@ Handle<Value> MakeCallback(Environment* env,
Handle<String> symbol,
int argc,
Handle<Value> argv[]) {
Local<Function> callback = recv->Get(symbol).As<Function>();
assert(callback->IsFunction());
return MakeCallback(env, recv.As<Value>(), callback, argc, argv);
Local<Value> cb_v = recv->Get(symbol);
CHECK(cb_v->IsFunction());
return MakeCallback(env, recv.As<Value>(), cb_v.As<Function>(), argc, argv);
}


Expand Down Expand Up @@ -1195,20 +1136,6 @@ Handle<Value> MakeCallback(Isolate* isolate,
}


Handle<Value> MakeDomainCallback(Handle<Object> recv,
Handle<Function> callback,
int argc,
Handle<Value> argv[]) {
Local<Context> context = recv->CreationContext();
Environment* env = Environment::GetCurrent(context);
Context::Scope context_scope(context);
EscapableHandleScope handle_scope(env->isolate());
return handle_scope.Escape(Local<Value>::New(
env->isolate(),
MakeDomainCallback(env, recv, callback, argc, argv)));
}


enum encoding ParseEncoding(Isolate* isolate,
Handle<Value> encoding_v,
enum encoding _default) {
Expand Down

0 comments on commit 42df679

Please sign in to comment.