Reviewers: Michael Starzinger, Toon Verwaest,
Message:
Please take a preliminary look, for now only ia32 arch.
This is based on https://chromiumcodereview.appspot.com/12224035/
Is lithium a good place to remove the check, or is it better to do on
hydrogen
level by adjusting HCheckPrototypeMaps?
Description:
Remove prototype checks for leaf maps in optimized code.
Please review this at https://chromiumcodereview.appspot.com/12225099/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files:
M src/ia32/lithium-codegen-ia32.h
M src/ia32/lithium-codegen-ia32.cc
M src/objects.h
M src/objects.cc
Index: src/ia32/lithium-codegen-ia32.cc
diff --git a/src/ia32/lithium-codegen-ia32.cc
b/src/ia32/lithium-codegen-ia32.cc
index
dfced7c221335f060f7c333e02c0ec38bb7516d8..94bba205320002dff531c9356bd87a3d96e87310
100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -5332,9 +5332,21 @@ void
LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
ASSERT(prototypes->length() == maps->length());
- for (int i = 0; i < prototypes->length(); i++) {
- __ LoadHeapObject(reg, prototypes->at(i));
- DoCheckMapCommon(reg, maps->at(i), ALLOW_ELEMENT_TRANSITION_MAPS,
instr);
+ bool can_ommit_checks = true;
+ for (int i = 0; i < maps->length() && can_ommit_checks; i++) {
+ if (maps->at(i)->HasTransitionArray()) can_ommit_checks = false;
+ if (maps->at(i)->is_dictionary_map()) can_ommit_checks = false;
+ }
+ if (can_ommit_checks) {
+ for (int i = 0; i < maps->length(); i++) {
+ prototype_maps_.Add(maps->at(i), info()->zone());
+ }
+ __ LoadHeapObject(reg, prototypes->at(prototypes->length() - 1));
+ } else {
+ for (int i = 0; i < prototypes->length(); i++) {
+ __ LoadHeapObject(reg, prototypes->at(i));
+ DoCheckMapCommon(reg, maps->at(i), ALLOW_ELEMENT_TRANSITION_MAPS,
instr);
+ }
}
}
Index: src/ia32/lithium-codegen-ia32.h
diff --git a/src/ia32/lithium-codegen-ia32.h
b/src/ia32/lithium-codegen-ia32.h
index
283430524c545eb39e22f7a6882f65e51bf2ef7b..6049257cbdf7e5a6704916376388c3e10f009852
100644
--- a/src/ia32/lithium-codegen-ia32.h
+++ b/src/ia32/lithium-codegen-ia32.h
@@ -57,6 +57,7 @@ class LCodeGen BASE_EMBEDDED {
deoptimizations_(4, info->zone()),
jump_table_(4, info->zone()),
deoptimization_literals_(8, info->zone()),
+ prototype_maps_(0, info->zone()),
inlined_function_count_(0),
scope_(info->scope()),
status_(UNUSED),
@@ -394,6 +395,7 @@ class LCodeGen BASE_EMBEDDED {
ZoneList<LEnvironment*> deoptimizations_;
ZoneList<JumpTableEntry> jump_table_;
ZoneList<Handle<Object> > deoptimization_literals_;
+ ZoneList<Handle<Map> > prototype_maps_;
int inlined_function_count_;
Scope* const scope_;
Status status_;
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index
a72585d696948c827a1659fb0d0c201003b9ac11..4a38c1f43141944dd82a4be3f458d1d8f4aa8fb2
100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -3624,6 +3624,7 @@ MaybeObject*
JSObject::NormalizeProperties(PropertyNormalizationMode mode,
}
set_map(new_map);
+
map_of_this->DeoptimizeDependentCodes(DependentCodes::kPrototypeCheckGroup);
set_properties(dictionary);
@@ -5292,6 +5293,7 @@ MaybeObject* Map::CopyDropDescriptors() {
result->set_pre_allocated_property_fields(pre_allocated_property_fields());
result->set_is_shared(false);
result->ClearCodeCache(GetHeap());
+ DeoptimizeDependentCodes(DependentCodes::kPrototypeCheckGroup);
return result;
}
@@ -9555,6 +9557,37 @@ bool DependentCodes::Contains(DependencyGroup group,
Code* code) {
return false;
}
+class DeoptimizeDependentCodeFilter : public OptimizedFunctionFilter {
+ public:
+ virtual bool TakeFunction(JSFunction* function) {
+ return function->code()->marked_for_deoptimization();
+ }
+};
+
+
+void Map::DeoptimizeDependentCodes(DependentCodes::DependencyGroup group) {
+ AssertNoAllocation no_allocation_scope;
+ DependentCodes* codes = dependent_codes();
+ DependentCodes::GroupStartIndexes starts;
+ codes->ComputeGroupStartIndexes(starts);
+ int start = starts[group];
+ int end = starts[group + 1];
+ int number_of_codes = starts[DependentCodes::kGroupCount];
+ if (start == end) return;
+ for (int i = start; i < end; i++) {
+ Code* code = codes->code_at(i);
+ if (!code->marked_for_deoptimization()) {
+ code->set_marked_for_deoptimization(true);
+ }
+ }
+ for (int src = end, dst = start; src < number_of_codes; src++, dst++) {
+ codes->set_code_at(dst, codes->code_at(src));
+ }
+ codes->set_number_of_codes(group, 0);
+ DeoptimizeDependentCodeFilter filter;
+ Deoptimizer::DeoptimizeAllFunctionsWith(&filter);
+}
+
MaybeObject* JSReceiver::SetPrototype(Object* value,
bool skip_hidden_prototypes) {
Index: src/objects.h
diff --git a/src/objects.h b/src/objects.h
index
1f6e7cc0878c87a8630b77f4e05bd40f7d89cc18..130d3a54d9336e426edb36ca06001170b85ce341
100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -4706,7 +4706,10 @@ class DependentCodes: public FixedArray {
// Group of codes that weakly embed this map and depend on being
// deoptimized when the map is garbage collected.
kWeaklyEmbeddedGroup,
- kGroupCount = kWeaklyEmbeddedGroup + 1
+ // Group of codes that omitted prototype check for a prototype with
this map
+ // and depend on being deoptimized when map layout changes.
+ kPrototypeCheckGroup,
+ kGroupCount = kPrototypeCheckGroup + 1
};
// Array for holding the index of the first code object of each group.
// The last element stores the total number of code objects.
@@ -5182,6 +5185,8 @@ class Map: public HeapObject {
inline void AddDependentCode(DependentCodes::DependencyGroup group,
Handle<Code> code);
+ void DeoptimizeDependentCodes(DependentCodes::DependencyGroup group);
+
// Dispatched behavior.
DECLARE_PRINTER(Map)
DECLARE_VERIFIER(Map)
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.