Commit c20f87a6 authored by dcarney@chromium.org's avatar dcarney@chromium.org

add uncached Function::New

TBR=mstarzinger@chromium.org
BUG=

Review URL: https://codereview.chromium.org/24071002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16586 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 5b0a2816
......@@ -2361,11 +2361,129 @@ class V8_EXPORT Array : public Object {
};
template<typename T>
class ReturnValue {
public:
template <class S> V8_INLINE(ReturnValue(const ReturnValue<S>& that))
: value_(that.value_) {
TYPE_CHECK(T, S);
}
// Handle setters
template <typename S> V8_INLINE(void Set(const Persistent<S>& handle));
template <typename S> V8_INLINE(void Set(const Handle<S> handle));
// Fast primitive setters
V8_INLINE(void Set(bool value));
V8_INLINE(void Set(double i));
V8_INLINE(void Set(int32_t i));
V8_INLINE(void Set(uint32_t i));
// Fast JS primitive setters
V8_INLINE(void SetNull());
V8_INLINE(void SetUndefined());
V8_INLINE(void SetEmptyString());
// Convenience getter for Isolate
V8_INLINE(Isolate* GetIsolate());
private:
template<class F> friend class ReturnValue;
template<class F> friend class FunctionCallbackInfo;
template<class F> friend class PropertyCallbackInfo;
V8_INLINE(internal::Object* GetDefaultValue());
V8_INLINE(explicit ReturnValue(internal::Object** slot));
internal::Object** value_;
};
/**
* The argument information given to function call callbacks. This
* class provides access to information about the context of the call,
* including the receiver, the number and values of arguments, and
* the holder of the function.
*/
template<typename T>
class FunctionCallbackInfo {
public:
V8_INLINE(int Length() const);
V8_INLINE(Local<Value> operator[](int i) const);
V8_INLINE(Local<Function> Callee() const);
V8_INLINE(Local<Object> This() const);
V8_INLINE(Local<Object> Holder() const);
V8_INLINE(bool IsConstructCall() const);
V8_INLINE(Local<Value> Data() const);
V8_INLINE(Isolate* GetIsolate() const);
V8_INLINE(ReturnValue<T> GetReturnValue() const);
// This shouldn't be public, but the arm compiler needs it.
static const int kArgsLength = 6;
protected:
friend class internal::FunctionCallbackArguments;
friend class internal::CustomArguments<FunctionCallbackInfo>;
static const int kReturnValueIndex = 0;
static const int kReturnValueDefaultValueIndex = -1;
static const int kIsolateIndex = -2;
static const int kDataIndex = -3;
static const int kCalleeIndex = -4;
static const int kHolderIndex = -5;
V8_INLINE(FunctionCallbackInfo(internal::Object** implicit_args,
internal::Object** values,
int length,
bool is_construct_call));
internal::Object** implicit_args_;
internal::Object** values_;
int length_;
bool is_construct_call_;
};
/**
* The information passed to a property callback about the context
* of the property access.
*/
template<typename T>
class PropertyCallbackInfo {
public:
V8_INLINE(Isolate* GetIsolate() const);
V8_INLINE(Local<Value> Data() const);
V8_INLINE(Local<Object> This() const);
V8_INLINE(Local<Object> Holder() const);
V8_INLINE(ReturnValue<T> GetReturnValue() const);
// This shouldn't be public, but the arm compiler needs it.
static const int kArgsLength = 6;
protected:
friend class MacroAssembler;
friend class internal::PropertyCallbackArguments;
friend class internal::CustomArguments<PropertyCallbackInfo>;
static const int kThisIndex = 0;
static const int kHolderIndex = -1;
static const int kDataIndex = -2;
static const int kReturnValueIndex = -3;
static const int kReturnValueDefaultValueIndex = -4;
static const int kIsolateIndex = -5;
V8_INLINE(PropertyCallbackInfo(internal::Object** args))
: args_(args) { }
internal::Object** args_;
};
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[]);
......@@ -3034,114 +3152,6 @@ class V8_EXPORT Template : public Data {
};
template<typename T>
class ReturnValue {
public:
template <class S> V8_INLINE(ReturnValue(const ReturnValue<S>& that))
: value_(that.value_) {
TYPE_CHECK(T, S);
}
// Handle setters
template <typename S> V8_INLINE(void Set(const Persistent<S>& handle));
template <typename S> V8_INLINE(void Set(const Handle<S> handle));
// Fast primitive setters
V8_INLINE(void Set(bool value));
V8_INLINE(void Set(double i));
V8_INLINE(void Set(int32_t i));
V8_INLINE(void Set(uint32_t i));
// Fast JS primitive setters
V8_INLINE(void SetNull());
V8_INLINE(void SetUndefined());
V8_INLINE(void SetEmptyString());
// Convenience getter for Isolate
V8_INLINE(Isolate* GetIsolate());
private:
template<class F> friend class ReturnValue;
template<class F> friend class FunctionCallbackInfo;
template<class F> friend class PropertyCallbackInfo;
V8_INLINE(internal::Object* GetDefaultValue());
V8_INLINE(explicit ReturnValue(internal::Object** slot));
internal::Object** value_;
};
/**
* The argument information given to function call callbacks. This
* class provides access to information about the context of the call,
* including the receiver, the number and values of arguments, and
* the holder of the function.
*/
template<typename T>
class FunctionCallbackInfo {
public:
V8_INLINE(int Length() const);
V8_INLINE(Local<Value> operator[](int i) const);
V8_INLINE(Local<Function> Callee() const);
V8_INLINE(Local<Object> This() const);
V8_INLINE(Local<Object> Holder() const);
V8_INLINE(bool IsConstructCall() const);
V8_INLINE(Local<Value> Data() const);
V8_INLINE(Isolate* GetIsolate() const);
V8_INLINE(ReturnValue<T> GetReturnValue() const);
// This shouldn't be public, but the arm compiler needs it.
static const int kArgsLength = 6;
protected:
friend class internal::FunctionCallbackArguments;
friend class internal::CustomArguments<FunctionCallbackInfo>;
static const int kReturnValueIndex = 0;
static const int kReturnValueDefaultValueIndex = -1;
static const int kIsolateIndex = -2;
static const int kDataIndex = -3;
static const int kCalleeIndex = -4;
static const int kHolderIndex = -5;
V8_INLINE(FunctionCallbackInfo(internal::Object** implicit_args,
internal::Object** values,
int length,
bool is_construct_call));
internal::Object** implicit_args_;
internal::Object** values_;
int length_;
bool is_construct_call_;
};
/**
* The information passed to a property callback about the context
* of the property access.
*/
template<typename T>
class PropertyCallbackInfo {
public:
V8_INLINE(Isolate* GetIsolate() const);
V8_INLINE(Local<Value> Data() const);
V8_INLINE(Local<Object> This() const);
V8_INLINE(Local<Object> Holder() const);
V8_INLINE(ReturnValue<T> GetReturnValue() const);
// This shouldn't be public, but the arm compiler needs it.
static const int kArgsLength = 6;
protected:
friend class MacroAssembler;
friend class internal::PropertyCallbackArguments;
friend class internal::CustomArguments<PropertyCallbackInfo>;
static const int kThisIndex = 0;
static const int kHolderIndex = -1;
static const int kDataIndex = -2;
static const int kReturnValueIndex = -3;
static const int kReturnValueDefaultValueIndex = -4;
static const int kIsolateIndex = -5;
V8_INLINE(PropertyCallbackInfo(internal::Object** args))
: args_(args) { }
internal::Object** args_;
};
typedef void (*FunctionCallback)(const FunctionCallbackInfo<Value>& info);
/**
* NamedProperty[Getter|Setter] are used as interceptors on object.
* See ObjectTemplate::SetNamedPropertyHandler.
......
......@@ -1052,22 +1052,24 @@ void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
}
Local<FunctionTemplate> FunctionTemplate::New(
static Local<FunctionTemplate> FunctionTemplateNew(
i::Isolate* isolate,
FunctionCallback callback,
v8::Handle<Value> data,
v8::Handle<Signature> signature,
int length) {
i::Isolate* isolate = i::Isolate::Current();
EnsureInitializedForIsolate(isolate, "v8::FunctionTemplate::New()");
LOG_API(isolate, "FunctionTemplate::New");
ENTER_V8(isolate);
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);
int next_serial_number = isolate->next_serial_number();
isolate->set_next_serial_number(next_serial_number + 1);
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();
......@@ -1076,12 +1078,24 @@ Local<FunctionTemplate> FunctionTemplate::New(
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,
v8::Handle<Signature> signature,
int length) {
i::Isolate* isolate = i::Isolate::Current();
EnsureInitializedForIsolate(isolate, "v8::FunctionTemplate::New()");
LOG_API(isolate, "FunctionTemplate::New");
ENTER_V8(isolate);
return FunctionTemplateNew(
isolate, callback, data, signature, length, false);
}
Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
int argc, Handle<FunctionTemplate> argv[]) {
......@@ -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);
}
......@@ -7865,7 +7892,7 @@ void InvokeAccessorGetterCallback(
getter));
VMState<EXTERNAL> state(isolate);
ExternalCallbackScope call_scope(isolate, getter_address);
return getter(property, info);
getter(property, info);
}
......@@ -7876,7 +7903,7 @@ void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback));
VMState<EXTERNAL> state(isolate);
ExternalCallbackScope call_scope(isolate, callback_address);
return callback(info);
callback(info);
}
......
......@@ -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();
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());
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment