add uncached Function::New
R=mstarzinger@chromium.org BUG= Review URL: https://codereview.chromium.org/23561007 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16584 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
d4d66a712e
commit
ddc5d437bb
14
include/v8.h
14
include/v8.h
@ -2361,11 +2361,23 @@ class V8_EXPORT Array : public Object {
|
||||
};
|
||||
|
||||
|
||||
typedef void (*FunctionCallback)(const FunctionCallbackInfo<Value>& info);
|
||||
|
||||
|
||||
/**
|
||||
* A JavaScript function object (ECMA-262, 15.3).
|
||||
*/
|
||||
class V8_EXPORT Function : public Object {
|
||||
public:
|
||||
/**
|
||||
* Create a function in the current execution context
|
||||
* for a given FunctionCallback.
|
||||
*/
|
||||
static Local<Function> New(Isolate* isolate,
|
||||
FunctionCallback callback,
|
||||
Local<Value> data = Local<Value>(),
|
||||
int length = 0);
|
||||
|
||||
Local<Object> NewInstance() const;
|
||||
Local<Object> NewInstance(int argc, Handle<Value> argv[]) const;
|
||||
Local<Value> Call(Handle<Object> recv, int argc, Handle<Value> argv[]);
|
||||
@ -3140,8 +3152,6 @@ class PropertyCallbackInfo {
|
||||
};
|
||||
|
||||
|
||||
typedef void (*FunctionCallback)(const FunctionCallbackInfo<Value>& info);
|
||||
|
||||
/**
|
||||
* NamedProperty[Getter|Setter] are used as interceptors on object.
|
||||
* See ObjectTemplate::SetNamedPropertyHandler.
|
||||
|
65
src/api.cc
65
src/api.cc
@ -1052,6 +1052,37 @@ void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
|
||||
}
|
||||
|
||||
|
||||
static Local<FunctionTemplate> FunctionTemplateNew(
|
||||
i::Isolate* isolate,
|
||||
FunctionCallback callback,
|
||||
v8::Handle<Value> data,
|
||||
v8::Handle<Signature> signature,
|
||||
int length,
|
||||
bool do_not_cache) {
|
||||
i::Handle<i::Struct> struct_obj =
|
||||
isolate->factory()->NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
|
||||
i::Handle<i::FunctionTemplateInfo> obj =
|
||||
i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
|
||||
InitializeFunctionTemplate(obj);
|
||||
obj->set_do_not_cache(do_not_cache);
|
||||
int next_serial_number = 0;
|
||||
if (!do_not_cache) {
|
||||
next_serial_number = isolate->next_serial_number() + 1;
|
||||
isolate->set_next_serial_number(next_serial_number);
|
||||
}
|
||||
obj->set_serial_number(i::Smi::FromInt(next_serial_number));
|
||||
if (callback != 0) {
|
||||
if (data.IsEmpty()) data = v8::Undefined();
|
||||
Utils::ToLocal(obj)->SetCallHandler(callback, data);
|
||||
}
|
||||
obj->set_length(length);
|
||||
obj->set_undetectable(false);
|
||||
obj->set_needs_access_check(false);
|
||||
if (!signature.IsEmpty())
|
||||
obj->set_signature(*Utils::OpenHandle(*signature));
|
||||
return Utils::ToLocal(obj);
|
||||
}
|
||||
|
||||
Local<FunctionTemplate> FunctionTemplate::New(
|
||||
FunctionCallback callback,
|
||||
v8::Handle<Value> data,
|
||||
@ -1061,25 +1092,8 @@ Local<FunctionTemplate> FunctionTemplate::New(
|
||||
EnsureInitializedForIsolate(isolate, "v8::FunctionTemplate::New()");
|
||||
LOG_API(isolate, "FunctionTemplate::New");
|
||||
ENTER_V8(isolate);
|
||||
i::Handle<i::Struct> struct_obj =
|
||||
isolate->factory()->NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
|
||||
i::Handle<i::FunctionTemplateInfo> obj =
|
||||
i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
|
||||
InitializeFunctionTemplate(obj);
|
||||
int next_serial_number = isolate->next_serial_number();
|
||||
isolate->set_next_serial_number(next_serial_number + 1);
|
||||
obj->set_serial_number(i::Smi::FromInt(next_serial_number));
|
||||
if (callback != 0) {
|
||||
if (data.IsEmpty()) data = v8::Undefined();
|
||||
Utils::ToLocal(obj)->SetCallHandler(callback, data);
|
||||
}
|
||||
obj->set_length(length);
|
||||
obj->set_undetectable(false);
|
||||
obj->set_needs_access_check(false);
|
||||
|
||||
if (!signature.IsEmpty())
|
||||
obj->set_signature(*Utils::OpenHandle(*signature));
|
||||
return Utils::ToLocal(obj);
|
||||
return FunctionTemplateNew(
|
||||
isolate, callback, data, signature, length, false);
|
||||
}
|
||||
|
||||
|
||||
@ -4189,6 +4203,19 @@ Local<v8::Value> Object::CallAsConstructor(int argc,
|
||||
}
|
||||
|
||||
|
||||
Local<Function> Function::New(Isolate* v8_isolate,
|
||||
FunctionCallback callback,
|
||||
Local<Value> data,
|
||||
int length) {
|
||||
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
|
||||
LOG_API(isolate, "Function::New");
|
||||
ENTER_V8(isolate);
|
||||
return FunctionTemplateNew(
|
||||
isolate, callback, data, Local<Signature>(), length, true)->
|
||||
GetFunction();
|
||||
}
|
||||
|
||||
|
||||
Local<v8::Object> Function::NewInstance() const {
|
||||
return NewInstance(0, NULL);
|
||||
}
|
||||
|
@ -74,8 +74,9 @@ function InstantiateFunction(data, name) {
|
||||
cache[serialNumber] = null;
|
||||
var fun = %CreateApiFunction(data);
|
||||
if (name) %FunctionSetName(fun, name);
|
||||
cache[serialNumber] = fun;
|
||||
var flags = %GetTemplateField(data, kApiFlagOffset);
|
||||
var doNotCache = flags & (1 << kDoNotCacheBit);
|
||||
if (!doNotCache) cache[serialNumber] = fun;
|
||||
if (flags & (1 << kRemovePrototypeBit)) {
|
||||
%FunctionRemovePrototype(fun);
|
||||
} else {
|
||||
@ -97,6 +98,7 @@ function InstantiateFunction(data, name) {
|
||||
}
|
||||
}
|
||||
ConfigureTemplateInstance(fun, data);
|
||||
if (doNotCache) return fun;
|
||||
} catch (e) {
|
||||
cache[serialNumber] = kUninitialized;
|
||||
throw e;
|
||||
|
@ -705,12 +705,14 @@ Handle<JSFunction> Execution::InstantiateFunction(
|
||||
Handle<FunctionTemplateInfo> data,
|
||||
bool* exc) {
|
||||
Isolate* isolate = data->GetIsolate();
|
||||
// Fast case: see if the function has already been instantiated
|
||||
int serial_number = Smi::cast(data->serial_number())->value();
|
||||
Object* elm =
|
||||
isolate->native_context()->function_cache()->
|
||||
GetElementNoExceptionThrown(isolate, serial_number);
|
||||
if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm));
|
||||
if (!data->do_not_cache()) {
|
||||
// Fast case: see if the function has already been instantiated
|
||||
int serial_number = Smi::cast(data->serial_number())->value();
|
||||
Object* elm =
|
||||
isolate->native_context()->function_cache()->
|
||||
GetElementNoExceptionThrown(isolate, serial_number);
|
||||
if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm));
|
||||
}
|
||||
// The function has not yet been instantiated in this context; do it.
|
||||
Handle<Object> args[] = { data };
|
||||
Handle<Object> result = Call(isolate,
|
||||
|
@ -69,6 +69,7 @@ const msPerMonth = 2592000000;
|
||||
const kUninitialized = -1;
|
||||
const kReadOnlyPrototypeBit = 3;
|
||||
const kRemovePrototypeBit = 4; # For FunctionTemplateInfo, matches objects.h
|
||||
const kDoNotCacheBit = 5; # For FunctionTemplateInfo, matches objects.h
|
||||
|
||||
# Note: kDayZeroInJulianDay = ToJulianDay(1970, 0, 1).
|
||||
const kInvalidDate = 'Invalid Date';
|
||||
|
@ -4569,6 +4569,8 @@ BOOL_ACCESSORS(FunctionTemplateInfo, flag, read_only_prototype,
|
||||
kReadOnlyPrototypeBit)
|
||||
BOOL_ACCESSORS(FunctionTemplateInfo, flag, remove_prototype,
|
||||
kRemovePrototypeBit)
|
||||
BOOL_ACCESSORS(FunctionTemplateInfo, flag, do_not_cache,
|
||||
kDoNotCacheBit)
|
||||
BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
|
||||
kIsExpressionBit)
|
||||
BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
|
||||
|
@ -9878,6 +9878,7 @@ class FunctionTemplateInfo: public TemplateInfo {
|
||||
DECL_BOOLEAN_ACCESSORS(needs_access_check)
|
||||
DECL_BOOLEAN_ACCESSORS(read_only_prototype)
|
||||
DECL_BOOLEAN_ACCESSORS(remove_prototype)
|
||||
DECL_BOOLEAN_ACCESSORS(do_not_cache)
|
||||
|
||||
static inline FunctionTemplateInfo* cast(Object* obj);
|
||||
|
||||
@ -9913,6 +9914,7 @@ class FunctionTemplateInfo: public TemplateInfo {
|
||||
static const int kNeedsAccessCheckBit = 2;
|
||||
static const int kReadOnlyPrototypeBit = 3;
|
||||
static const int kRemovePrototypeBit = 4;
|
||||
static const int kDoNotCacheBit = 5;
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(FunctionTemplateInfo);
|
||||
};
|
||||
|
@ -20491,4 +20491,34 @@ THREADED_TEST(CrankshaftInterceptorFieldWrite) {
|
||||
ExpectInt32("obj.interceptor_age", 103);
|
||||
}
|
||||
|
||||
|
||||
#endif // V8_OS_POSIX
|
||||
|
||||
|
||||
static Local<Value> function_new_expected_env;
|
||||
static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
|
||||
CHECK_EQ(function_new_expected_env, info.Data());
|
||||
info.GetReturnValue().Set(17);
|
||||
}
|
||||
|
||||
|
||||
THREADED_TEST(FunctionNew) {
|
||||
LocalContext env;
|
||||
v8::Isolate* isolate = env->GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
Local<Object> data = v8::Object::New();
|
||||
function_new_expected_env = data;
|
||||
Local<Function> func = Function::New(isolate, FunctionNewCallback, data);
|
||||
env->Global()->Set(v8_str("func"), func);
|
||||
Local<Value> result = CompileRun("func();");
|
||||
CHECK_EQ(v8::Integer::New(17, isolate), result);
|
||||
// Verify function not cached
|
||||
int serial_number =
|
||||
i::Smi::cast(v8::Utils::OpenHandle(*func)
|
||||
->shared()->get_api_func_data()->serial_number())->value();
|
||||
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
|
||||
i::Object* elm = i_isolate->native_context()->function_cache()
|
||||
->GetElementNoExceptionThrown(i_isolate, serial_number);
|
||||
CHECK(elm->IsNull());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user