Author: [EMAIL PROTECTED]
Date: Sun Nov 16 21:50:52 2008
New Revision: 764
Modified:
branches/bleeding_edge/src/ast.h
branches/bleeding_edge/src/codegen-arm.h
branches/bleeding_edge/src/codegen-ia32.cc
branches/bleeding_edge/src/codegen-ia32.h
branches/bleeding_edge/src/codegen.cc
branches/bleeding_edge/src/codegen.h
branches/bleeding_edge/src/compiler.cc
branches/bleeding_edge/src/compiler.h
branches/bleeding_edge/src/debug.cc
branches/bleeding_edge/src/globals.h
branches/bleeding_edge/src/handles.cc
branches/bleeding_edge/src/handles.h
branches/bleeding_edge/src/ic.cc
branches/bleeding_edge/src/objects.cc
branches/bleeding_edge/src/runtime.cc
branches/bleeding_edge/src/stub-cache.cc
branches/bleeding_edge/src/stub-cache.h
Log:
Track loop nesting across function calls when the function
is called through an IC the first time.
Review URL: http://codereview.chromium.org/10746
Modified: branches/bleeding_edge/src/ast.h
==============================================================================
--- branches/bleeding_edge/src/ast.h (original)
+++ branches/bleeding_edge/src/ast.h Sun Nov 16 21:50:52 2008
@@ -1125,6 +1125,7 @@
start_position_(start_position),
end_position_(end_position),
is_expression_(is_expression),
+ loop_nesting_(0),
function_token_position_(RelocInfo::kNoPosition) {
}
@@ -1149,6 +1150,9 @@
bool AllowsLazyCompilation();
+ bool loop_nesting() const { return loop_nesting_; }
+ void set_loop_nesting(int nesting) { loop_nesting_ = nesting; }
+
private:
Handle<String> name_;
Scope* scope_;
@@ -1160,6 +1164,7 @@
int start_position_;
int end_position_;
bool is_expression_;
+ int loop_nesting_;
int function_token_position_;
};
Modified: branches/bleeding_edge/src/codegen-arm.h
==============================================================================
--- branches/bleeding_edge/src/codegen-arm.h (original)
+++ branches/bleeding_edge/src/codegen-arm.h Sun Nov 16 21:50:52 2008
@@ -296,6 +296,7 @@
void ProcessDeclarations(ZoneList<Declaration*>* declarations);
Handle<Code> ComputeCallInitialize(int argc);
+ Handle<Code> ComputeCallInitializeInLoop(int argc);
// Declare global variables and functions in the given array of
// name/value pairs.
Modified: branches/bleeding_edge/src/codegen-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/codegen-ia32.cc (original)
+++ branches/bleeding_edge/src/codegen-ia32.cc Sun Nov 16 21:50:52 2008
@@ -197,6 +197,10 @@
VirtualFrame virtual_frame(this);
frame_ = &virtual_frame;
cc_reg_ = no_condition;
+
+ // Adjust for function-level loop nesting.
+ loop_nesting_ += fun->loop_nesting();
+
{
CodeGenState state(this);
@@ -383,11 +387,15 @@
}
}
+ // Adjust for function-level loop nesting.
+ loop_nesting_ -= fun->loop_nesting();
+
// Code generation state must be reset.
scope_ = NULL;
frame_ = NULL;
ASSERT(!has_cc());
ASSERT(state_ == NULL);
+ ASSERT(loop_nesting() == 0);
}
@@ -2694,14 +2702,15 @@
// patch the stack to use the global proxy as 'this' in the
// invoked function.
LoadGlobal();
-
// Load the arguments.
for (int i = 0; i < args->length(); i++) {
Load(args->at(i));
}
// Setup the receiver register and call the IC initialization code.
- Handle<Code> stub = ComputeCallInitialize(args->length());
+ Handle<Code> stub = (loop_nesting() > 0)
+ ? ComputeCallInitializeInLoop(args->length())
+ : ComputeCallInitialize(args->length());
__ RecordPosition(node->position());
__ call(stub, RelocInfo::CODE_TARGET_CONTEXT);
__ mov(esi, frame_->Context());
@@ -2745,7 +2754,9 @@
for (int i = 0; i < args->length(); i++) Load(args->at(i));
// Call the IC initialization code.
- Handle<Code> stub = ComputeCallInitialize(args->length());
+ Handle<Code> stub = (loop_nesting() > 0)
+ ? ComputeCallInitializeInLoop(args->length())
+ : ComputeCallInitialize(args->length());
__ RecordPosition(node->position());
__ call(stub, RelocInfo::CODE_TARGET);
__ mov(esi, frame_->Context());
Modified: branches/bleeding_edge/src/codegen-ia32.h
==============================================================================
--- branches/bleeding_edge/src/codegen-ia32.h (original)
+++ branches/bleeding_edge/src/codegen-ia32.h Sun Nov 16 21:50:52 2008
@@ -320,6 +320,7 @@
void ProcessDeclarations(ZoneList<Declaration*>* declarations);
Handle<Code> ComputeCallInitialize(int argc);
+ Handle<Code> ComputeCallInitializeInLoop(int argc);
// Declare global variables and functions in the given array of
// name/value pairs.
Modified: branches/bleeding_edge/src/codegen.cc
==============================================================================
--- branches/bleeding_edge/src/codegen.cc (original)
+++ branches/bleeding_edge/src/codegen.cc Sun Nov 16 21:50:52 2008
@@ -242,6 +242,15 @@
}
+Handle<Code> CodeGenerator::ComputeCallInitializeInLoop(int argc) {
+ // Force the creation of the corresponding stub outside loops,
+ // because it will be used when clearing the ICs later - when we
+ // don't know if we're inside a loop or not.
+ ComputeCallInitialize(argc);
+ CALL_HEAP_FUNCTION(StubCache::ComputeCallInitializeInLoop(argc), Code);
+}
+
+
void CodeGenerator::ProcessDeclarations(ZoneList<Declaration*>*
declarations) {
int length = declarations->length();
int globals = 0;
Modified: branches/bleeding_edge/src/codegen.h
==============================================================================
--- branches/bleeding_edge/src/codegen.h (original)
+++ branches/bleeding_edge/src/codegen.h Sun Nov 16 21:50:52 2008
@@ -48,6 +48,7 @@
// CodeGenerator::GenCode
// CodeGenerator::BuildBoilerplate
// CodeGenerator::ComputeCallInitialize
+// CodeGenerator::ComputeCallInitializeInLoop
// CodeGenerator::ProcessDeclarations
// CodeGenerator::DeclareGlobals
// CodeGenerator::CheckForInlineRuntimeCall
Modified: branches/bleeding_edge/src/compiler.cc
==============================================================================
--- branches/bleeding_edge/src/compiler.cc (original)
+++ branches/bleeding_edge/src/compiler.cc Sun Nov 16 21:50:52 2008
@@ -239,7 +239,8 @@
}
-bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared) {
+bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
+ int loop_nesting) {
ZoneScope zone_scope(DELETE_ON_EXIT);
// The VM is in the COMPILER state until exiting this function.
@@ -270,6 +271,9 @@
ASSERT(Top::has_pending_exception());
return false;
}
+
+ // Update the loop nesting in the function literal.
+ lit->set_loop_nesting(loop_nesting);
// Measure how long it takes to do the lazy compilation; only take
// the rest of the function into account to avoid overlap with the
Modified: branches/bleeding_edge/src/compiler.h
==============================================================================
--- branches/bleeding_edge/src/compiler.h (original)
+++ branches/bleeding_edge/src/compiler.h Sun Nov 16 21:50:52 2008
@@ -64,7 +64,7 @@
// 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);
+ static bool CompileLazy(Handle<SharedFunctionInfo> shared, int
loop_nesting);
};
} } // namespace v8::internal
Modified: branches/bleeding_edge/src/debug.cc
==============================================================================
--- branches/bleeding_edge/src/debug.cc (original)
+++ branches/bleeding_edge/src/debug.cc Sun Nov 16 21:50:52 2008
@@ -1135,7 +1135,7 @@
bool Debug::EnsureCompiled(Handle<SharedFunctionInfo> shared) {
if (shared->is_compiled()) return true;
- return CompileLazyShared(shared, CLEAR_EXCEPTION);
+ return CompileLazyShared(shared, CLEAR_EXCEPTION, 0);
}
Modified: branches/bleeding_edge/src/globals.h
==============================================================================
--- branches/bleeding_edge/src/globals.h (original)
+++ branches/bleeding_edge/src/globals.h Sun Nov 16 21:50:52 2008
@@ -282,6 +282,8 @@
enum InlineCacheState {
// Has never been executed.
UNINITIALIZED,
+ // Has never been executed, but is in a loop.
+ UNINITIALIZED_IN_LOOP,
// Has been executed but monomorhic state has been delayed.
PREMONOMORPHIC,
// Has been executed and only one receiver type has been seen.
Modified: branches/bleeding_edge/src/handles.cc
==============================================================================
--- branches/bleeding_edge/src/handles.cc (original)
+++ branches/bleeding_edge/src/handles.cc Sun Nov 16 21:50:52 2008
@@ -422,10 +422,11 @@
bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
- ClearExceptionFlag flag) {
+ ClearExceptionFlag flag,
+ int loop_nesting) {
// Compile the source information to a code object.
ASSERT(!shared->is_compiled());
- bool result = Compiler::CompileLazy(shared);
+ bool result = Compiler::CompileLazy(shared, loop_nesting);
ASSERT(result != Top::has_pending_exception());
if (!result && flag == CLEAR_EXCEPTION) Top::clear_pending_exception();
return result;
@@ -435,9 +436,15 @@
bool CompileLazy(Handle<JSFunction> function, ClearExceptionFlag flag) {
// Compile the source information to a code object.
Handle<SharedFunctionInfo> shared(function->shared());
- return CompileLazyShared(shared, flag);
+ return CompileLazyShared(shared, flag, 0);
}
+
+bool CompileLazyInLoop(Handle<JSFunction> function, ClearExceptionFlag
flag) {
+ // Compile the source information to a code object.
+ Handle<SharedFunctionInfo> shared(function->shared());
+ return CompileLazyShared(shared, flag, 1);
+}
OptimizedObjectForAddingMultipleProperties::
OptimizedObjectForAddingMultipleProperties(Handle<JSObject> object,
Modified: branches/bleeding_edge/src/handles.h
==============================================================================
--- branches/bleeding_edge/src/handles.h (original)
+++ branches/bleeding_edge/src/handles.h Sun Nov 16 21:50:52 2008
@@ -194,9 +194,13 @@
// Do lazy compilation of the given function. Returns true on success
// and false if the compilation resulted in a stack overflow.
enum ClearExceptionFlag { KEEP_EXCEPTION, CLEAR_EXCEPTION };
+
bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
- ClearExceptionFlag flag);
+ ClearExceptionFlag flag,
+ int loop_nesting);
+
bool CompileLazy(Handle<JSFunction> function, ClearExceptionFlag flag);
+bool CompileLazyInLoop(Handle<JSFunction> function, ClearExceptionFlag
flag);
// These deal with lazily loaded properties.
void SetupLazy(Handle<JSFunction> fun,
Modified: branches/bleeding_edge/src/ic.cc
==============================================================================
--- branches/bleeding_edge/src/ic.cc (original)
+++ branches/bleeding_edge/src/ic.cc Sun Nov 16 21:50:52 2008
@@ -41,6 +41,7 @@
static char TransitionMarkFromState(IC::State state) {
switch (state) {
case UNINITIALIZED: return '0';
+ case UNINITIALIZED_IN_LOOP: return 'L';
case PREMONOMORPHIC: return '0';
case MONOMORPHIC: return '1';
case MONOMORPHIC_PROTOTYPE_FAILURE: return '^';
@@ -223,7 +224,8 @@
void CallIC::Clear(Address address, Code* target) {
- if (target->ic_state() == UNINITIALIZED) return;
+ State state = target->ic_state();
+ if (state == UNINITIALIZED || state == UNINITIALIZED_IN_LOOP) return;
Code* code = StubCache::FindCallInitialize(target->arguments_count());
SetTargetAtAddress(address, code);
}
@@ -434,8 +436,9 @@
if (code->IsFailure()) return;
// Patch the call site depending on the state of the cache.
- if (state == UNINITIALIZED || state == PREMONOMORPHIC ||
- state == MONOMORPHIC || state == MONOMORPHIC_PROTOTYPE_FAILURE) {
+ if (state == UNINITIALIZED || state == UNINITIALIZED_IN_LOOP ||
+ state == PREMONOMORPHIC || state == MONOMORPHIC ||
+ state == MONOMORPHIC_PROTOTYPE_FAILURE) {
set_target(Code::cast(code));
}
@@ -1044,7 +1047,17 @@
ASSERT(args.length() == 2);
CallIC ic;
IC::State state = IC::StateFrom(ic.target(), args[0]);
- return ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1));
+ Object* result =
+ ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1));
+ if (state != UNINITIALIZED_IN_LOOP || !result->IsJSFunction())
+ return result;
+
+ // Compile the function with the knowledge that it's called from
+ // within a loop. This enables further optimization of the function.
+ HandleScope scope;
+ Handle<JSFunction> function =
Handle<JSFunction>(JSFunction::cast(result));
+ if (!function->is_compiled()) CompileLazyInLoop(function,
CLEAR_EXCEPTION);
+ return *function;
}
Modified: branches/bleeding_edge/src/objects.cc
==============================================================================
--- branches/bleeding_edge/src/objects.cc (original)
+++ branches/bleeding_edge/src/objects.cc Sun Nov 16 21:50:52 2008
@@ -4603,6 +4603,7 @@
const char* Code::ICState2String(InlineCacheState state) {
switch (state) {
case UNINITIALIZED: return "UNINITIALIZED";
+ case UNINITIALIZED_IN_LOOP: return "UNINITIALIZED_IN_LOOP";
case PREMONOMORPHIC: return "PREMONOMORPHIC";
case MONOMORPHIC: return "MONOMORPHIC";
case MONOMORPHIC_PROTOTYPE_FAILURE:
return "MONOMORPHIC_PROTOTYPE_FAILURE";
Modified: branches/bleeding_edge/src/runtime.cc
==============================================================================
--- branches/bleeding_edge/src/runtime.cc (original)
+++ branches/bleeding_edge/src/runtime.cc Sun Nov 16 21:50:52 2008
@@ -5088,7 +5088,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);
+ CompileLazyShared(target, KEEP_EXCEPTION, 0);
}
}
Modified: branches/bleeding_edge/src/stub-cache.cc
==============================================================================
--- branches/bleeding_edge/src/stub-cache.cc (original)
+++ branches/bleeding_edge/src/stub-cache.cc Sun Nov 16 21:50:52 2008
@@ -543,6 +543,17 @@
}
+Object* StubCache::ComputeCallInitializeInLoop(int argc) {
+ Code::Flags flags =
+ Code::ComputeFlags(Code::CALL_IC, UNINITIALIZED_IN_LOOP, NORMAL,
argc);
+ Object* probe = ProbeCache(flags);
+ if (!probe->IsUndefined()) return probe;
+ StubCompiler compiler;
+ return FillCache(compiler.CompileCallInitialize(flags));
+}
+
+
+
Object* StubCache::ComputeCallPreMonomorphic(int argc) {
Code::Flags flags =
Code::ComputeFlags(Code::CALL_IC, PREMONOMORPHIC, NORMAL, argc);
Modified: branches/bleeding_edge/src/stub-cache.h
==============================================================================
--- branches/bleeding_edge/src/stub-cache.h (original)
+++ branches/bleeding_edge/src/stub-cache.h Sun Nov 16 21:50:52 2008
@@ -148,6 +148,7 @@
// ---
static Object* ComputeCallInitialize(int argc);
+ static Object* ComputeCallInitializeInLoop(int argc);
static Object* ComputeCallPreMonomorphic(int argc);
static Object* ComputeCallNormal(int argc);
static Object* ComputeCallMegamorphic(int argc);
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---