Author: [email protected]
Date: Mon May 25 11:29:02 2009
New Revision: 2046
Modified:
branches/bleeding_edge/src/arm/codegen-arm.cc
branches/bleeding_edge/src/arm/codegen-arm.h
branches/bleeding_edge/src/arm/ic-arm.cc
branches/bleeding_edge/src/arm/stub-cache-arm.cc
branches/bleeding_edge/src/builtins.cc
branches/bleeding_edge/src/code-stubs.cc
branches/bleeding_edge/src/code-stubs.h
branches/bleeding_edge/src/codegen.cc
branches/bleeding_edge/src/globals.h
branches/bleeding_edge/src/ia32/codegen-ia32.cc
branches/bleeding_edge/src/ia32/codegen-ia32.h
branches/bleeding_edge/src/ia32/ic-ia32.cc
branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc
branches/bleeding_edge/src/ic.cc
branches/bleeding_edge/src/ic.h
branches/bleeding_edge/src/objects-inl.h
branches/bleeding_edge/src/objects.cc
branches/bleeding_edge/src/objects.h
branches/bleeding_edge/src/runtime.cc
branches/bleeding_edge/src/stub-cache.cc
branches/bleeding_edge/src/stub-cache.h
Log:
This patch much improves our tracking of whether function is
called from within a loop or not. In the past we lost the
information if a call site went megamorphic before a lazily
compiled callee was called for the first time. Now we track
that correctly (this is an issue that affects richards).
We still don't manage to track the in-loop state through a
constructor call, since constructor calls use LoadICs instead
of CallICs. This issue affects delta-blue. So in this patch
we assume that lazy compilations that don't happen through a
CallIC happen from inside a loop. I have an idea to fix this
but this patch is big enough already.
With our improved tracking of in-loop state I have switched
off the inlining of in-object loads for code that is not in
a loop. This benefits compile speed. One issue is that
eagerly compiled code now doesn't get the in-object loads
inlined. We need to eagerly compile less code to fix this.
Review URL: http://codereview.chromium.org/115744
Modified: branches/bleeding_edge/src/arm/codegen-arm.cc
==============================================================================
--- branches/bleeding_edge/src/arm/codegen-arm.cc (original)
+++ branches/bleeding_edge/src/arm/codegen-arm.cc Mon May 25 11:29:02 2009
@@ -1058,12 +1058,14 @@
class CallFunctionStub: public CodeStub {
public:
- explicit CallFunctionStub(int argc) : argc_(argc) {}
+ CallFunctionStub(int argc, InLoopFlag in_loop)
+ : argc_(argc), in_loop_(in_loop) {}
void Generate(MacroAssembler* masm);
private:
int argc_;
+ InLoopFlag in_loop_;
#if defined(DEBUG)
void Print() { PrintF("CallFunctionStub (argc %d)\n", argc_); }
@@ -1071,6 +1073,7 @@
Major MajorKey() { return CallFunction; }
int MinorKey() { return argc_; }
+ InLoopFlag InLoop() { return in_loop_; }
};
@@ -1088,7 +1091,8 @@
CodeForSourcePosition(position);
// Use the shared code stub to call the function.
- CallFunctionStub call_function(arg_count);
+ InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
+ CallFunctionStub call_function(arg_count, in_loop);
frame_->CallStub(&call_function, arg_count + 1);
// Restore context and pop function from the stack.
@@ -3051,7 +3055,8 @@
}
// Setup the receiver register and call the IC initialization code.
- Handle<Code> stub = ComputeCallInitialize(arg_count);
+ InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
+ Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop);
CodeForSourcePosition(node->position());
frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT,
arg_count + 1);
@@ -3102,7 +3107,8 @@
}
// Set the receiver register and call the IC initialization code.
- Handle<Code> stub = ComputeCallInitialize(arg_count);
+ InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
+ Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop);
CodeForSourcePosition(node->position());
frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
__ ldr(cp, frame_->Context());
@@ -3200,7 +3206,8 @@
// Call the function.
CodeForSourcePosition(node->position());
- CallFunctionStub call_function(arg_count);
+ InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
+ CallFunctionStub call_function(arg_count, in_loop);
frame_->CallStub(&call_function, arg_count + 1);
__ ldr(cp, frame_->Context());
@@ -3462,7 +3469,8 @@
if (function == NULL) {
// Call the JS runtime function.
- Handle<Code> stub = ComputeCallInitialize(arg_count);
+ InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
+ Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop);
frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET, arg_count + 1);
__ ldr(cp, frame_->Context());
frame_->Drop();
Modified: branches/bleeding_edge/src/arm/codegen-arm.h
==============================================================================
--- branches/bleeding_edge/src/arm/codegen-arm.h (original)
+++ branches/bleeding_edge/src/arm/codegen-arm.h Mon May 25 11:29:02 2009
@@ -206,6 +206,8 @@
JumpTarget* true_target() const { return state_->true_target(); }
JumpTarget* false_target() const { return state_->false_target(); }
+ // We don't track loop nesting level on ARM yet.
+ int loop_nesting() const { return 0; }
// Node visitors.
void VisitStatements(ZoneList<Statement*>* statements);
@@ -318,8 +320,7 @@
Handle<JSFunction> BuildBoilerplate(FunctionLiteral* node);
void ProcessDeclarations(ZoneList<Declaration*>* declarations);
- Handle<Code> ComputeCallInitialize(int argc);
- Handle<Code> ComputeCallInitializeInLoop(int argc);
+ Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
// Declare global variables and functions in the given array of
// name/value pairs.
Modified: branches/bleeding_edge/src/arm/ic-arm.cc
==============================================================================
--- branches/bleeding_edge/src/arm/ic-arm.cc (original)
+++ branches/bleeding_edge/src/arm/ic-arm.cc Mon May 25 11:29:02 2009
@@ -212,7 +212,7 @@
// Probe the stub cache.
Code::Flags flags =
- Code::ComputeFlags(Code::CALL_IC, MONOMORPHIC, NORMAL, argc);
+ Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, MONOMORPHIC, NORMAL,
argc);
StubCache::GenerateProbe(masm, flags, r1, r2, r3);
// If the stub cache probing failed, the receiver might be a value.
@@ -423,7 +423,9 @@
__ ldr(r0, MemOperand(sp, 0));
// Probe the stub cache.
- Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, MONOMORPHIC);
+ Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC,
+ NOT_IN_LOOP,
+ MONOMORPHIC);
StubCache::GenerateProbe(masm, flags, r0, r2, r3);
// Cache miss: Jump to runtime.
@@ -756,7 +758,9 @@
// Get the receiver from the stack and probe the stub cache.
__ ldr(r1, MemOperand(sp));
- Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, MONOMORPHIC);
+ Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
+ NOT_IN_LOOP,
+ MONOMORPHIC);
StubCache::GenerateProbe(masm, flags, r1, r2, r3);
// Cache miss: Jump to runtime.
Modified: branches/bleeding_edge/src/arm/stub-cache-arm.cc
==============================================================================
--- branches/bleeding_edge/src/arm/stub-cache-arm.cc (original)
+++ branches/bleeding_edge/src/arm/stub-cache-arm.cc Mon May 25 11:29:02
2009
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -62,7 +62,7 @@
// Check that the flags match what we're looking for.
__ ldr(offset, FieldMemOperand(offset, Code::kFlagsOffset));
- __ and_(offset, offset, Operand(~Code::kFlagsTypeMask));
+ __ and_(offset, offset, Operand(~Code::kFlagsNotUsedInLookup));
__ cmp(offset, Operand(flags));
__ b(ne, &miss);
@@ -495,7 +495,9 @@
Object* CallStubCompiler::CompileCallField(Object* object,
JSObject* holder,
int index,
- String* name) {
+ String* name,
+ Code::Flags flags) {
+ ASSERT_EQ(FIELD, Code::ExtractTypeFromFlags(flags));
// ----------- S t a t e -------------
// -- lr: return address
// -----------------------------------
@@ -539,14 +541,16 @@
__ Jump(ic, RelocInfo::CODE_TARGET);
// Return the generated code.
- return GetCode(FIELD, name);
+ return GetCodeWithFlags(flags, name);
}
Object* CallStubCompiler::CompileCallConstant(Object* object,
JSObject* holder,
JSFunction* function,
- CheckType check) {
+ CheckType check,
+ Code::Flags flags) {
+ ASSERT_EQ(CONSTANT_FUNCTION, Code::ExtractTypeFromFlags(flags));
// ----------- S t a t e -------------
// -- lr: return address
// -----------------------------------
@@ -664,7 +668,7 @@
if (function->shared()->name()->IsString()) {
function_name = String::cast(function->shared()->name());
}
- return GetCode(CONSTANT_FUNCTION, function_name);
+ return GetCodeWithFlags(flags, function_name);
}
Modified: branches/bleeding_edge/src/builtins.cc
==============================================================================
--- branches/bleeding_edge/src/builtins.cc (original)
+++ branches/bleeding_edge/src/builtins.cc Mon May 25 11:29:02 2009
@@ -666,12 +666,12 @@
Code::ComputeFlags(Code::BUILTIN) \
},
-#define DEF_FUNCTION_PTR_A(name, kind, state) \
- { FUNCTION_ADDR(Generate_##name), \
- NULL, \
- #name, \
- name, \
- Code::ComputeFlags(Code::kind, state) \
+#define DEF_FUNCTION_PTR_A(name, kind, state) \
+ { FUNCTION_ADDR(Generate_##name), \
+ NULL, \
+ #name, \
+ name, \
+ Code::ComputeFlags(Code::kind, NOT_IN_LOOP, state) \
},
// Define array of pointers to generators and C builtin functions.
Modified: branches/bleeding_edge/src/code-stubs.cc
==============================================================================
--- branches/bleeding_edge/src/code-stubs.cc (original)
+++ branches/bleeding_edge/src/code-stubs.cc Mon May 25 11:29:02 2009
@@ -59,7 +59,7 @@
masm.GetCode(&desc);
// Copy the generated code into a heap object, and store the major key.
- Code::Flags flags = Code::ComputeFlags(Code::STUB);
+ Code::Flags flags = Code::ComputeFlags(Code::STUB, InLoop());
Handle<Code> code = Factory::NewCode(desc, NULL, flags,
masm.CodeObject());
code->set_major_key(MajorKey());
Modified: branches/bleeding_edge/src/code-stubs.h
==============================================================================
--- branches/bleeding_edge/src/code-stubs.h (original)
+++ branches/bleeding_edge/src/code-stubs.h Mon May 25 11:29:02 2009
@@ -83,6 +83,10 @@
virtual Major MajorKey() = 0;
virtual int MinorKey() = 0;
+ // The CallFunctionStub needs to override this so it can encode whether a
+ // lazily generated function should be fully optimized or not.
+ virtual InLoopFlag InLoop() { return NOT_IN_LOOP; }
+
// Returns a name for logging/debugging purposes.
virtual const char* GetName() { return MajorName(MajorKey()); }
Modified: branches/bleeding_edge/src/codegen.cc
==============================================================================
--- branches/bleeding_edge/src/codegen.cc (original)
+++ branches/bleeding_edge/src/codegen.cc Mon May 25 11:29:02 2009
@@ -171,7 +171,8 @@
CodeDesc desc;
cgen.masm()->GetCode(&desc);
ZoneScopeInfo sinfo(flit->scope());
- Code::Flags flags = Code::ComputeFlags(Code::FUNCTION);
+ InLoopFlag in_loop = (cgen.loop_nesting() != 0) ? IN_LOOP : NOT_IN_LOOP;
+ Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, in_loop);
Handle<Code> code = Factory::NewCode(desc,
&sinfo,
flags,
@@ -323,17 +324,18 @@
}
-Handle<Code> CodeGenerator::ComputeCallInitialize(int argc) {
- CALL_HEAP_FUNCTION(StubCache::ComputeCallInitialize(argc), Code);
-}
-
-
-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);
+Handle<Code> CodeGenerator::ComputeCallInitialize(
+ int argc,
+ InLoopFlag in_loop) {
+ if (in_loop == IN_LOOP) {
+ // Force the creation of the corresponding stub outside loops,
+ // because it may be used when clearing the ICs later - it is
+ // possible for a series of IC transitions to lose the in-loop
+ // information, and the IC clearing code can't generate a stub
+ // that it needs so we need to ensure it is generated already.
+ ComputeCallInitialize(argc, NOT_IN_LOOP);
+ }
+ CALL_HEAP_FUNCTION(StubCache::ComputeCallInitialize(argc, in_loop),
Code);
}
Modified: branches/bleeding_edge/src/globals.h
==============================================================================
--- branches/bleeding_edge/src/globals.h (original)
+++ branches/bleeding_edge/src/globals.h Mon May 25 11:29:02 2009
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -326,8 +326,6 @@
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.
@@ -339,6 +337,12 @@
// Special states for debug break or step in prepare stubs.
DEBUG_BREAK,
DEBUG_PREPARE_STEP_IN
+};
+
+
+enum InLoopFlag {
+ NOT_IN_LOOP,
+ IN_LOOP
};
Modified: branches/bleeding_edge/src/ia32/codegen-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/ia32/codegen-ia32.cc (original)
+++ branches/bleeding_edge/src/ia32/codegen-ia32.cc Mon May 25 11:29:02 2009
@@ -1653,12 +1653,14 @@
class CallFunctionStub: public CodeStub {
public:
- explicit CallFunctionStub(int argc) : argc_(argc) { }
+ CallFunctionStub(int argc, InLoopFlag in_loop)
+ : argc_(argc), in_loop_(in_loop) { }
void Generate(MacroAssembler* masm);
private:
int argc_;
+ InLoopFlag in_loop_;
#ifdef DEBUG
void Print() { PrintF("CallFunctionStub (args %d)\n", argc_); }
@@ -1666,6 +1668,7 @@
Major MajorKey() { return CallFunction; }
int MinorKey() { return argc_; }
+ InLoopFlag InLoop() { return in_loop_; }
};
@@ -1683,7 +1686,8 @@
CodeForSourcePosition(position);
// Use the shared code stub to call the function.
- CallFunctionStub call_function(arg_count);
+ InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
+ CallFunctionStub call_function(arg_count, in_loop);
Result answer = frame_->CallStub(&call_function, arg_count + 1);
// Restore context and replace function on the stack with the
// result of the stub invocation.
@@ -4217,7 +4221,8 @@
// Call the function.
CodeForSourcePosition(node->position());
- CallFunctionStub call_function(arg_count);
+ InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP;
+ CallFunctionStub call_function(arg_count, in_loop);
result = frame_->CallStub(&call_function, arg_count + 1);
// Restore the context and overwrite the function on the stack with
@@ -4581,9 +4586,10 @@
}
if (function == NULL) {
- // Call the JS runtime function. Pass 0 as the loop nesting depth
- // because we do not handle runtime calls specially in loops.
- Result answer = frame_->CallCallIC(RelocInfo::CODE_TARGET, arg_count,
0);
+ // Call the JS runtime function.
+ Result answer = frame_->CallCallIC(RelocInfo::CODE_TARGET,
+ arg_count,
+ loop_nesting_);
frame_->RestoreContextRegister();
frame_->SetElementAt(0, &answer);
} else {
@@ -5395,9 +5401,13 @@
bool is_global = var != NULL;
ASSERT(!is_global || var->is_global());
- if (is_global || cgen_->scope()->is_global_scope()) {
- // Do not inline the inobject property case for loads from the
- // global object or loads in toplevel code.
+ // Do not inline the inobject property case for loads from the global
+ // object. Also do not inline for unoptimized code. This saves time
+ // in the code generator. Unoptimized code is toplevel code or code
+ // that is not in a loop.
+ if (is_global ||
+ cgen_->scope()->is_global_scope() ||
+ cgen_->loop_nesting() == 0) {
Comment cmnt(masm, "[ Load from named Property");
cgen_->frame()->Push(GetName());
Modified: branches/bleeding_edge/src/ia32/codegen-ia32.h
==============================================================================
--- branches/bleeding_edge/src/ia32/codegen-ia32.h (original)
+++ branches/bleeding_edge/src/ia32/codegen-ia32.h Mon May 25 11:29:02 2009
@@ -348,7 +348,6 @@
void IncrementLoopNesting() { loop_nesting_++; }
void DecrementLoopNesting() { loop_nesting_--; }
-
// Node visitors.
void VisitStatements(ZoneList<Statement*>* statements);
@@ -488,8 +487,7 @@
Handle<JSFunction> BuildBoilerplate(FunctionLiteral* node);
void ProcessDeclarations(ZoneList<Declaration*>* declarations);
- Handle<Code> ComputeCallInitialize(int argc);
- Handle<Code> ComputeCallInitializeInLoop(int argc);
+ Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
// Declare global variables and functions in the given array of
// name/value pairs.
Modified: branches/bleeding_edge/src/ia32/ic-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/ia32/ic-ia32.cc (original)
+++ branches/bleeding_edge/src/ia32/ic-ia32.cc Mon May 25 11:29:02 2009
@@ -427,7 +427,7 @@
// Probe the stub cache.
Code::Flags flags =
- Code::ComputeFlags(Code::CALL_IC, MONOMORPHIC, NORMAL, argc);
+ Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, MONOMORPHIC, NORMAL,
argc);
StubCache::GenerateProbe(masm, flags, edx, ecx, ebx);
// If the stub cache probing failed, the receiver might be a value.
@@ -636,7 +636,9 @@
__ mov(eax, Operand(esp, kPointerSize));
// Probe the stub cache.
- Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, MONOMORPHIC);
+ Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC,
+ NOT_IN_LOOP,
+ MONOMORPHIC);
StubCache::GenerateProbe(masm, flags, eax, ecx, ebx);
// Cache miss: Jump to runtime.
@@ -839,7 +841,9 @@
// Get the receiver from the stack and probe the stub cache.
__ mov(edx, Operand(esp, 4));
- Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, MONOMORPHIC);
+ Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
+ NOT_IN_LOOP,
+ MONOMORPHIC);
StubCache::GenerateProbe(masm, flags, edx, ecx, ebx);
// Cache miss: Jump to runtime.
Modified: branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/ia32/stub-cache-ia32.cc (original)
+++ branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Mon May 25 11:29:02
2009
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -59,7 +59,7 @@
// Check that the flags match what we're looking for.
__ mov(offset, FieldOperand(offset, Code::kFlagsOffset));
- __ and_(offset, ~Code::kFlagsTypeMask);
+ __ and_(offset, ~Code::kFlagsNotUsedInLookup);
__ cmp(offset, flags);
__ j(not_equal, &miss);
@@ -471,7 +471,9 @@
Object* CallStubCompiler::CompileCallField(Object* object,
JSObject* holder,
int index,
- String* name) {
+ String* name,
+ Code::Flags flags) {
+ ASSERT_EQ(FIELD, Code::ExtractTypeFromFlags(flags));
// ----------- S t a t e -------------
// -----------------------------------
Label miss;
@@ -512,14 +514,16 @@
__ jmp(ic, RelocInfo::CODE_TARGET);
// Return the generated code.
- return GetCode(FIELD, name);
+ return GetCodeWithFlags(flags, name);
}
Object* CallStubCompiler::CompileCallConstant(Object* object,
JSObject* holder,
JSFunction* function,
- CheckType check) {
+ CheckType check,
+ Code::Flags flags) {
+ ASSERT_EQ(CONSTANT_FUNCTION, Code::ExtractTypeFromFlags(flags));
// ----------- S t a t e -------------
// -----------------------------------
Label miss;
@@ -634,7 +638,7 @@
if (function->shared()->name()->IsString()) {
function_name = String::cast(function->shared()->name());
}
- return GetCode(CONSTANT_FUNCTION, function_name);
+ return GetCodeWithFlags(flags, function_name);
}
Modified: branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc (original)
+++ branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc Mon May 25
11:29:02 2009
@@ -941,9 +941,8 @@
// Arguments, receiver, and function name are on top of the frame.
// The IC expects them on the stack. It does not drop the function
// name slot (but it does drop the rest).
- Handle<Code> ic = (loop_nesting > 0)
- ? cgen()->ComputeCallInitializeInLoop(arg_count)
- : cgen()->ComputeCallInitialize(arg_count);
+ InLoopFlag in_loop = loop_nesting > 0 ? IN_LOOP : NOT_IN_LOOP;
+ Handle<Code> ic = cgen()->ComputeCallInitialize(arg_count, in_loop);
// Spill args, receiver, and function. The call will drop args and
// receiver.
PrepareForCall(arg_count + 2, arg_count + 1);
Modified: branches/bleeding_edge/src/ic.cc
==============================================================================
--- branches/bleeding_edge/src/ic.cc (original)
+++ branches/bleeding_edge/src/ic.cc Mon May 25 11:29:02 2009
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -39,10 +39,9 @@
namespace internal {
#ifdef DEBUG
-static char TransitionMarkFromState(IC::State state) {
+static const char TransitionMarkFromState(IC::State state) {
switch (state) {
case UNINITIALIZED: return '0';
- case UNINITIALIZED_IN_LOOP: return 'L';
case PREMONOMORPHIC: return 'P';
case MONOMORPHIC: return '1';
case MONOMORPHIC_PROTOTYPE_FAILURE: return '^';
@@ -61,12 +60,14 @@
void IC::TraceIC(const char* type,
Handle<String> name,
State old_state,
- Code* new_target) {
+ Code* new_target,
+ const char* extra_info) {
if (FLAG_trace_ic) {
State new_state = StateFrom(new_target, Heap::undefined_value());
- PrintF("[%s (%c->%c) ", type,
+ PrintF("[%s (%c->%c)%s", type,
TransitionMarkFromState(old_state),
- TransitionMarkFromState(new_state));
+ TransitionMarkFromState(new_state),
+ extra_info);
name->Print();
PrintF("]\n");
}
@@ -227,8 +228,10 @@
void CallIC::Clear(Address address, Code* target) {
State state = target->ic_state();
- if (state == UNINITIALIZED || state == UNINITIALIZED_IN_LOOP) return;
- Code* code = StubCache::FindCallInitialize(target->arguments_count());
+ InLoopFlag in_loop = target->ic_in_loop();
+ if (state == UNINITIALIZED) return;
+ Code* code =
+ StubCache::FindCallInitialize(target->arguments_count(), in_loop);
SetTargetAtAddress(address, code);
}
@@ -391,21 +394,22 @@
// Compute the number of arguments.
int argc = target()->arguments_count();
+ InLoopFlag in_loop = target()->ic_in_loop();
Object* code = NULL;
if (state == UNINITIALIZED) {
// This is the first time we execute this inline cache.
// Set the target to the pre monomorphic stub to delay
// setting the monomorphic state.
- code = StubCache::ComputeCallPreMonomorphic(argc);
+ code = StubCache::ComputeCallPreMonomorphic(argc, in_loop);
} else if (state == MONOMORPHIC) {
- code = StubCache::ComputeCallMegamorphic(argc);
+ code = StubCache::ComputeCallMegamorphic(argc, in_loop);
} else {
// Compute monomorphic stub.
switch (lookup->type()) {
case FIELD: {
int index = lookup->GetFieldIndex();
- code = StubCache::ComputeCallField(argc, *name, *object,
+ code = StubCache::ComputeCallField(argc, in_loop, *name, *object,
lookup->holder(), index);
break;
}
@@ -414,7 +418,7 @@
// call; used for rewriting to monomorphic state and making sure
// that the code stub is in the stub cache.
JSFunction* function = lookup->GetConstantFunction();
- code = StubCache::ComputeCallConstant(argc, *name, *object,
+ code = StubCache::ComputeCallConstant(argc, in_loop, *name,
*object,
lookup->holder(), function);
break;
}
@@ -426,7 +430,7 @@
if (!object->IsJSObject()) return;
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
if (lookup->holder() != *receiver) return;
- code = StubCache::ComputeCallNormal(argc, *name, *receiver);
+ code = StubCache::ComputeCallNormal(argc, in_loop, *name,
*receiver);
break;
}
case INTERCEPTOR: {
@@ -444,14 +448,15 @@
if (code->IsFailure()) return;
// Patch the call site depending on the state of the cache.
- if (state == UNINITIALIZED || state == UNINITIALIZED_IN_LOOP ||
- state == PREMONOMORPHIC || state == MONOMORPHIC ||
+ if (state == UNINITIALIZED ||
+ state == PREMONOMORPHIC ||
+ state == MONOMORPHIC ||
state == MONOMORPHIC_PROTOTYPE_FAILURE) {
set_target(Code::cast(code));
}
#ifdef DEBUG
- TraceIC("CallIC", name, state, target());
+ TraceIC("CallIC", name, state, target(), in_loop ? " (in-loop)" : "");
#endif
}
@@ -1089,14 +1094,27 @@
IC::State state = IC::StateFrom(ic.target(), args[0]);
Object* result =
ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1));
- if (state != UNINITIALIZED_IN_LOOP || !result->IsJSFunction())
+
+ // The first time the inline cache is updated may be the first time the
+ // function it references gets called. If the function was lazily
compiled
+ // then the first call will trigger a compilation. We check for this
case
+ // and we do the compilation immediately, instead of waiting for the stub
+ // currently attached to the JSFunction object to trigger compilation.
We
+ // do this in the case where we know that the inline cache is inside a
loop,
+ // because then we know that we want to optimize the function.
+ if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) {
return result;
+ }
- // Compile the function with the knowledge that it's called from
- // within a loop. This enables further optimization of the function.
+ // Compile now with optimization.
HandleScope scope;
Handle<JSFunction> function =
Handle<JSFunction>(JSFunction::cast(result));
- if (!function->is_compiled()) CompileLazyInLoop(function,
CLEAR_EXCEPTION);
+ InLoopFlag in_loop = ic.target()->ic_in_loop();
+ if (in_loop == IN_LOOP) {
+ CompileLazyInLoop(function, CLEAR_EXCEPTION);
+ } else {
+ CompileLazy(function, CLEAR_EXCEPTION);
+ }
return *function;
}
Modified: branches/bleeding_edge/src/ic.h
==============================================================================
--- branches/bleeding_edge/src/ic.h (original)
+++ branches/bleeding_edge/src/ic.h Mon May 25 11:29:02 2009
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -121,7 +121,8 @@
static void TraceIC(const char* type,
Handle<String> name,
State old_state,
- Code* new_target);
+ Code* new_target,
+ const char* extra_info = "");
#endif
static Failure* TypeError(const char* type,
Modified: branches/bleeding_edge/src/objects-inl.h
==============================================================================
--- branches/bleeding_edge/src/objects-inl.h (original)
+++ branches/bleeding_edge/src/objects-inl.h Mon May 25 11:29:02 2009
@@ -1898,6 +1898,11 @@
}
+InLoopFlag Code::ic_in_loop() {
+ return ExtractICInLoopFromFlags(flags());
+}
+
+
InlineCacheState Code::ic_state() {
InlineCacheState result = ExtractICStateFromFlags(flags());
// Only allow uninitialized or debugger states for non-IC code
@@ -1944,11 +1949,13 @@
Code::Flags Code::ComputeFlags(Kind kind,
+ InLoopFlag in_loop,
InlineCacheState ic_state,
PropertyType type,
int argc) {
// Compute the bit mask.
int bits = kind << kFlagsKindShift;
+ if (in_loop) bits |= kFlagsICInLoopMask;
bits |= ic_state << kFlagsICStateShift;
bits |= type << kFlagsTypeShift;
bits |= argc << kFlagsArgumentsCountShift;
@@ -1956,6 +1963,7 @@
Flags result = static_cast<Flags>(bits);
ASSERT(ExtractKindFromFlags(result) == kind);
ASSERT(ExtractICStateFromFlags(result) == ic_state);
+ ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
ASSERT(ExtractTypeFromFlags(result) == type);
ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
return result;
@@ -1964,8 +1972,9 @@
Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
PropertyType type,
+ InLoopFlag in_loop,
int argc) {
- return ComputeFlags(kind, MONOMORPHIC, type, argc);
+ return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc);
}
@@ -1978,6 +1987,12 @@
InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
int bits = (flags & kFlagsICStateMask) >> kFlagsICStateShift;
return static_cast<InlineCacheState>(bits);
+}
+
+
+InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
+ int bits = (flags & kFlagsICInLoopMask);
+ return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
}
Modified: branches/bleeding_edge/src/objects.cc
==============================================================================
--- branches/bleeding_edge/src/objects.cc (original)
+++ branches/bleeding_edge/src/objects.cc Mon May 25 11:29:02 2009
@@ -4860,7 +4860,6 @@
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/objects.h
==============================================================================
--- branches/bleeding_edge/src/objects.h (original)
+++ branches/bleeding_edge/src/objects.h Mon May 25 11:29:02 2009
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -2253,9 +2253,10 @@
// [flags]: Access to specific code flags.
inline Kind kind();
- inline InlineCacheState ic_state(); // only valid for IC stubs
- inline PropertyType type(); // only valid for monomorphic IC stubs
- inline int arguments_count(); // only valid for call IC stubs
+ inline InlineCacheState ic_state(); // Only valid for IC stubs.
+ inline InLoopFlag ic_in_loop(); // Only valid for IC stubs..
+ inline PropertyType type(); // Only valid for monomorphic IC stubs.
+ inline int arguments_count(); // Only valid for call IC stubs.
// Testers for IC stub kinds.
inline bool is_inline_cache_stub();
@@ -2277,16 +2278,20 @@
// Flags operations.
static inline Flags ComputeFlags(Kind kind,
+ InLoopFlag in_loop = NOT_IN_LOOP,
InlineCacheState ic_state =
UNINITIALIZED,
PropertyType type = NORMAL,
int argc = -1);
- static inline Flags ComputeMonomorphicFlags(Kind kind,
- PropertyType type,
- int argc = -1);
+ static inline Flags ComputeMonomorphicFlags(
+ Kind kind,
+ PropertyType type,
+ InLoopFlag in_loop = NOT_IN_LOOP,
+ int argc = -1);
static inline Kind ExtractKindFromFlags(Flags flags);
static inline InlineCacheState ExtractICStateFromFlags(Flags flags);
+ static inline InLoopFlag ExtractICInLoopFromFlags(Flags flags);
static inline PropertyType ExtractTypeFromFlags(Flags flags);
static inline int ExtractArgumentsCountFromFlags(Flags flags);
static inline Flags RemoveTypeFromFlags(Flags flags);
@@ -2378,14 +2383,19 @@
// Flags layout.
static const int kFlagsICStateShift = 0;
- static const int kFlagsKindShift = 3;
- static const int kFlagsTypeShift = 6;
- static const int kFlagsArgumentsCountShift = 9;
-
- static const int kFlagsICStateMask = 0x00000007; // 000000111
- static const int kFlagsKindMask = 0x00000038; // 000111000
- static const int kFlagsTypeMask = 0x000001C0; // 111000000
- static const int kFlagsArgumentsCountMask = 0xFFFFFE00;
+ static const int kFlagsICInLoopShift = 3;
+ static const int kFlagsKindShift = 4;
+ static const int kFlagsTypeShift = 7;
+ static const int kFlagsArgumentsCountShift = 10;
+
+ static const int kFlagsICStateMask = 0x00000007; // 0000000111
+ static const int kFlagsICInLoopMask = 0x00000008; // 0000001000
+ static const int kFlagsKindMask = 0x00000070; // 0001110000
+ static const int kFlagsTypeMask = 0x00000380; // 1110000000
+ static const int kFlagsArgumentsCountMask = 0xFFFFFC00;
+
+ static const int kFlagsNotUsedInLookup =
+ (kFlagsICInLoopMask | kFlagsTypeMask);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Code);
Modified: branches/bleeding_edge/src/runtime.cc
==============================================================================
--- branches/bleeding_edge/src/runtime.cc (original)
+++ branches/bleeding_edge/src/runtime.cc Mon May 25 11:29:02 2009
@@ -4319,9 +4319,15 @@
}
#endif
- // Compile the target function.
+ // Compile the target function. Here we compile using CompileLazyInLoop
in
+ // order to get the optimized version. This helps code like delta-blue
+ // that calls performance-critical routines through constructors. A
+ // constructor call doesn't use a CallIC, it uses a LoadIC followed by a
+ // direct call. Since the in-loop tracking takes place through CallICs
+ // 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 (!CompileLazy(function, KEEP_EXCEPTION)) {
+ if (!CompileLazyInLoop(function, KEEP_EXCEPTION)) {
return Failure::Exception();
}
Modified: branches/bleeding_edge/src/stub-cache.cc
==============================================================================
--- branches/bleeding_edge/src/stub-cache.cc (original)
+++ branches/bleeding_edge/src/stub-cache.cc Mon May 25 11:29:02 2009
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -370,6 +370,7 @@
Object* StubCache::ComputeCallConstant(int argc,
+ InLoopFlag in_loop,
String* name,
Object* object,
JSObject* holder,
@@ -388,7 +389,10 @@
}
Code::Flags flags =
- Code::ComputeMonomorphicFlags(Code::CALL_IC, CONSTANT_FUNCTION,
argc);
+ Code::ComputeMonomorphicFlags(Code::CALL_IC,
+ CONSTANT_FUNCTION,
+ in_loop,
+ argc);
Object* code = map->FindInCodeCache(name, flags);
if (code->IsUndefined()) {
if (object->IsJSObject()) {
@@ -406,7 +410,7 @@
if (!function->is_compiled()) return Failure::InternalError();
// Compile the stub - only create stubs for fully compiled functions.
CallStubCompiler compiler(argc);
- code = compiler.CompileCallConstant(object, holder, function, check);
+ code = compiler.CompileCallConstant(object, holder, function, check,
flags);
if (code->IsFailure()) return code;
LOG(CodeCreateEvent("CallIC", Code::cast(code), name));
Object* result = map->UpdateCodeCache(name, Code::cast(code));
@@ -417,6 +421,7 @@
Object* StubCache::ComputeCallField(int argc,
+ InLoopFlag in_loop,
String* name,
Object* object,
JSObject* holder,
@@ -431,11 +436,14 @@
object = holder;
}
- Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, FIELD,
argc);
+ Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC,
+ FIELD,
+ in_loop,
+ argc);
Object* code = map->FindInCodeCache(name, flags);
if (code->IsUndefined()) {
CallStubCompiler compiler(argc);
- code = compiler.CompileCallField(object, holder, index, name);
+ code = compiler.CompileCallField(object, holder, index, name, flags);
if (code->IsFailure()) return code;
LOG(CodeCreateEvent("CallIC", Code::cast(code), name));
Object* result = map->UpdateCodeCache(name, Code::cast(code));
@@ -461,7 +469,10 @@
}
Code::Flags flags =
- Code::ComputeMonomorphicFlags(Code::CALL_IC, INTERCEPTOR, argc);
+ Code::ComputeMonomorphicFlags(Code::CALL_IC,
+ INTERCEPTOR,
+ NOT_IN_LOOP,
+ argc);
Object* code = map->FindInCodeCache(name, flags);
if (code->IsUndefined()) {
CallStubCompiler compiler(argc);
@@ -476,9 +487,10 @@
Object* StubCache::ComputeCallNormal(int argc,
+ InLoopFlag in_loop,
String* name,
JSObject* receiver) {
- Object* code = ComputeCallNormal(argc);
+ Object* code = ComputeCallNormal(argc, in_loop);
if (code->IsFailure()) return code;
return Set(name, receiver->map(), Code::cast(code));
}
@@ -523,9 +535,9 @@
}
-Code* StubCache::FindCallInitialize(int argc) {
+Code* StubCache::FindCallInitialize(int argc, InLoopFlag in_loop) {
Code::Flags flags =
- Code::ComputeFlags(Code::CALL_IC, UNINITIALIZED, NORMAL, argc);
+ Code::ComputeFlags(Code::CALL_IC, in_loop, UNINITIALIZED, NORMAL,
argc);
Object* result = ProbeCache(flags);
ASSERT(!result->IsUndefined());
// This might be called during the marking phase of the collector
@@ -534,9 +546,9 @@
}
-Object* StubCache::ComputeCallInitialize(int argc) {
+Object* StubCache::ComputeCallInitialize(int argc, InLoopFlag in_loop) {
Code::Flags flags =
- Code::ComputeFlags(Code::CALL_IC, UNINITIALIZED, NORMAL, argc);
+ Code::ComputeFlags(Code::CALL_IC, in_loop, UNINITIALIZED, NORMAL,
argc);
Object* probe = ProbeCache(flags);
if (!probe->IsUndefined()) return probe;
StubCompiler compiler;
@@ -544,20 +556,9 @@
}
-Object* StubCache::ComputeCallInitializeInLoop(int argc) {
+Object* StubCache::ComputeCallPreMonomorphic(int argc, InLoopFlag in_loop)
{
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);
+ Code::ComputeFlags(Code::CALL_IC, in_loop, PREMONOMORPHIC, NORMAL,
argc);
Object* probe = ProbeCache(flags);
if (!probe->IsUndefined()) return probe;
StubCompiler compiler;
@@ -565,9 +566,9 @@
}
-Object* StubCache::ComputeCallNormal(int argc) {
+Object* StubCache::ComputeCallNormal(int argc, InLoopFlag in_loop) {
Code::Flags flags =
- Code::ComputeFlags(Code::CALL_IC, MONOMORPHIC, NORMAL, argc);
+ Code::ComputeFlags(Code::CALL_IC, in_loop, MONOMORPHIC, NORMAL,
argc);
Object* probe = ProbeCache(flags);
if (!probe->IsUndefined()) return probe;
StubCompiler compiler;
@@ -575,9 +576,9 @@
}
-Object* StubCache::ComputeCallMegamorphic(int argc) {
+Object* StubCache::ComputeCallMegamorphic(int argc, InLoopFlag in_loop) {
Code::Flags flags =
- Code::ComputeFlags(Code::CALL_IC, MEGAMORPHIC, NORMAL, argc);
+ Code::ComputeFlags(Code::CALL_IC, in_loop, MEGAMORPHIC, NORMAL,
argc);
Object* probe = ProbeCache(flags);
if (!probe->IsUndefined()) return probe;
StubCompiler compiler;
@@ -587,7 +588,7 @@
Object* StubCache::ComputeCallMiss(int argc) {
Code::Flags flags =
- Code::ComputeFlags(Code::STUB, MEGAMORPHIC, NORMAL, argc);
+ Code::ComputeFlags(Code::STUB, NOT_IN_LOOP, MEGAMORPHIC, NORMAL,
argc);
Object* probe = ProbeCache(flags);
if (!probe->IsUndefined()) return probe;
StubCompiler compiler;
@@ -598,7 +599,7 @@
#ifdef ENABLE_DEBUGGER_SUPPORT
Object* StubCache::ComputeCallDebugBreak(int argc) {
Code::Flags flags =
- Code::ComputeFlags(Code::CALL_IC, DEBUG_BREAK, NORMAL, argc);
+ Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, DEBUG_BREAK, NORMAL,
argc);
Object* probe = ProbeCache(flags);
if (!probe->IsUndefined()) return probe;
StubCompiler compiler;
@@ -608,7 +609,11 @@
Object* StubCache::ComputeCallDebugPrepareStepIn(int argc) {
Code::Flags flags =
- Code::ComputeFlags(Code::CALL_IC, DEBUG_PREPARE_STEP_IN, NORMAL,
argc);
+ Code::ComputeFlags(Code::CALL_IC,
+ NOT_IN_LOOP,
+ DEBUG_PREPARE_STEP_IN,
+ NORMAL,
+ argc);
Object* probe = ProbeCache(flags);
if (!probe->IsUndefined()) return probe;
StubCompiler compiler;
@@ -619,7 +624,7 @@
Object* StubCache::ComputeLazyCompile(int argc) {
Code::Flags flags =
- Code::ComputeFlags(Code::STUB, UNINITIALIZED, NORMAL, argc);
+ Code::ComputeFlags(Code::STUB, NOT_IN_LOOP, UNINITIALIZED, NORMAL,
argc);
Object* probe = ProbeCache(flags);
if (!probe->IsUndefined()) return probe;
StubCompiler compiler;
@@ -918,7 +923,10 @@
Object* CallStubCompiler::GetCode(PropertyType type, String* name) {
int argc = arguments_.immediate();
- Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, type,
argc);
+ Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC,
+ type,
+ NOT_IN_LOOP,
+ argc);
return GetCodeWithFlags(flags, name);
}
Modified: branches/bleeding_edge/src/stub-cache.h
==============================================================================
--- branches/bleeding_edge/src/stub-cache.h (original)
+++ branches/bleeding_edge/src/stub-cache.h Mon May 25 11:29:02 2009
@@ -128,18 +128,23 @@
// ---
static Object* ComputeCallField(int argc,
+ InLoopFlag in_loop,
String* name,
Object* object,
JSObject* holder,
int index);
static Object* ComputeCallConstant(int argc,
+ InLoopFlag in_loop,
String* name,
Object* object,
JSObject* holder,
JSFunction* function);
- static Object* ComputeCallNormal(int argc, String* name, JSObject*
receiver);
+ static Object* ComputeCallNormal(int argc,
+ InLoopFlag in_loop,
+ String* name,
+ JSObject* receiver);
static Object* ComputeCallInterceptor(int argc,
String* name,
@@ -148,15 +153,14 @@
// ---
- 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);
+ static Object* ComputeCallInitialize(int argc, InLoopFlag in_loop);
+ static Object* ComputeCallPreMonomorphic(int argc, InLoopFlag in_loop);
+ static Object* ComputeCallNormal(int argc, InLoopFlag in_loop);
+ static Object* ComputeCallMegamorphic(int argc, InLoopFlag in_loop);
static Object* ComputeCallMiss(int argc);
// Finds the Code object stored in the Heap::non_monomorphic_cache().
- static Code* FindCallInitialize(int argc);
+ static Code* FindCallInitialize(int argc, InLoopFlag in_loop);
#ifdef ENABLE_DEBUGGER_SUPPORT
static Object* ComputeCallDebugBreak(int argc);
@@ -209,8 +213,12 @@
// 4Gb (and not at all if it isn't).
uint32_t map_low32bits =
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map));
+ // We always set the in_loop bit to zero when generating the lookup
code
+ // so do it here too so the hash codes match.
+ uint32_t iflags =
+ (static_cast<uint32_t>(flags) & ~Code::kFlagsNotUsedInLookup);
// Base the offset on a simple combination of name, flags, and map.
- uint32_t key = (map_low32bits + field) ^ flags;
+ uint32_t key = (map_low32bits + field) ^ iflags;
return key & ((kPrimaryTableSize - 1) << kHeapObjectTagSize);
}
@@ -218,7 +226,11 @@
// Use the seed from the primary cache in the secondary cache.
uint32_t string_low32bits =
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name));
- uint32_t key = seed - string_low32bits + flags;
+ // We always set the in_loop bit to zero when generating the lookup
code
+ // so do it here too so the hash codes match.
+ uint32_t iflags =
+ (static_cast<uint32_t>(flags) & ~Code::kFlagsICInLoopMask);
+ uint32_t key = seed - string_low32bits + iflags;
return key & ((kSecondaryTableSize - 1) << kHeapObjectTagSize);
}
@@ -469,11 +481,13 @@
Object* CompileCallField(Object* object,
JSObject* holder,
int index,
- String* name);
+ String* name,
+ Code::Flags flags);
Object* CompileCallConstant(Object* object,
JSObject* holder,
JSFunction* function,
- CheckType check);
+ CheckType check,
+ Code::Flags flags);
Object* CompileCallInterceptor(Object* object,
JSObject* holder,
String* name);
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---