Revision: 5174
Author: [email protected]
Date: Thu Aug 5 01:37:12 2010
Log: Avoid GC when compiling CallIC stubs.
In rare cases GC could be called from ComputeCallMiss function thus
breaking CallIC::LoadFunction.
Review URL: http://codereview.chromium.org/3047027
http://code.google.com/p/v8/source/detail?r=5174
Modified:
/branches/bleeding_edge/src/arm/stub-cache-arm.cc
/branches/bleeding_edge/src/heap-inl.h
/branches/bleeding_edge/src/heap.cc
/branches/bleeding_edge/src/heap.h
/branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
/branches/bleeding_edge/src/ic.cc
/branches/bleeding_edge/src/stub-cache.cc
/branches/bleeding_edge/src/stub-cache.h
/branches/bleeding_edge/src/x64/stub-cache-x64.cc
=======================================
--- /branches/bleeding_edge/src/arm/stub-cache-arm.cc Wed Jul 14 23:17:45
2010
+++ /branches/bleeding_edge/src/arm/stub-cache-arm.cc Thu Aug 5 01:37:12
2010
@@ -1252,9 +1252,11 @@
}
-void CallStubCompiler::GenerateMissBranch() {
- Handle<Code> ic = ComputeCallMiss(arguments().immediate(), kind_);
- __ Jump(ic, RelocInfo::CODE_TARGET);
+Object* CallStubCompiler::GenerateMissBranch() {
+ Object* obj = StubCache::ComputeCallMiss(arguments().immediate(), kind_);
+ if (obj->IsFailure()) return obj;
+ __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
+ return obj;
}
@@ -1286,7 +1288,8 @@
// Handle call cache miss.
__ bind(&miss);
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(FIELD, name);
@@ -1337,7 +1340,8 @@
// Handle call cache miss.
__ bind(&miss);
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(function);
@@ -1388,7 +1392,8 @@
// Handle call cache miss.
__ bind(&miss);
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(function);
@@ -1561,7 +1566,8 @@
}
__ bind(&miss_in_smi_check);
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(function);
@@ -1610,7 +1616,8 @@
// Handle call cache miss.
__ bind(&miss);
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(INTERCEPTOR, name);
@@ -1694,7 +1701,8 @@
// Handle call cache miss.
__ bind(&miss);
__ IncrementCounter(&Counters::call_global_inline_miss, 1, r1, r3);
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(NORMAL, name);
=======================================
--- /branches/bleeding_edge/src/heap-inl.h Fri Jun 11 10:03:19 2010
+++ /branches/bleeding_edge/src/heap-inl.h Thu Aug 5 01:37:12 2010
@@ -434,6 +434,12 @@
allocation_allowed_ = new_state;
return old;
}
+
+inline bool Heap::allow_gc(bool new_state) {
+ bool old = gc_allowed_;
+ gc_allowed_ = new_state;
+ return old;
+}
#endif
=======================================
--- /branches/bleeding_edge/src/heap.cc Mon Aug 2 08:08:17 2010
+++ /branches/bleeding_edge/src/heap.cc Thu Aug 5 01:37:12 2010
@@ -134,6 +134,7 @@
#ifdef DEBUG
bool Heap::allocation_allowed_ = true;
+bool Heap::gc_allowed_ = true;
int Heap::allocation_timeout_ = 0;
bool Heap::disallow_allocation_failure_ = false;
@@ -319,6 +320,9 @@
void Heap::GarbageCollectionPrologue() {
+#ifdef DEBUG
+ ASSERT(gc_allowed_);
+#endif
TranscendentalCache::Clear();
ClearJSFunctionResultCaches();
gc_count_++;
=======================================
--- /branches/bleeding_edge/src/heap.h Mon Aug 2 08:08:17 2010
+++ /branches/bleeding_edge/src/heap.h Thu Aug 5 01:37:12 2010
@@ -877,6 +877,8 @@
#ifdef DEBUG
static bool IsAllocationAllowed() { return allocation_allowed_; }
static inline bool allow_allocation(bool enable);
+ static bool IsGCAllowed() { return gc_allowed_; }
+ static inline bool allow_gc(bool enable);
static bool disallow_allocation_failure() {
return disallow_allocation_failure_;
@@ -1078,6 +1080,7 @@
#ifdef DEBUG
static bool allocation_allowed_;
+ static bool gc_allowed_;
// If the --gc-interval flag is set to a positive value, this
// variable holds the value indicating the number of allocations
@@ -1675,6 +1678,20 @@
~AssertNoAllocation() {
Heap::allow_allocation(old_state_);
}
+
+ private:
+ bool old_state_;
+};
+
+class AssertNoGC {
+ public:
+ AssertNoGC() {
+ old_state_ = Heap::allow_gc(false);
+ }
+
+ ~AssertNoGC() {
+ Heap::allow_gc(old_state_);
+ }
private:
bool old_state_;
@@ -1702,6 +1719,12 @@
~AssertNoAllocation() { }
};
+class AssertNoGC {
+ public:
+ AssertNoGC() { }
+ ~AssertNoGC() { }
+};
+
class DisableAssertNoAllocation {
public:
DisableAssertNoAllocation() { }
=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Wed Jul 28 02:36:53
2010
+++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Thu Aug 5 01:37:12
2010
@@ -1287,9 +1287,11 @@
}
-void CallStubCompiler::GenerateMissBranch() {
- Handle<Code> ic = ComputeCallMiss(arguments().immediate(), kind_);
- __ jmp(ic, RelocInfo::CODE_TARGET);
+Object* CallStubCompiler::GenerateMissBranch() {
+ Object* obj = StubCache::ComputeCallMiss(arguments().immediate(), kind_);
+ if (obj->IsFailure()) return obj;
+ __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
+ return obj;
}
@@ -1340,7 +1342,8 @@
// Handle call cache miss.
__ bind(&miss);
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(FIELD, name);
@@ -1487,7 +1490,8 @@
}
__ bind(&miss);
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(function);
@@ -1570,7 +1574,8 @@
1);
__ bind(&miss);
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(function);
@@ -1633,8 +1638,8 @@
__ ret((argc + 1) * kPointerSize);
__ bind(&miss);
-
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(function);
@@ -1700,9 +1705,8 @@
__ ret((argc + 1) * kPointerSize);
__ bind(&miss);
- // Restore function name in ecx.
-
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(function);
@@ -1856,7 +1860,8 @@
FreeSpaceForFastApiCall(masm(), eax);
}
__ bind(&miss_in_smi_check);
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(function);
@@ -1920,7 +1925,8 @@
// Handle load cache miss.
__ bind(&miss);
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(INTERCEPTOR, name);
@@ -2005,7 +2011,8 @@
// Handle call cache miss.
__ bind(&miss);
__ IncrementCounter(&Counters::call_global_inline_miss, 1);
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(NORMAL, name);
=======================================
--- /branches/bleeding_edge/src/ic.cc Tue Jul 20 23:59:34 2010
+++ /branches/bleeding_edge/src/ic.cc Thu Aug 5 01:37:12 2010
@@ -501,20 +501,24 @@
// Lookup the property in the object.
LookupResult lookup;
- LookupForRead(*object, *name, &lookup);
-
- if (!lookup.IsProperty()) {
- // If the object does not have the requested property, check which
- // exception we need to throw.
- if (IsContextual(object)) {
- return ReferenceError("not_defined", name);
- }
- return TypeError("undefined_method", object, name);
- }
-
- // Lookup is valid: Update inline cache and stub cache.
- if (FLAG_use_ic) {
- UpdateCaches(&lookup, state, object, name);
+ {
+ AssertNoGC nogc; // GC could invalidate the pointers held in lookup.
+
+ LookupForRead(*object, *name, &lookup);
+
+ if (!lookup.IsProperty()) {
+ // If the object does not have the requested property, check which
+ // exception we need to throw.
+ if (IsContextual(object)) {
+ return ReferenceError("not_defined", name);
+ }
+ return TypeError("undefined_method", object, name);
+ }
+
+ // Lookup is valid: Update inline cache and stub cache.
+ if (FLAG_use_ic) {
+ UpdateCaches(&lookup, state, object, name);
+ }
}
// Get the property.
@@ -787,68 +791,72 @@
// Named lookup in the object.
LookupResult lookup;
- LookupForRead(*object, *name, &lookup);
-
- // If we did not find a property, check if we need to throw an exception.
- if (!lookup.IsProperty()) {
- if (FLAG_strict || IsContextual(object)) {
- return ReferenceError("not_defined", name);
- }
- LOG(SuspectReadEvent(*name, *object));
- }
-
- bool can_be_inlined =
- FLAG_use_ic &&
- state == PREMONOMORPHIC &&
- lookup.IsProperty() &&
- lookup.IsCacheable() &&
- lookup.holder() == *object &&
- lookup.type() == FIELD &&
- !object->IsAccessCheckNeeded();
-
- if (can_be_inlined) {
- Map* map = lookup.holder()->map();
- // Property's index in the properties array. If negative we have
- // an inobject property.
- int index = lookup.GetFieldIndex() - map->inobject_properties();
- if (index < 0) {
- // Index is an offset from the end of the object.
- int offset = map->instance_size() + (index * kPointerSize);
- if (PatchInlinedLoad(address(), map, offset)) {
- set_target(megamorphic_stub());
-#ifdef DEBUG
- if (FLAG_trace_ic) {
- PrintF("[LoadIC : inline patch %s]\n", *name->ToCString());
- }
-#endif
- return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex());
-#ifdef DEBUG
+ {
+ AssertNoGC nogc; // GC could invalidate the pointers held in lookup.
+
+ LookupForRead(*object, *name, &lookup);
+
+ // If we did not find a property, check if we need to throw an
exception.
+ if (!lookup.IsProperty()) {
+ if (FLAG_strict || IsContextual(object)) {
+ return ReferenceError("not_defined", name);
+ }
+ LOG(SuspectReadEvent(*name, *object));
+ }
+
+ bool can_be_inlined =
+ FLAG_use_ic &&
+ state == PREMONOMORPHIC &&
+ lookup.IsProperty() &&
+ lookup.IsCacheable() &&
+ lookup.holder() == *object &&
+ lookup.type() == FIELD &&
+ !object->IsAccessCheckNeeded();
+
+ if (can_be_inlined) {
+ Map* map = lookup.holder()->map();
+ // Property's index in the properties array. If negative we have
+ // an inobject property.
+ int index = lookup.GetFieldIndex() - map->inobject_properties();
+ if (index < 0) {
+ // Index is an offset from the end of the object.
+ int offset = map->instance_size() + (index * kPointerSize);
+ if (PatchInlinedLoad(address(), map, offset)) {
+ set_target(megamorphic_stub());
+ #ifdef DEBUG
+ if (FLAG_trace_ic) {
+ PrintF("[LoadIC : inline patch %s]\n", *name->ToCString());
+ }
+ #endif
+ return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex());
+ #ifdef DEBUG
+ } else {
+ if (FLAG_trace_ic) {
+ PrintF("[LoadIC : no inline patch %s (patching failed)]\n",
+ *name->ToCString());
+ }
+ }
} else {
if (FLAG_trace_ic) {
- PrintF("[LoadIC : no inline patch %s (patching failed)]\n",
+ PrintF("[LoadIC : no inline patch %s (not inobject)]\n",
*name->ToCString());
}
}
} else {
- if (FLAG_trace_ic) {
- PrintF("[LoadIC : no inline patch %s (not inobject)]\n",
- *name->ToCString());
+ if (FLAG_use_ic && state == PREMONOMORPHIC) {
+ if (FLAG_trace_ic) {
+ PrintF("[LoadIC : no inline patch %s (not inlinable)]\n",
+ *name->ToCString());
+ #endif
+ }
}
}
- } else {
- if (FLAG_use_ic && state == PREMONOMORPHIC) {
- if (FLAG_trace_ic) {
- PrintF("[LoadIC : no inline patch %s (not inlinable)]\n",
- *name->ToCString());
-#endif
- }
+
+ // Update inline cache and stub cache.
+ if (FLAG_use_ic) {
+ UpdateCaches(&lookup, state, object, name);
}
}
-
- // Update inline cache and stub cache.
- if (FLAG_use_ic) {
- UpdateCaches(&lookup, state, object, name);
- }
PropertyAttributes attr;
if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
@@ -1037,17 +1045,21 @@
// Named lookup.
LookupResult lookup;
- LookupForRead(*object, *name, &lookup);
-
- // If we did not find a property, check if we need to throw an
exception.
- if (!lookup.IsProperty()) {
- if (FLAG_strict || IsContextual(object)) {
- return ReferenceError("not_defined", name);
- }
- }
-
- if (FLAG_use_ic) {
- UpdateCaches(&lookup, state, object, name);
+ {
+ AssertNoGC nogc; // GC could invalidate the pointers held in lookup.
+
+ LookupForRead(*object, *name, &lookup);
+
+ // If we did not find a property, check if we need to throw an
exception.
+ if (!lookup.IsProperty()) {
+ if (FLAG_strict || IsContextual(object)) {
+ return ReferenceError("not_defined", name);
+ }
+ }
+
+ if (FLAG_use_ic) {
+ UpdateCaches(&lookup, state, object, name);
+ }
}
PropertyAttributes attr;
@@ -1245,6 +1257,8 @@
// Lookup the property locally in the receiver.
if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) {
+ AssertNoGC nogc; // GC could invalidate the pointers held in lookup.
+
LookupResult lookup;
if (LookupForWrite(*receiver, *name, &lookup)) {
@@ -1418,13 +1432,17 @@
return *value;
}
- // Lookup the property locally in the receiver.
- LookupResult lookup;
- receiver->LocalLookup(*name, &lookup);
-
- // Update inline cache and stub cache.
- if (FLAG_use_ic) {
- UpdateCaches(&lookup, state, receiver, name, value);
+ {
+ AssertNoGC nogc; // GC could invalidate the pointers held in lookup.
+
+ // Lookup the property locally in the receiver.
+ LookupResult lookup;
+ receiver->LocalLookup(*name, &lookup);
+
+ // Update inline cache and stub cache.
+ if (FLAG_use_ic) {
+ UpdateCaches(&lookup, state, receiver, name, value);
+ }
}
// Set the property.
=======================================
--- /branches/bleeding_edge/src/stub-cache.cc Tue Jul 13 06:06:33 2010
+++ /branches/bleeding_edge/src/stub-cache.cc Thu Aug 5 01:37:12 2010
@@ -822,13 +822,6 @@
// StubCompiler implementation.
-// Support function for computing call IC miss stubs.
-Handle<Code> ComputeCallMiss(int argc, Code::Kind kind) {
- CALL_HEAP_FUNCTION(StubCache::ComputeCallMiss(argc, kind), Code);
-}
-
-
-
Object* LoadCallbackProperty(Arguments args) {
ASSERT(args[0]->IsJSObject());
ASSERT(args[1]->IsJSObject());
=======================================
--- /branches/bleeding_edge/src/stub-cache.h Tue Jul 13 03:02:11 2010
+++ /branches/bleeding_edge/src/stub-cache.h Thu Aug 5 01:37:12 2010
@@ -336,10 +336,6 @@
Object* KeyedLoadPropertyWithInterceptor(Arguments args);
-// Support function for computing call IC miss stubs.
-Handle<Code> ComputeCallMiss(int argc, Code::Kind kind);
-
-
// The stub compiler compiles stubs for the stub cache.
class StubCompiler BASE_EMBEDDED {
public:
@@ -688,7 +684,9 @@
void GenerateNameCheck(String* name, Label* miss);
- void GenerateMissBranch();
+ // Generates a jump to CallIC miss stub. Returns Failure if the jump
cannot
+ // be generated.
+ Object* GenerateMissBranch();
};
=======================================
--- /branches/bleeding_edge/src/x64/stub-cache-x64.cc Wed Jul 28 02:36:53
2010
+++ /branches/bleeding_edge/src/x64/stub-cache-x64.cc Thu Aug 5 01:37:12
2010
@@ -820,9 +820,11 @@
}
-void CallStubCompiler::GenerateMissBranch() {
- Handle<Code> ic = ComputeCallMiss(arguments().immediate(), kind_);
- __ Jump(ic, RelocInfo::CODE_TARGET);
+Object* CallStubCompiler::GenerateMissBranch() {
+ Object* obj = StubCache::ComputeCallMiss(arguments().immediate(), kind_);
+ if (obj->IsFailure()) return obj;
+ __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
+ return obj;
}
@@ -975,7 +977,8 @@
// Handle call cache miss.
__ bind(&miss_in_smi_check);
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(function);
@@ -1029,7 +1032,8 @@
// Handle call cache miss.
__ bind(&miss);
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(FIELD, name);
@@ -1186,8 +1190,8 @@
}
__ bind(&miss);
-
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(function);
@@ -1270,8 +1274,8 @@
argc + 1,
1);
__ bind(&miss);
-
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(function);
@@ -1357,7 +1361,8 @@
// Handle load cache miss.
__ bind(&miss);
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(INTERCEPTOR, name);
@@ -1442,7 +1447,8 @@
// Handle call cache miss.
__ bind(&miss);
__ IncrementCounter(&Counters::call_global_inline_miss, 1);
- GenerateMissBranch();
+ Object* obj = GenerateMissBranch();
+ if (obj->IsFailure()) return obj;
// Return the generated code.
return GetCode(NORMAL, name);
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev