Revision: 3739
Author: [email protected]
Date: Fri Jan 29 01:52:51 2010
Log: Propagate receiver from initial call site to code generator.
When doing lazy compilation of methods, allow the code generator to know the
(initial) receiver at the (initial) call site.
Review URL: http://codereview.chromium.org/551189
http://code.google.com/p/v8/source/detail?r=3739
Modified:
/branches/bleeding_edge/src/accessors.cc
/branches/bleeding_edge/src/bootstrapper.cc
/branches/bleeding_edge/src/builtins.cc
/branches/bleeding_edge/src/compiler.cc
/branches/bleeding_edge/src/compiler.h
/branches/bleeding_edge/src/debug.cc
/branches/bleeding_edge/src/debug.h
/branches/bleeding_edge/src/fast-codegen.cc
/branches/bleeding_edge/src/fast-codegen.h
/branches/bleeding_edge/src/handles.cc
/branches/bleeding_edge/src/handles.h
/branches/bleeding_edge/src/ic.cc
/branches/bleeding_edge/src/runtime.cc
=======================================
--- /branches/bleeding_edge/src/accessors.cc Tue Dec 1 06:36:45 2009
+++ /branches/bleeding_edge/src/accessors.cc Fri Jan 29 01:52:51 2010
@@ -493,11 +493,11 @@
// If the function isn't compiled yet, the length is not computed
// correctly yet. Compile it now and return the right length.
HandleScope scope;
- Handle<JSFunction> function_handle(function);
- if (!CompileLazy(function_handle, KEEP_EXCEPTION)) {
+ Handle<SharedFunctionInfo> shared(function->shared());
+ if (!CompileLazyShared(shared, KEEP_EXCEPTION)) {
return Failure::Exception();
}
- return Smi::FromInt(function_handle->shared()->length());
+ return Smi::FromInt(shared->length());
} else {
return Smi::FromInt(function->shared()->length());
}
=======================================
--- /branches/bleeding_edge/src/bootstrapper.cc Thu Jan 28 02:46:58 2010
+++ /branches/bleeding_edge/src/bootstrapper.cc Fri Jan 29 01:52:51 2010
@@ -249,26 +249,24 @@
V8_Fatal(__FILE__, __LINE__, "Cannot resolve call to builtin %s",
name);
}
#endif
- Handle<JSFunction> f = Handle<JSFunction>(JSFunction::cast(o));
+ Handle<SharedFunctionInfo> shared(JSFunction::cast(o)->shared());
// Make sure the number of parameters match the formal parameter count.
int argc = Bootstrapper::FixupFlagsArgumentsCount::decode(flags);
USE(argc);
- ASSERT(f->shared()->formal_parameter_count() == argc);
- if (!f->is_compiled()) {
- // Do lazy compilation and check for stack overflows.
- if (!CompileLazy(f, CLEAR_EXCEPTION)) {
- Clear();
- return false;
- }
+ ASSERT(shared->formal_parameter_count() == argc);
+ // Do lazy compilation if necessary and check for stack overflows.
+ if (!EnsureCompiled(shared, CLEAR_EXCEPTION)) {
+ Clear();
+ return false;
}
Code* code = Code::cast(code_[i]);
Address pc = code->instruction_start() + pc_[i];
RelocInfo target(pc, RelocInfo::CODE_TARGET, 0);
bool use_code_object =
Bootstrapper::FixupFlagsUseCodeObject::decode(flags);
if (use_code_object) {
- target.set_target_object(f->code());
+ target.set_target_object(shared->code());
} else {
- target.set_target_address(f->code()->instruction_start());
+ target.set_target_address(shared->code()->instruction_start());
}
LOG(StringEvent("resolved", name));
}
=======================================
--- /branches/bleeding_edge/src/builtins.cc Fri Jan 15 05:43:28 2010
+++ /branches/bleeding_edge/src/builtins.cc Fri Jan 29 01:52:51 2010
@@ -175,12 +175,12 @@
if (Top::context() != NULL) {
Object* object = Top::builtins()->javascript_builtin(id);
if (object->IsJSFunction()) {
- Handle<JSFunction> function(JSFunction::cast(object));
+ Handle<SharedFunctionInfo>
shared(JSFunction::cast(object)->shared());
// Make sure the number of parameters match the formal parameter
count.
- ASSERT(function->shared()->formal_parameter_count() ==
+ ASSERT(shared->formal_parameter_count() ==
Builtins::GetArgumentsCount(id));
- if (function->is_compiled() || CompileLazy(function,
CLEAR_EXCEPTION)) {
- code = function->code();
+ if (EnsureCompiled(shared, CLEAR_EXCEPTION)) {
+ code = shared->code();
*resolved = true;
}
}
=======================================
--- /branches/bleeding_edge/src/compiler.cc Fri Jan 29 01:42:13 2010
+++ /branches/bleeding_edge/src/compiler.cc Fri Jan 29 01:52:51 2010
@@ -48,7 +48,8 @@
Handle<Script> script,
Handle<Context> context,
bool is_eval,
- Handle<SharedFunctionInfo> shared) {
+ Handle<SharedFunctionInfo> shared,
+ Handle<Object> receiver) {
ASSERT(literal != NULL);
// Rewrite the AST by introducing .result assignments where needed.
@@ -109,7 +110,7 @@
}
} else if (FLAG_always_fast_compiler ||
(FLAG_fast_compiler && !is_run_once)) {
- FastCodeGenSyntaxChecker checker;
+ FastCodeGenSyntaxChecker checker(receiver);
checker.Check(literal);
if (checker.has_supported_syntax()) {
AstLabeler labeler;
@@ -203,8 +204,12 @@
HistogramTimerScope timer(rate);
// Compile the code.
- Handle<Code> code = MakeCode(lit, script, context, is_eval,
- Handle<SharedFunctionInfo>::null());
+ Handle<Code> code = MakeCode(lit,
+ script,
+ context,
+ is_eval,
+ Handle<SharedFunctionInfo>::null(),
+ Handle<Object>::null()); // No receiver.
// Check for stack-overflow exceptions.
if (code.is_null()) {
@@ -366,6 +371,7 @@
bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
+ Handle<Object> receiver,
int loop_nesting) {
CompilationZoneScope zone_scope(DELETE_ON_EXIT);
@@ -405,8 +411,12 @@
HistogramTimerScope timer(&Counters::compile_lazy);
// Compile the code.
- Handle<Code> code = MakeCode(lit, script, Handle<Context>::null(), false,
- shared);
+ Handle<Code> code = MakeCode(lit,
+ script,
+ Handle<Context>::null(),
+ false,
+ shared,
+ receiver);
// Check for stack-overflow exception.
if (code.is_null()) {
@@ -501,7 +511,9 @@
}
} else if (FLAG_always_fast_compiler ||
(FLAG_fast_compiler && !is_run_once)) {
- FastCodeGenSyntaxChecker checker;
+ // Since we are not lazily compiling we do not have a receiver to
+ // specialize for.
+ FastCodeGenSyntaxChecker checker(Handle<Object>::null());
checker.Check(literal);
if (checker.has_supported_syntax()) {
AstLabeler label_nodes;
=======================================
--- /branches/bleeding_edge/src/compiler.h Wed Nov 4 09:59:24 2009
+++ /branches/bleeding_edge/src/compiler.h Fri Jan 29 01:52:51 2010
@@ -70,7 +70,9 @@
// Compile from function info (used for lazy compilation). Returns
// true on success and false if the compilation resulted in a stack
// overflow.
- static bool CompileLazy(Handle<SharedFunctionInfo> shared, int
loop_nesting);
+ static bool CompileLazy(Handle<SharedFunctionInfo> shared,
+ Handle<Object> receiver,
+ int loop_nesting);
// Compile a function boilerplate object (the function is possibly
// lazily compiled). Called recursively from a backend code
=======================================
--- /branches/bleeding_edge/src/debug.cc Mon Jan 25 14:53:18 2010
+++ /branches/bleeding_edge/src/debug.cc Fri Jan 29 01:52:51 2010
@@ -1524,12 +1524,6 @@
thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
thread_local_.last_fp_ = 0;
}
-
-
-bool Debug::EnsureCompiled(Handle<SharedFunctionInfo> shared) {
- if (shared->is_compiled()) return true;
- return CompileLazyShared(shared, CLEAR_EXCEPTION, 0);
-}
// Ensures the debug information is present for shared.
@@ -1538,7 +1532,7 @@
if (HasDebugInfo(shared)) return true;
// Ensure shared in compiled. Return false if this failed.
- if (!EnsureCompiled(shared)) return false;
+ if (!EnsureCompiled(shared, CLEAR_EXCEPTION)) return false;
// Create the debug info object.
Handle<DebugInfo> debug_info = Factory::NewDebugInfo(shared);
=======================================
--- /branches/bleeding_edge/src/debug.h Mon Jan 18 07:48:41 2010
+++ /branches/bleeding_edge/src/debug.h Fri Jan 29 01:52:51 2010
@@ -391,7 +391,6 @@
static void ClearStepOut();
static void ClearStepNext();
// Returns whether the compile succeeded.
- static bool EnsureCompiled(Handle<SharedFunctionInfo> shared);
static void RemoveDebugInfo(Handle<DebugInfo> debug_info);
static void SetAfterBreakTarget(JavaScriptFrame* frame);
static Handle<Object> CheckBreakPoints(Handle<Object> break_point);
=======================================
--- /branches/bleeding_edge/src/fast-codegen.cc Wed Jan 27 07:23:48 2010
+++ /branches/bleeding_edge/src/fast-codegen.cc Fri Jan 29 01:52:51 2010
@@ -50,10 +50,12 @@
void FastCodeGenSyntaxChecker::Check(FunctionLiteral* fun) {
- Scope* scope = fun->scope();
+ // We do not specialize if we do not have a receiver.
+ if (receiver().is_null()) BAILOUT("No receiver");
// We do not support stack or heap slots (both of which require
// allocation).
+ Scope* scope = fun->scope();
if (scope->num_stack_slots() > 0) {
BAILOUT("Function has stack-allocated locals");
}
@@ -245,6 +247,21 @@
if (!prop->key()->IsPropertyName()) {
BAILOUT("Non-named-property assignment");
}
+
+ // We will only specialize for fields on the object itself.
+ // Expression::IsPropertyName implies that the name is a literal
+ // symbol but we do not assume that.
+ Literal* key = prop->key()->AsLiteral();
+ if (key != NULL && key->handle()->IsString()) {
+ Handle<String> name = Handle<String>::cast(key->handle());
+ LookupResult lookup;
+ receiver()->Lookup(*name, &lookup);
+ if (lookup.holder() != *receiver()) BAILOUT("Non-own property
assignment");
+ if (!lookup.type() == FIELD) BAILOUT("Non-field property assignment");
+ } else {
+ UNREACHABLE();
+ BAILOUT("Unexpected non-string-literal property key");
+ }
Visit(expr->value());
}
=======================================
--- /branches/bleeding_edge/src/fast-codegen.h Wed Jan 27 07:23:48 2010
+++ /branches/bleeding_edge/src/fast-codegen.h Fri Jan 29 01:52:51 2010
@@ -37,10 +37,13 @@
class FastCodeGenSyntaxChecker: public AstVisitor {
public:
- FastCodeGenSyntaxChecker() : has_supported_syntax_(true) {}
+ explicit FastCodeGenSyntaxChecker(Handle<Object> receiver)
+ : receiver_(receiver), has_supported_syntax_(true) {
+ }
void Check(FunctionLiteral* fun);
+ Handle<Object> receiver() { return receiver_; }
bool has_supported_syntax() { return has_supported_syntax_; }
private:
@@ -52,6 +55,7 @@
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
+ Handle<Object> receiver_;
bool has_supported_syntax_;
DISALLOW_COPY_AND_ASSIGN(FastCodeGenSyntaxChecker);
=======================================
--- /branches/bleeding_edge/src/handles.cc Thu Jan 21 08:42:41 2010
+++ /branches/bleeding_edge/src/handles.cc Fri Jan 29 01:52:51 2010
@@ -666,34 +666,52 @@
}
-bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
- ClearExceptionFlag flag,
- int loop_nesting) {
+bool EnsureCompiled(Handle<SharedFunctionInfo> shared,
+ ClearExceptionFlag flag) {
+ return shared->is_compiled() || CompileLazyShared(shared, flag);
+}
+
+
+static bool CompileLazyHelper(Handle<SharedFunctionInfo> shared,
+ Handle<Object> receiver,
+ ClearExceptionFlag flag,
+ int loop_nesting) {
// Compile the source information to a code object.
ASSERT(!shared->is_compiled());
- bool result = Compiler::CompileLazy(shared, loop_nesting);
+ bool result = Compiler::CompileLazy(shared, receiver, loop_nesting);
ASSERT(result != Top::has_pending_exception());
if (!result && flag == CLEAR_EXCEPTION) Top::clear_pending_exception();
return result;
}
-bool CompileLazy(Handle<JSFunction> function, ClearExceptionFlag flag) {
+bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
+ ClearExceptionFlag flag) {
+ return CompileLazyHelper(shared, Handle<Object>::null(), flag, 0);
+}
+
+
+bool CompileLazy(Handle<JSFunction> function,
+ Handle<Object> receiver,
+ ClearExceptionFlag flag) {
// Compile the source information to a code object.
Handle<SharedFunctionInfo> shared(function->shared());
- bool result = CompileLazyShared(shared, flag, 0);
+ bool result = CompileLazyHelper(shared, receiver, flag, 0);
LOG(FunctionCreateEvent(*function));
return result;
}
-bool CompileLazyInLoop(Handle<JSFunction> function, ClearExceptionFlag
flag) {
+bool CompileLazyInLoop(Handle<JSFunction> function,
+ Handle<Object> receiver,
+ ClearExceptionFlag flag) {
// Compile the source information to a code object.
Handle<SharedFunctionInfo> shared(function->shared());
- bool result = CompileLazyShared(shared, flag, 1);
+ bool result = CompileLazyHelper(shared, receiver, flag, 1);
LOG(FunctionCreateEvent(*function));
return result;
}
+
OptimizedObjectForAddingMultipleProperties::
OptimizedObjectForAddingMultipleProperties(Handle<JSObject> object,
=======================================
--- /branches/bleeding_edge/src/handles.h Tue Dec 1 02:25:29 2009
+++ /branches/bleeding_edge/src/handles.h Fri Jan 29 01:52:51 2010
@@ -313,12 +313,19 @@
// false if the compilation resulted in a stack overflow.
enum ClearExceptionFlag { KEEP_EXCEPTION, CLEAR_EXCEPTION };
+bool EnsureCompiled(Handle<SharedFunctionInfo> shared,
+ ClearExceptionFlag flag);
+
bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
- ClearExceptionFlag flag,
- int loop_nesting);
-
-bool CompileLazy(Handle<JSFunction> function, ClearExceptionFlag flag);
-bool CompileLazyInLoop(Handle<JSFunction> function, ClearExceptionFlag
flag);
+ ClearExceptionFlag flag);
+
+bool CompileLazy(Handle<JSFunction> function,
+ Handle<Object> receiver,
+ ClearExceptionFlag flag);
+
+bool CompileLazyInLoop(Handle<JSFunction> function,
+ Handle<Object> receiver,
+ ClearExceptionFlag flag);
// Returns the lazy compilation stub for argc arguments.
Handle<Code> ComputeLazyCompile(int argc);
=======================================
--- /branches/bleeding_edge/src/ic.cc Mon Jan 18 06:13:58 2010
+++ /branches/bleeding_edge/src/ic.cc Fri Jan 29 01:52:51 2010
@@ -1302,9 +1302,9 @@
Handle<JSFunction> function =
Handle<JSFunction>(JSFunction::cast(result));
InLoopFlag in_loop = ic.target()->ic_in_loop();
if (in_loop == IN_LOOP) {
- CompileLazyInLoop(function, CLEAR_EXCEPTION);
+ CompileLazyInLoop(function, args.at<Object>(0), CLEAR_EXCEPTION);
} else {
- CompileLazy(function, CLEAR_EXCEPTION);
+ CompileLazy(function, args.at<Object>(0), CLEAR_EXCEPTION);
}
return *function;
}
=======================================
--- /branches/bleeding_edge/src/runtime.cc Mon Jan 25 14:53:18 2010
+++ /branches/bleeding_edge/src/runtime.cc Fri Jan 29 01:52:51 2010
@@ -1405,16 +1405,18 @@
if (!code->IsNull()) {
RUNTIME_ASSERT(code->IsJSFunction());
Handle<JSFunction> fun = Handle<JSFunction>::cast(code);
- SetExpectedNofProperties(target,
fun->shared()->expected_nof_properties());
- if (!fun->is_compiled() && !CompileLazy(fun, KEEP_EXCEPTION)) {
+ Handle<SharedFunctionInfo> shared(fun->shared());
+ SetExpectedNofProperties(target, shared->expected_nof_properties());
+
+ if (!EnsureCompiled(shared, KEEP_EXCEPTION)) {
return Failure::Exception();
}
// Set the code, formal parameter count, and the length of the target
// function.
target->set_code(fun->code());
- target->shared()->set_length(fun->shared()->length());
+ target->shared()->set_length(shared->length());
target->shared()->set_formal_parameter_count(
- fun->shared()->formal_parameter_count());
+ shared->formal_parameter_count());
// Set the source code of the target function to undefined.
// SetCode is only used for built-in constructors like String,
// Array, and Object, and some web code
@@ -4826,12 +4828,8 @@
}
// The function should be compiled for the optimization hints to be
available.
- if (!function->shared()->is_compiled()) {
- CompileLazyShared(Handle<SharedFunctionInfo>(function->shared()),
- CLEAR_EXCEPTION,
- 0);
- LOG(FunctionCreateEvent(*function));
- }
+ Handle<SharedFunctionInfo> shared(function->shared());
+ EnsureCompiled(shared, CLEAR_EXCEPTION);
bool first_allocation = !function->has_initial_map();
Handle<JSObject> result = Factory::NewJSObject(function);
@@ -4870,7 +4868,7 @@
// this means that things called through constructors are never known to
// be in loops. We compile them as if they are in loops here just in
case.
ASSERT(!function->is_compiled());
- if (!CompileLazyInLoop(function, KEEP_EXCEPTION)) {
+ if (!CompileLazyInLoop(function, Handle<Object>::null(),
KEEP_EXCEPTION)) {
return Failure::Exception();
}
@@ -7278,7 +7276,7 @@
if (!done) {
// If the candidate is not compiled compile it to reveal any inner
// functions which might contain the requested source position.
- CompileLazyShared(target, KEEP_EXCEPTION, 0);
+ CompileLazyShared(target, KEEP_EXCEPTION);
}
}
@@ -7864,7 +7862,8 @@
ASSERT(args.length() == 1);
// Get the function and make sure it is compiled.
CONVERT_ARG_CHECKED(JSFunction, func, 0);
- if (!func->is_compiled() && !CompileLazy(func, KEEP_EXCEPTION)) {
+ Handle<SharedFunctionInfo> shared(func->shared());
+ if (!EnsureCompiled(shared, KEEP_EXCEPTION)) {
return Failure::Exception();
}
func->code()->PrintLn();
@@ -7879,10 +7878,11 @@
ASSERT(args.length() == 1);
// Get the function and make sure it is compiled.
CONVERT_ARG_CHECKED(JSFunction, func, 0);
- if (!func->is_compiled() && !CompileLazy(func, KEEP_EXCEPTION)) {
+ Handle<SharedFunctionInfo> shared(func->shared());
+ if (!EnsureCompiled(shared, KEEP_EXCEPTION)) {
return Failure::Exception();
}
- func->shared()->construct_stub()->PrintLn();
+ shared->construct_stub()->PrintLn();
#endif // DEBUG
return Heap::undefined_value();
}
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev