Revision: 15229
Author: [email protected]
Date: Thu Jun 20 03:48:14 2013
Log: Revert r14930 and r14935 temporarily.
This is a temporary revert to track down a potential perf regression
introduced in r14930. The following two changes were reverted:
- "Deprecate HAllocateObject in favor of HAllocate."
- "Added pretenuring support for call new."
[email protected]
BUG=chromium:247504
Review URL: https://codereview.chromium.org/17491002
http://code.google.com/p/v8/source/detail?r=15229
Modified:
/branches/bleeding_edge/src/arm/lithium-arm.cc
/branches/bleeding_edge/src/arm/lithium-arm.h
/branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
/branches/bleeding_edge/src/arm/lithium-codegen-arm.h
/branches/bleeding_edge/src/flag-definitions.h
/branches/bleeding_edge/src/heap.cc
/branches/bleeding_edge/src/hydrogen-instructions.cc
/branches/bleeding_edge/src/hydrogen-instructions.h
/branches/bleeding_edge/src/hydrogen.cc
/branches/bleeding_edge/src/hydrogen.h
/branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
/branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h
/branches/bleeding_edge/src/ia32/lithium-ia32.cc
/branches/bleeding_edge/src/ia32/lithium-ia32.h
/branches/bleeding_edge/src/mips/lithium-codegen-mips.cc
/branches/bleeding_edge/src/mips/lithium-codegen-mips.h
/branches/bleeding_edge/src/mips/lithium-mips.cc
/branches/bleeding_edge/src/mips/lithium-mips.h
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/x64/lithium-codegen-x64.cc
/branches/bleeding_edge/src/x64/lithium-codegen-x64.h
/branches/bleeding_edge/src/x64/lithium-x64.cc
/branches/bleeding_edge/src/x64/lithium-x64.h
/branches/bleeding_edge/test/cctest/test-heap.cc
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc Mon Jun 17 04:11:41 2013
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc Thu Jun 20 03:48:14 2013
@@ -2418,6 +2418,14 @@
LOperand* string = UseRegisterAtStart(instr->value());
return DefineAsRegister(new(zone()) LStringLength(string));
}
+
+
+LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) {
+ info()->MarkAsDeferredCalling();
+ LAllocateObject* result =
+ new(zone()) LAllocateObject(TempRegister(), TempRegister());
+ return AssignPointerMap(DefineAsRegister(result));
+}
LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.h Fri Jun 14 07:33:15 2013
+++ /branches/bleeding_edge/src/arm/lithium-arm.h Thu Jun 20 03:48:14 2013
@@ -49,6 +49,7 @@
#define LITHIUM_CONCRETE_INSTRUCTION_LIST(V) \
V(AccessArgumentsAt) \
V(AddI) \
+ V(AllocateObject) \
V(Allocate) \
V(ApplyArguments) \
V(ArgumentsElements) \
@@ -2444,6 +2445,21 @@
};
+class LAllocateObject: public LTemplateInstruction<1, 1, 2> {
+ public:
+ LAllocateObject(LOperand* temp, LOperand* temp2) {
+ temps_[0] = temp;
+ temps_[1] = temp2;
+ }
+
+ LOperand* temp() { return temps_[0]; }
+ LOperand* temp2() { return temps_[1]; }
+
+ DECLARE_CONCRETE_INSTRUCTION(AllocateObject, "allocate-object")
+ DECLARE_HYDROGEN_ACCESSOR(AllocateObject)
+};
+
+
class LAllocate: public LTemplateInstruction<1, 2, 2> {
public:
LAllocate(LOperand* size, LOperand* temp1, LOperand* temp2) {
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Wed Jun 19
02:38:28 2013
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Thu Jun 20
03:48:14 2013
@@ -5363,6 +5363,80 @@
}
}
}
+
+
+void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
+ class DeferredAllocateObject: public LDeferredCode {
+ public:
+ DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr)
+ : LDeferredCode(codegen), instr_(instr) { }
+ virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_);
}
+ virtual LInstruction* instr() { return instr_; }
+ private:
+ LAllocateObject* instr_;
+ };
+
+ DeferredAllocateObject* deferred =
+ new(zone()) DeferredAllocateObject(this, instr);
+
+ Register result = ToRegister(instr->result());
+ Register scratch = ToRegister(instr->temp());
+ Register scratch2 = ToRegister(instr->temp2());
+ Handle<JSFunction> constructor = instr->hydrogen()->constructor();
+ Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
+ int instance_size = initial_map->instance_size();
+ ASSERT(initial_map->pre_allocated_property_fields() +
+ initial_map->unused_property_fields() -
+ initial_map->inobject_properties() == 0);
+
+ __ Allocate(instance_size, result, scratch, scratch2, deferred->entry(),
+ TAG_OBJECT);
+
+ __ bind(deferred->exit());
+ if (FLAG_debug_code) {
+ Label is_in_new_space;
+ __ JumpIfInNewSpace(result, scratch, &is_in_new_space);
+ __ Abort("Allocated object is not in new-space");
+ __ bind(&is_in_new_space);
+ }
+
+ // Load the initial map.
+ Register map = scratch;
+ __ LoadHeapObject(map, constructor);
+ __ ldr(map, FieldMemOperand(map,
JSFunction::kPrototypeOrInitialMapOffset));
+
+ // Initialize map and fields of the newly allocated object.
+ ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE);
+ __ str(map, FieldMemOperand(result, JSObject::kMapOffset));
+ __ LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex);
+ __ str(scratch, FieldMemOperand(result, JSObject::kElementsOffset));
+ __ str(scratch, FieldMemOperand(result, JSObject::kPropertiesOffset));
+ if (initial_map->inobject_properties() != 0) {
+ __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
+ for (int i = 0; i < initial_map->inobject_properties(); i++) {
+ int property_offset = JSObject::kHeaderSize + i * kPointerSize;
+ __ str(scratch, FieldMemOperand(result, property_offset));
+ }
+ }
+}
+
+
+void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
+ Register result = ToRegister(instr->result());
+ Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
+ int instance_size = initial_map->instance_size();
+
+ // TODO(3095996): Get rid of this. For now, we need to make the
+ // result register contain a valid pointer because it is already
+ // contained in the register pointer map.
+ __ mov(result, Operand::Zero());
+
+ PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
+ __ mov(r0, Operand(Smi::FromInt(instance_size)));
+ __ push(r0);
+ CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr);
+ __ StoreToSafepointRegisterSlot(r0, result);
+}
void LCodeGen::DoAllocate(LAllocate* instr) {
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.h Wed Jun 12
07:22:49 2013
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.h Thu Jun 20
03:48:14 2013
@@ -151,6 +151,7 @@
void DoDeferredRandom(LRandom* instr);
void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
+ void DoDeferredAllocateObject(LAllocateObject* instr);
void DoDeferredAllocate(LAllocate* instr);
void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
Label* map_check);
=======================================
--- /branches/bleeding_edge/src/flag-definitions.h Wed Jun 19 10:00:01 2013
+++ /branches/bleeding_edge/src/flag-definitions.h Thu Jun 20 03:48:14 2013
@@ -195,9 +195,6 @@
true,
"Optimize object size, Array shift, DOM strings and string +")
DEFINE_bool(pretenuring, true, "allocate objects in old space")
-// TODO(hpayer): We will remove this flag as soon as we have pretenuring
-// support for specific allocation sites.
-DEFINE_bool(pretenuring_call_new, false, "pretenure call new")
DEFINE_bool(track_fields, true, "track fields with only smi values")
DEFINE_bool(track_double_fields, true, "track fields with double values")
DEFINE_bool(track_heap_object_fields, true, "track fields with heap
values")
=======================================
--- /branches/bleeding_edge/src/heap.cc Wed Jun 19 10:01:43 2013
+++ /branches/bleeding_edge/src/heap.cc Thu Jun 20 03:48:14 2013
@@ -4421,7 +4421,10 @@
ASSERT(map->instance_type() != JS_BUILTINS_OBJECT_TYPE);
// Allocate the backing storage for the properties.
- int prop_size = map->InitialPropertiesLength();
+ int prop_size =
+ map->pre_allocated_property_fields() +
+ map->unused_property_fields() -
+ map->inobject_properties();
ASSERT(prop_size >= 0);
Object* properties;
{ MaybeObject* maybe_properties = AllocateFixedArray(prop_size,
pretenure);
@@ -4458,7 +4461,10 @@
ASSERT(map->instance_type() != JS_BUILTINS_OBJECT_TYPE);
// Allocate the backing storage for the properties.
- int prop_size = map->InitialPropertiesLength();
+ int prop_size =
+ map->pre_allocated_property_fields() +
+ map->unused_property_fields() -
+ map->inobject_properties();
ASSERT(prop_size >= 0);
Object* properties;
{ MaybeObject* maybe_properties = AllocateFixedArray(prop_size);
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.cc Mon Jun 17
08:06:41 2013
+++ /branches/bleeding_edge/src/hydrogen-instructions.cc Thu Jun 20
03:48:14 2013
@@ -3141,6 +3141,11 @@
HType HStringCharFromCode::CalculateInferredType() {
return HType::String();
}
+
+
+HType HAllocateObject::CalculateInferredType() {
+ return HType::JSObject();
+}
HType HAllocate::CalculateInferredType() {
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Fri Jun 14 10:25:03
2013
+++ /branches/bleeding_edge/src/hydrogen-instructions.h Thu Jun 20 03:48:14
2013
@@ -66,6 +66,7 @@
V(AccessArgumentsAt) \
V(Add) \
V(Allocate) \
+ V(AllocateObject) \
V(ApplyArguments) \
V(ArgumentsElements) \
V(ArgumentsLength) \
@@ -4927,6 +4928,48 @@
};
+class HAllocateObject: public HTemplateInstruction<1> {
+ public:
+ HAllocateObject(HValue* context, Handle<JSFunction> constructor)
+ : constructor_(constructor) {
+ SetOperandAt(0, context);
+ set_representation(Representation::Tagged());
+ SetGVNFlag(kChangesNewSpacePromotion);
+ constructor_initial_map_ = constructor->has_initial_map()
+ ? Handle<Map>(constructor->initial_map())
+ : Handle<Map>::null();
+ // If slack tracking finished, the instance size and property counts
+ // remain unchanged so that we can allocate memory for the object.
+ ASSERT(!constructor->shared()->IsInobjectSlackTrackingInProgress());
+ }
+
+ // Maximum instance size for which allocations will be inlined.
+ static const int kMaxSize = 64 * kPointerSize;
+
+ HValue* context() { return OperandAt(0); }
+ Handle<JSFunction> constructor() { return constructor_; }
+ Handle<Map> constructor_initial_map() { return constructor_initial_map_;
}
+
+ virtual Representation RequiredInputRepresentation(int index) {
+ return Representation::Tagged();
+ }
+ virtual Handle<Map> GetMonomorphicJSObjectMap() {
+ ASSERT(!constructor_initial_map_.is_null());
+ return constructor_initial_map_;
+ }
+ virtual HType CalculateInferredType();
+
+ DECLARE_CONCRETE_INSTRUCTION(AllocateObject)
+
+ private:
+ // TODO(svenpanne) Might be safe, but leave it out until we know for
sure.
+ // virtual bool IsDeletable() const { return true; }
+
+ Handle<JSFunction> constructor_;
+ Handle<Map> constructor_initial_map_;
+};
+
+
class HAllocate: public HTemplateInstruction<2> {
public:
enum Flags {
@@ -4944,9 +4987,6 @@
set_representation(Representation::Tagged());
SetGVNFlag(kChangesNewSpacePromotion);
}
-
- // Maximum instance size for which allocations will be inlined.
- static const int kMaxInlineSize = 64 * kPointerSize;
static Flags DefaultFlags() {
return CAN_ALLOCATE_IN_NEW_SPACE;
@@ -4971,14 +5011,6 @@
return Representation::Integer32();
}
}
-
- virtual Handle<Map> GetMonomorphicJSObjectMap() {
- return known_initial_map_;
- }
-
- void set_known_initial_map(Handle<Map> known_initial_map) {
- known_initial_map_ = known_initial_map;
- }
virtual HType CalculateInferredType();
@@ -5014,7 +5046,6 @@
private:
HType type_;
Flags flags_;
- Handle<Map> known_initial_map_;
};
@@ -5058,6 +5089,7 @@
new_space_dominator);
}
if (object != new_space_dominator) return true;
+ if (object->IsAllocateObject()) return false;
if (object->IsAllocate()) {
return !HAllocate::cast(object)->GuaranteedInNewSpace();
}
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc Thu Jun 20 02:19:19 2013
+++ /branches/bleeding_edge/src/hydrogen.cc Thu Jun 20 03:48:14 2013
@@ -8827,8 +8827,7 @@
static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
return constructor->has_initial_map() &&
constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
- constructor->initial_map()->instance_size() <
HAllocate::kMaxInlineSize &&
- constructor->initial_map()->InitialPropertiesLength() == 0;
+ constructor->initial_map()->instance_size() <
HAllocateObject::kMaxSize;
}
@@ -8838,7 +8837,6 @@
ASSERT(current_block()->HasPredecessor());
int argument_count = expr->arguments()->length() + 1; // Plus
constructor.
HValue* context = environment()->LookupContext();
- Factory* factory = isolate()->factory();
if (FLAG_inline_construct &&
expr->IsMonomorphic() &&
@@ -8858,81 +8856,20 @@
constructor->shared()->CompleteInobjectSlackTracking();
}
- // Calculate instance size from initial map of constructor.
- ASSERT(constructor->has_initial_map());
- Handle<Map> initial_map(constructor->initial_map());
- int instance_size = initial_map->instance_size();
- ASSERT(initial_map->InitialPropertiesLength() == 0);
-
- // Allocate an instance of the implicit receiver object.
- HValue* size_in_bytes =
- AddInstruction(new(zone()) HConstant(instance_size));
-
- HAllocate::Flags flags = HAllocate::DefaultFlags();
- if (FLAG_pretenuring_call_new &&
- isolate()->heap()->ShouldGloballyPretenure()) {
- flags = static_cast<HAllocate::Flags>(
- flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
- }
-
- HInstruction* receiver =
- AddInstruction(new(zone()) HAllocate(context,
- size_in_bytes,
- HType::JSObject(),
- flags));
- HAllocate::cast(receiver)->set_known_initial_map(initial_map);
-
- // Load the initial map from the constructor.
- HValue* constructor_value =
- AddInstruction(new(zone()) HConstant(constructor));
- HValue* initial_map_value =
- AddLoad(constructor_value, HObjectAccess::ForJSObjectOffset(
- JSFunction::kPrototypeOrInitialMapOffset));
-
- // Initialize map and fields of the newly allocated object.
- { NoObservableSideEffectsScope no_effects(this);
- ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE);
- AddStore(receiver,
- HObjectAccess::ForJSObjectOffset(JSObject::kMapOffset),
- initial_map_value);
- HValue* empty_fixed_array =
- AddInstruction(new(zone())
HConstant(factory->empty_fixed_array()));
- AddStore(receiver,
-
HObjectAccess::ForJSObjectOffset(JSObject::kPropertiesOffset),
- empty_fixed_array);
- AddStore(receiver,
- HObjectAccess::ForJSObjectOffset(JSObject::kElementsOffset),
- empty_fixed_array);
- if (initial_map->inobject_properties() != 0) {
- HConstant* undefined = graph()->GetConstantUndefined();
- for (int i = 0; i < initial_map->inobject_properties(); i++) {
- int property_offset = JSObject::kHeaderSize + i * kPointerSize;
- AddStore(receiver,
- HObjectAccess::ForJSObjectOffset(property_offset),
- undefined);
- }
- }
- }
-
- // Replace the constructor function with a newly allocated receiver
using
- // the index of the receiver from the top of the expression stack.
+ // Replace the constructor function with a newly allocated receiver.
+ HInstruction* receiver = new(zone()) HAllocateObject(context,
constructor);
+ // Index of the receiver from the top of the expression stack.
const int receiver_index = argument_count - 1;
+ AddInstruction(receiver);
ASSERT(environment()->ExpressionStackAt(receiver_index) == function);
environment()->SetExpressionStackAt(receiver_index, receiver);
if (TryInlineConstruct(expr, receiver)) return;
- // TODO(mstarzinger): For now we remove the previous HAllocate and all
- // corresponding instructions and instead add HPushArgument for the
- // arguments in case inlining failed. What we actually should do is
for
- // inlining to try to build a subgraph without mutating the parent
graph.
- HInstruction* instr = current_block()->last();
- while (instr != initial_map_value) {
- HInstruction* prev_instr = instr->previous();
- instr->DeleteAndReplaceWith(NULL);
- instr = prev_instr;
- }
- initial_map_value->DeleteAndReplaceWith(NULL);
+ // TODO(mstarzinger): For now we remove the previous HAllocateObject
and
+ // add HPushArgument for the arguments in case inlining failed. What
we
+ // actually should do is emit HInvokeFunction on the constructor
instead
+ // of using HCallNew as a fallback.
receiver->DeleteAndReplaceWith(NULL);
check->DeleteAndReplaceWith(NULL);
environment()->SetExpressionStackAt(receiver_index, function);
=======================================
--- /branches/bleeding_edge/src/hydrogen.h Thu Jun 20 02:19:19 2013
+++ /branches/bleeding_edge/src/hydrogen.h Thu Jun 20 03:48:14 2013
@@ -66,6 +66,7 @@
HInstruction* first() const { return first_; }
HInstruction* last() const { return last_; }
void set_last(HInstruction* instr) { last_ = instr; }
+ HInstruction* GetLastInstruction();
HControlInstruction* end() const { return end_; }
HLoopInformation* loop_information() const { return loop_information_; }
const ZoneList<HBasicBlock*>* predecessors() const { return
&predecessors_; }
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Wed Jun 19
02:38:28 2013
+++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Thu Jun 20
03:48:14 2013
@@ -5989,6 +5989,95 @@
}
}
}
+
+
+void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
+ class DeferredAllocateObject: public LDeferredCode {
+ public:
+ DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr)
+ : LDeferredCode(codegen), instr_(instr) { }
+ virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_);
}
+ virtual LInstruction* instr() { return instr_; }
+ private:
+ LAllocateObject* instr_;
+ };
+
+ DeferredAllocateObject* deferred =
+ new(zone()) DeferredAllocateObject(this, instr);
+
+ Register result = ToRegister(instr->result());
+ Register scratch = ToRegister(instr->temp());
+ Handle<JSFunction> constructor = instr->hydrogen()->constructor();
+ Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
+ int instance_size = initial_map->instance_size();
+ ASSERT(initial_map->pre_allocated_property_fields() +
+ initial_map->unused_property_fields() -
+ initial_map->inobject_properties() == 0);
+
+ __ Allocate(instance_size, result, no_reg, scratch, deferred->entry(),
+ TAG_OBJECT);
+
+ __ bind(deferred->exit());
+ if (FLAG_debug_code) {
+ Label is_in_new_space;
+ __ JumpIfInNewSpace(result, scratch, &is_in_new_space);
+ __ Abort("Allocated object is not in new-space");
+ __ bind(&is_in_new_space);
+ }
+
+ // Load the initial map.
+ Register map = scratch;
+ __ LoadHeapObject(scratch, constructor);
+ __ mov(map, FieldOperand(scratch,
JSFunction::kPrototypeOrInitialMapOffset));
+
+ if (FLAG_debug_code) {
+ __ AssertNotSmi(map);
+ __ cmpb(FieldOperand(map, Map::kInstanceSizeOffset),
+ instance_size >> kPointerSizeLog2);
+ __ Assert(equal, "Unexpected instance size");
+ __ cmpb(FieldOperand(map, Map::kPreAllocatedPropertyFieldsOffset),
+ initial_map->pre_allocated_property_fields());
+ __ Assert(equal, "Unexpected pre-allocated property fields count");
+ __ cmpb(FieldOperand(map, Map::kUnusedPropertyFieldsOffset),
+ initial_map->unused_property_fields());
+ __ Assert(equal, "Unexpected unused property fields count");
+ __ cmpb(FieldOperand(map, Map::kInObjectPropertiesOffset),
+ initial_map->inobject_properties());
+ __ Assert(equal, "Unexpected in-object property fields count");
+ }
+
+ // Initialize map and fields of the newly allocated object.
+ ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE);
+ __ mov(FieldOperand(result, JSObject::kMapOffset), map);
+ __ mov(scratch, factory()->empty_fixed_array());
+ __ mov(FieldOperand(result, JSObject::kElementsOffset), scratch);
+ __ mov(FieldOperand(result, JSObject::kPropertiesOffset), scratch);
+ if (initial_map->inobject_properties() != 0) {
+ __ mov(scratch, factory()->undefined_value());
+ for (int i = 0; i < initial_map->inobject_properties(); i++) {
+ int property_offset = JSObject::kHeaderSize + i * kPointerSize;
+ __ mov(FieldOperand(result, property_offset), scratch);
+ }
+ }
+}
+
+
+void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
+ Register result = ToRegister(instr->result());
+ Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
+ int instance_size = initial_map->instance_size();
+
+ // TODO(3095996): Get rid of this. For now, we need to make the
+ // result register contain a valid pointer because it is already
+ // contained in the register pointer map.
+ __ Set(result, Immediate(0));
+
+ PushSafepointRegistersScope scope(this);
+ __ push(Immediate(Smi::FromInt(instance_size)));
+ CallRuntimeFromDeferred(
+ Runtime::kAllocateInNewSpace, 1, instr, instr->context());
+ __ StoreToSafepointRegisterSlot(result, eax);
+}
void LCodeGen::DoAllocate(LAllocate* instr) {
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h Wed Jun 12
07:22:49 2013
+++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h Thu Jun 20
03:48:14 2013
@@ -157,6 +157,7 @@
void DoDeferredRandom(LRandom* instr);
void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
+ void DoDeferredAllocateObject(LAllocateObject* instr);
void DoDeferredAllocate(LAllocate* instr);
void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
Label* map_check);
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc Mon Jun 17 04:11:41
2013
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Thu Jun 20 03:48:14
2013
@@ -2546,6 +2546,15 @@
LOperand* string = UseRegisterAtStart(instr->value());
return DefineAsRegister(new(zone()) LStringLength(string));
}
+
+
+LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) {
+ info()->MarkAsDeferredCalling();
+ LOperand* context = UseAny(instr->context());
+ LOperand* temp = TempRegister();
+ LAllocateObject* result = new(zone()) LAllocateObject(context, temp);
+ return AssignPointerMap(DefineAsRegister(result));
+}
LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.h Fri Jun 14 07:33:15 2013
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.h Thu Jun 20 03:48:14 2013
@@ -44,6 +44,7 @@
V(AccessArgumentsAt) \
V(AddI) \
V(Allocate) \
+ V(AllocateObject) \
V(ApplyArguments) \
V(ArgumentsElements) \
V(ArgumentsLength) \
@@ -2551,6 +2552,21 @@
};
+class LAllocateObject: public LTemplateInstruction<1, 1, 1> {
+ public:
+ LAllocateObject(LOperand* context, LOperand* temp) {
+ inputs_[0] = context;
+ temps_[0] = temp;
+ }
+
+ LOperand* context() { return inputs_[0]; }
+ LOperand* temp() { return temps_[0]; }
+
+ DECLARE_CONCRETE_INSTRUCTION(AllocateObject, "allocate-object")
+ DECLARE_HYDROGEN_ACCESSOR(AllocateObject)
+};
+
+
class LAllocate: public LTemplateInstruction<1, 2, 1> {
public:
LAllocate(LOperand* context, LOperand* size, LOperand* temp) {
=======================================
--- /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc Wed Jun 19
02:38:28 2013
+++ /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc Thu Jun 20
03:48:14 2013
@@ -5291,6 +5291,80 @@
}
}
}
+
+
+void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
+ class DeferredAllocateObject: public LDeferredCode {
+ public:
+ DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr)
+ : LDeferredCode(codegen), instr_(instr) { }
+ virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_);
}
+ virtual LInstruction* instr() { return instr_; }
+ private:
+ LAllocateObject* instr_;
+ };
+
+ DeferredAllocateObject* deferred =
+ new(zone()) DeferredAllocateObject(this, instr);
+
+ Register result = ToRegister(instr->result());
+ Register scratch = ToRegister(instr->temp());
+ Register scratch2 = ToRegister(instr->temp2());
+ Handle<JSFunction> constructor = instr->hydrogen()->constructor();
+ Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
+ int instance_size = initial_map->instance_size();
+ ASSERT(initial_map->pre_allocated_property_fields() +
+ initial_map->unused_property_fields() -
+ initial_map->inobject_properties() == 0);
+
+ __ Allocate(instance_size, result, scratch, scratch2, deferred->entry(),
+ TAG_OBJECT);
+
+ __ bind(deferred->exit());
+ if (FLAG_debug_code) {
+ Label is_in_new_space;
+ __ JumpIfInNewSpace(result, scratch, &is_in_new_space);
+ __ Abort("Allocated object is not in new-space");
+ __ bind(&is_in_new_space);
+ }
+
+ // Load the initial map.
+ Register map = scratch;
+ __ LoadHeapObject(map, constructor);
+ __ lw(map, FieldMemOperand(map,
JSFunction::kPrototypeOrInitialMapOffset));
+
+ // Initialize map and fields of the newly allocated object.
+ ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE);
+ __ sw(map, FieldMemOperand(result, JSObject::kMapOffset));
+ __ LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex);
+ __ sw(scratch, FieldMemOperand(result, JSObject::kElementsOffset));
+ __ sw(scratch, FieldMemOperand(result, JSObject::kPropertiesOffset));
+ if (initial_map->inobject_properties() != 0) {
+ __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
+ for (int i = 0; i < initial_map->inobject_properties(); i++) {
+ int property_offset = JSObject::kHeaderSize + i * kPointerSize;
+ __ sw(scratch, FieldMemOperand(result, property_offset));
+ }
+ }
+}
+
+
+void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
+ Register result = ToRegister(instr->result());
+ Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
+ int instance_size = initial_map->instance_size();
+
+ // TODO(3095996): Get rid of this. For now, we need to make the
+ // result register contain a valid pointer because it is already
+ // contained in the register pointer map.
+ __ mov(result, zero_reg);
+
+ PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
+ __ li(a0, Operand(Smi::FromInt(instance_size)));
+ __ push(a0);
+ CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr);
+ __ StoreToSafepointRegisterSlot(v0, result);
+}
void LCodeGen::DoAllocate(LAllocate* instr) {
=======================================
--- /branches/bleeding_edge/src/mips/lithium-codegen-mips.h Mon Jun 17
08:06:41 2013
+++ /branches/bleeding_edge/src/mips/lithium-codegen-mips.h Thu Jun 20
03:48:14 2013
@@ -149,6 +149,7 @@
void DoDeferredRandom(LRandom* instr);
void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
+ void DoDeferredAllocateObject(LAllocateObject* instr);
void DoDeferredAllocate(LAllocate* instr);
void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
Label* map_check);
=======================================
--- /branches/bleeding_edge/src/mips/lithium-mips.cc Mon Jun 17 08:06:41
2013
+++ /branches/bleeding_edge/src/mips/lithium-mips.cc Thu Jun 20 03:48:14
2013
@@ -2336,6 +2336,14 @@
LOperand* string = UseRegisterAtStart(instr->value());
return DefineAsRegister(new(zone()) LStringLength(string));
}
+
+
+LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) {
+ info()->MarkAsDeferredCalling();
+ LAllocateObject* result =
+ new(zone()) LAllocateObject(TempRegister(), TempRegister());
+ return AssignPointerMap(DefineAsRegister(result));
+}
LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
=======================================
--- /branches/bleeding_edge/src/mips/lithium-mips.h Mon Jun 17 08:06:41 2013
+++ /branches/bleeding_edge/src/mips/lithium-mips.h Thu Jun 20 03:48:14 2013
@@ -49,6 +49,7 @@
#define LITHIUM_CONCRETE_INSTRUCTION_LIST(V) \
V(AccessArgumentsAt) \
V(AddI) \
+ V(AllocateObject) \
V(Allocate) \
V(ApplyArguments) \
V(ArgumentsElements) \
@@ -2417,6 +2418,21 @@
};
+class LAllocateObject: public LTemplateInstruction<1, 1, 2> {
+ public:
+ LAllocateObject(LOperand* temp, LOperand* temp2) {
+ temps_[0] = temp;
+ temps_[1] = temp2;
+ }
+
+ LOperand* temp() { return temps_[0]; }
+ LOperand* temp2() { return temps_[1]; }
+
+ DECLARE_CONCRETE_INSTRUCTION(AllocateObject, "allocate-object")
+ DECLARE_HYDROGEN_ACCESSOR(AllocateObject)
+};
+
+
class LAllocate: public LTemplateInstruction<1, 2, 2> {
public:
LAllocate(LOperand* size, LOperand* temp1, LOperand* temp2) {
=======================================
--- /branches/bleeding_edge/src/objects.h Wed Jun 19 10:00:01 2013
+++ /branches/bleeding_edge/src/objects.h Thu Jun 20 03:48:14 2013
@@ -5475,13 +5475,6 @@
// filtering out properties with the specified attributes.
int NumberOfDescribedProperties(DescriptorFlag which = OWN_DESCRIPTORS,
PropertyAttributes filter = NONE);
-
- // Returns the number of slots allocated for the initial properties
- // backing storage for instances of this map.
- int InitialPropertiesLength() {
- return pre_allocated_property_fields() + unused_property_fields() -
- inobject_properties();
- }
// Casting.
static inline Map* cast(Object* obj);
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Wed Jun 19
02:38:28 2013
+++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Thu Jun 20
03:48:14 2013
@@ -5082,6 +5082,94 @@
}
}
}
+
+
+void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
+ class DeferredAllocateObject: public LDeferredCode {
+ public:
+ DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr)
+ : LDeferredCode(codegen), instr_(instr) { }
+ virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_);
}
+ virtual LInstruction* instr() { return instr_; }
+ private:
+ LAllocateObject* instr_;
+ };
+
+ DeferredAllocateObject* deferred =
+ new(zone()) DeferredAllocateObject(this, instr);
+
+ Register result = ToRegister(instr->result());
+ Register scratch = ToRegister(instr->temp());
+ Handle<JSFunction> constructor = instr->hydrogen()->constructor();
+ Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
+ int instance_size = initial_map->instance_size();
+ ASSERT(initial_map->pre_allocated_property_fields() +
+ initial_map->unused_property_fields() -
+ initial_map->inobject_properties() == 0);
+
+ __ Allocate(instance_size, result, no_reg, scratch, deferred->entry(),
+ TAG_OBJECT);
+
+ __ bind(deferred->exit());
+ if (FLAG_debug_code) {
+ Label is_in_new_space;
+ __ JumpIfInNewSpace(result, scratch, &is_in_new_space);
+ __ Abort("Allocated object is not in new-space");
+ __ bind(&is_in_new_space);
+ }
+
+ // Load the initial map.
+ Register map = scratch;
+ __ LoadHeapObject(scratch, constructor);
+ __ movq(map, FieldOperand(scratch,
JSFunction::kPrototypeOrInitialMapOffset));
+
+ if (FLAG_debug_code) {
+ __ AssertNotSmi(map);
+ __ cmpb(FieldOperand(map, Map::kInstanceSizeOffset),
+ Immediate(instance_size >> kPointerSizeLog2));
+ __ Assert(equal, "Unexpected instance size");
+ __ cmpb(FieldOperand(map, Map::kPreAllocatedPropertyFieldsOffset),
+ Immediate(initial_map->pre_allocated_property_fields()));
+ __ Assert(equal, "Unexpected pre-allocated property fields count");
+ __ cmpb(FieldOperand(map, Map::kUnusedPropertyFieldsOffset),
+ Immediate(initial_map->unused_property_fields()));
+ __ Assert(equal, "Unexpected unused property fields count");
+ __ cmpb(FieldOperand(map, Map::kInObjectPropertiesOffset),
+ Immediate(initial_map->inobject_properties()));
+ __ Assert(equal, "Unexpected in-object property fields count");
+ }
+
+ // Initialize map and fields of the newly allocated object.
+ ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE);
+ __ movq(FieldOperand(result, JSObject::kMapOffset), map);
+ __ LoadRoot(scratch, Heap::kEmptyFixedArrayRootIndex);
+ __ movq(FieldOperand(result, JSObject::kElementsOffset), scratch);
+ __ movq(FieldOperand(result, JSObject::kPropertiesOffset), scratch);
+ if (initial_map->inobject_properties() != 0) {
+ __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
+ for (int i = 0; i < initial_map->inobject_properties(); i++) {
+ int property_offset = JSObject::kHeaderSize + i * kPointerSize;
+ __ movq(FieldOperand(result, property_offset), scratch);
+ }
+ }
+}
+
+
+void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
+ Register result = ToRegister(instr->result());
+ Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
+ int instance_size = initial_map->instance_size();
+
+ // TODO(3095996): Get rid of this. For now, we need to make the
+ // result register contain a valid pointer because it is already
+ // contained in the register pointer map.
+ __ Set(result, 0);
+
+ PushSafepointRegistersScope scope(this);
+ __ Push(Smi::FromInt(instance_size));
+ CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr);
+ __ StoreToSafepointRegisterSlot(result, rax);
+}
void LCodeGen::DoAllocate(LAllocate* instr) {
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.h Wed Jun 12
07:22:49 2013
+++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.h Thu Jun 20
03:48:14 2013
@@ -128,6 +128,7 @@
void DoDeferredRandom(LRandom* instr);
void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
+ void DoDeferredAllocateObject(LAllocateObject* instr);
void DoDeferredAllocate(LAllocate* instr);
void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
Label* map_check);
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.cc Mon Jun 17 04:11:41 2013
+++ /branches/bleeding_edge/src/x64/lithium-x64.cc Thu Jun 20 03:48:14 2013
@@ -2355,6 +2355,13 @@
LOperand* string = UseRegisterAtStart(instr->value());
return DefineAsRegister(new(zone()) LStringLength(string));
}
+
+
+LInstruction* LChunkBuilder::DoAllocateObject(HAllocateObject* instr) {
+ info()->MarkAsDeferredCalling();
+ LAllocateObject* result = new(zone()) LAllocateObject(TempRegister());
+ return AssignPointerMap(DefineAsRegister(result));
+}
LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.h Fri Jun 14 07:33:15 2013
+++ /branches/bleeding_edge/src/x64/lithium-x64.h Thu Jun 20 03:48:14 2013
@@ -50,6 +50,7 @@
V(AccessArgumentsAt) \
V(AddI) \
V(Allocate) \
+ V(AllocateObject) \
V(ApplyArguments) \
V(ArgumentsElements) \
V(ArgumentsLength) \
@@ -2362,6 +2363,19 @@
};
+class LAllocateObject: public LTemplateInstruction<1, 0, 1> {
+ public:
+ explicit LAllocateObject(LOperand* temp) {
+ temps_[0] = temp;
+ }
+
+ LOperand* temp() { return temps_[0]; }
+
+ DECLARE_CONCRETE_INSTRUCTION(AllocateObject, "allocate-object")
+ DECLARE_HYDROGEN_ACCESSOR(AllocateObject)
+};
+
+
class LAllocate: public LTemplateInstruction<1, 1, 1> {
public:
LAllocate(LOperand* size, LOperand* temp) {
=======================================
--- /branches/bleeding_edge/test/cctest/test-heap.cc Wed Jun 19 01:58:09
2013
+++ /branches/bleeding_edge/test/cctest/test-heap.cc Thu Jun 20 03:48:14
2013
@@ -2188,30 +2188,6 @@
}
-TEST(OptimizedPretenuringCallNew) {
- i::FLAG_allow_natives_syntax = true;
- i::FLAG_pretenuring_call_new = true;
- CcTest::InitializeVM();
- if (!i::V8::UseCrankshaft() || i::FLAG_always_opt) return;
- if (i::FLAG_gc_global || i::FLAG_stress_compaction) return;
- v8::HandleScope scope(CcTest::isolate());
- HEAP->SetNewSpaceHighPromotionModeActive(true);
-
- AlwaysAllocateScope always_allocate;
- v8::Local<v8::Value> res = CompileRun(
- "function g() { this.a = 0; }"
- "function f() {"
- " return new g();"
- "};"
- "f(); f(); f();"
- "%OptimizeFunctionOnNextCall(f);"
- "f();");
-
- Handle<JSObject> o =
- v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
- CHECK(HEAP->InOldPointerSpace(*o));
-}
-
static int CountMapTransitions(Map* map) {
return map->transitions()->number_of_transitions();
}
--
--
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.