Revision: 16584
Author: [email protected]
Date: Mon Sep 9 07:08:34 2013 UTC
Log: add uncached Function::New
[email protected]
BUG=
Review URL: https://codereview.chromium.org/23561007
http://code.google.com/p/v8/source/detail?r=16584
Modified:
/branches/bleeding_edge/include/v8.h
/branches/bleeding_edge/src/api.cc
/branches/bleeding_edge/src/apinatives.js
/branches/bleeding_edge/src/execution.cc
/branches/bleeding_edge/src/macros.py
/branches/bleeding_edge/src/objects-inl.h
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/test/cctest/test-api.cc
=======================================
--- /branches/bleeding_edge/include/v8.h Fri Sep 6 11:29:13 2013 UTC
+++ /branches/bleeding_edge/include/v8.h Mon Sep 9 07:08:34 2013 UTC
@@ -2361,11 +2361,23 @@
};
+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[]);
@@ -3139,8 +3151,6 @@
internal::Object** args_;
};
-
-typedef void (*FunctionCallback)(const FunctionCallbackInfo<Value>& info);
/**
* NamedProperty[Getter|Setter] are used as interceptors on object.
=======================================
--- /branches/bleeding_edge/src/api.cc Fri Sep 6 11:29:13 2013 UTC
+++ /branches/bleeding_edge/src/api.cc Mon Sep 9 07:08:34 2013 UTC
@@ -1052,22 +1052,24 @@
}
-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,11 +1078,23 @@
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,
@@ -4187,6 +4201,19 @@
}
return Local<v8::Object>();
}
+
+
+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 {
=======================================
--- /branches/bleeding_edge/src/apinatives.js Mon Aug 26 17:40:03 2013 UTC
+++ /branches/bleeding_edge/src/apinatives.js Mon Sep 9 07:08:34 2013 UTC
@@ -74,8 +74,9 @@
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 @@
}
}
ConfigureTemplateInstance(fun, data);
+ if (doNotCache) return fun;
} catch (e) {
cache[serialNumber] = kUninitialized;
throw e;
=======================================
--- /branches/bleeding_edge/src/execution.cc Thu Sep 5 08:48:34 2013 UTC
+++ /branches/bleeding_edge/src/execution.cc Mon Sep 9 07:08:34 2013 UTC
@@ -705,12 +705,14 @@
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,
=======================================
--- /branches/bleeding_edge/src/macros.py Wed Sep 4 07:45:36 2013 UTC
+++ /branches/bleeding_edge/src/macros.py Mon Sep 9 07:08:34 2013 UTC
@@ -69,6 +69,7 @@
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';
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Thu Sep 5 13:20:51 2013 UTC
+++ /branches/bleeding_edge/src/objects-inl.h Mon Sep 9 07:08:34 2013 UTC
@@ -4569,6 +4569,8 @@
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,
=======================================
--- /branches/bleeding_edge/src/objects.h Thu Sep 5 13:20:51 2013 UTC
+++ /branches/bleeding_edge/src/objects.h Mon Sep 9 07:08:34 2013 UTC
@@ -9878,6 +9878,7 @@
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 @@
static const int kNeedsAccessCheckBit = 2;
static const int kReadOnlyPrototypeBit = 3;
static const int kRemovePrototypeBit = 4;
+ static const int kDoNotCacheBit = 5;
DISALLOW_IMPLICIT_CONSTRUCTORS(FunctionTemplateInfo);
};
=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc Fri Sep 6 11:31:25
2013 UTC
+++ /branches/bleeding_edge/test/cctest/test-api.cc Mon Sep 9 07:08:34
2013 UTC
@@ -20490,5 +20490,35 @@
ExpectInt32("obj.age", 100000);
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());
+}
+
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.