Revision: 9715
Author: [email protected]
Date: Thu Oct 20 02:38:24 2011
Log: Add flag to trace element kind transitions
Currently only traces transitions from generated ia32 code.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/8357004
http://code.google.com/p/v8/source/detail?r=9715
Modified:
/branches/bleeding_edge/src/code-stubs.cc
/branches/bleeding_edge/src/code-stubs.h
/branches/bleeding_edge/src/flag-definitions.h
/branches/bleeding_edge/src/frames.cc
/branches/bleeding_edge/src/frames.h
/branches/bleeding_edge/src/ia32/code-stubs-ia32.cc
/branches/bleeding_edge/src/objects-inl.h
/branches/bleeding_edge/src/objects-printer.cc
/branches/bleeding_edge/src/objects.cc
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/runtime.h
=======================================
--- /branches/bleeding_edge/src/code-stubs.cc Wed Oct 19 02:04:35 2011
+++ /branches/bleeding_edge/src/code-stubs.cc Thu Oct 20 02:38:24 2011
@@ -418,7 +418,7 @@
void FastElementsConversionStub::Generate(MacroAssembler* masm) {
if (to_ == FAST_ELEMENTS) {
if (from_ == FAST_SMI_ONLY_ELEMENTS) {
- GenerateSmiOnlyToObject(masm);
+ GenerateSmiOnlyToObject(masm, strict_mode_);
} else if (from_ == FAST_DOUBLE_ELEMENTS) {
GenerateDoubleToObject(masm, strict_mode_);
} else {
=======================================
--- /branches/bleeding_edge/src/code-stubs.h Wed Oct 19 04:36:55 2011
+++ /branches/bleeding_edge/src/code-stubs.h Thu Oct 20 02:38:24 2011
@@ -1054,7 +1054,8 @@
}
void Generate(MacroAssembler* masm);
- static void GenerateSmiOnlyToObject(MacroAssembler* masm);
+ static void GenerateSmiOnlyToObject(MacroAssembler* masm,
+ StrictModeFlag strict_mode);
static void GenerateSmiOnlyToDouble(MacroAssembler* masm,
StrictModeFlag strict_mode);
static void GenerateDoubleToObject(MacroAssembler* masm,
=======================================
--- /branches/bleeding_edge/src/flag-definitions.h Wed Oct 12 05:30:30 2011
+++ /branches/bleeding_edge/src/flag-definitions.h Thu Oct 20 02:38:24 2011
@@ -527,6 +527,9 @@
#define FLAG FLAG_READONLY
#endif
+// elements.cc
+DEFINE_bool(trace_elements_transitions, false, "trace elements
transitions")
+
// code-stubs.cc
DEFINE_bool(print_code_stubs, false, "print code stubs")
=======================================
--- /branches/bleeding_edge/src/frames.cc Mon Oct 3 04:13:20 2011
+++ /branches/bleeding_edge/src/frames.cc Thu Oct 20 02:38:24 2011
@@ -709,6 +709,69 @@
IsConstructor());
functions->Add(summary);
}
+
+
+void JavaScriptFrame::PrintTop(FILE* file,
+ bool print_args,
+ bool print_line_number) {
+ // constructor calls
+ HandleScope scope;
+ AssertNoAllocation no_allocation;
+ JavaScriptFrameIterator it;
+ while (!it.done()) {
+ if (it.frame()->is_java_script()) {
+ JavaScriptFrame* frame = it.frame();
+ if (frame->IsConstructor()) PrintF(file, "new ");
+ // function name
+ Object* fun = frame->function();
+ if (fun->IsJSFunction()) {
+ SharedFunctionInfo* shared = JSFunction::cast(fun)->shared();
+ shared->DebugName()->ShortPrint(file);
+ if (print_line_number) {
+ Address pc = frame->pc();
+ Code* code = Code::cast(
+
v8::internal::Isolate::Current()->heap()->FindCodeObject(pc));
+ int source_pos = code->SourcePosition(pc);
+ Object* maybe_script = shared->script();
+ if (maybe_script->IsScript()) {
+ Handle<Script> script(Script::cast(maybe_script));
+ int line = GetScriptLineNumberSafe(script, source_pos) + 1;
+ Object* script_name_raw = script->name();
+ if (script_name_raw->IsString()) {
+ String* script_name = String::cast(script->name());
+ SmartArrayPointer<char> c_script_name =
+ script_name->ToCString(DISALLOW_NULLS,
+ ROBUST_STRING_TRAVERSAL);
+ PrintF(file, " at %s:%d", *c_script_name, line);
+ } else {
+ PrintF(file, "at <unknown>:%d", line);
+ }
+ } else {
+ PrintF(file, " at <unknown>:<unknown>");
+ }
+ }
+ } else {
+ fun->ShortPrint(file);
+ }
+
+ if (print_args) {
+ // function arguments
+ // (we are intentionally only printing the actually
+ // supplied parameters, not all parameters required)
+ PrintF(file, "(this=");
+ frame->receiver()->ShortPrint(file);
+ const int length = frame->ComputeParametersCount();
+ for (int i = 0; i < length; i++) {
+ PrintF(file, ", ");
+ frame->GetParameter(i)->ShortPrint(file);
+ }
+ PrintF(file, ")");
+ }
+ break;
+ }
+ it.Advance();
+ }
+}
void FrameSummary::Print() {
=======================================
--- /branches/bleeding_edge/src/frames.h Wed Oct 12 03:35:42 2011
+++ /branches/bleeding_edge/src/frames.h Thu Oct 20 02:38:24 2011
@@ -511,6 +511,8 @@
ASSERT(frame->is_java_script());
return static_cast<JavaScriptFrame*>(frame);
}
+
+ static void PrintTop(FILE* file, bool print_args, bool
print_line_number);
protected:
inline explicit JavaScriptFrame(StackFrameIterator* iterator);
=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Wed Oct 19 04:36:55
2011
+++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Thu Oct 20 02:38:24
2011
@@ -7023,7 +7023,9 @@
}
-void FastElementsConversionStub::GenerateSmiOnlyToObject(MacroAssembler*
masm) {
+void FastElementsConversionStub::GenerateSmiOnlyToObject(MacroAssembler*
masm,
+ StrictModeFlag
+ strict_mode) {
// ----------- S t a t e -------------
// -- eax : value
// -- ebx : target map
@@ -7032,14 +7034,18 @@
// -- esp[0] : return address
// -----------------------------------
// Set transitioned map.
- __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx);
- __ RecordWriteField(edx,
- HeapObject::kMapOffset,
- ebx,
- edi,
- kDontSaveFPRegs,
- EMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
+ if (FLAG_trace_elements_transitions) {
+ KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
+ } else {
+ __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx);
+ __ RecordWriteField(edx,
+ HeapObject::kMapOffset,
+ ebx,
+ edi,
+ kDontSaveFPRegs,
+ EMIT_REMEMBERED_SET,
+ OMIT_SMI_CHECK);
+ }
}
@@ -7052,30 +7058,33 @@
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
- Label loop, entry, convert_hole, gc_required;
- __ push(eax);
- __ push(ebx);
-
- __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
- __ mov(edi, FieldOperand(edi, FixedArray::kLengthOffset));
-
- // Allocate new FixedDoubleArray.
- // edx: receiver
- // edi: length of source FixedArray (smi-tagged)
- __ lea(esi, Operand(edi, times_4, FixedDoubleArray::kHeaderSize));
- __ AllocateInNewSpace(esi, eax, ebx, no_reg, &gc_required, TAG_OBJECT);
-
- // eax: destination FixedDoubleArray
- // edi: number of elements
- // edx: receiver
- __ mov(FieldOperand(eax, HeapObject::kMapOffset),
- Immediate(masm->isolate()->factory()->fixed_double_array_map()));
- __ mov(FieldOperand(eax, FixedDoubleArray::kLengthOffset), edi);
- __ mov(esi, FieldOperand(edx, JSObject::kElementsOffset));
- // Replace receiver's backing store with newly created FixedDoubleArray.
- __ mov(FieldOperand(edx, JSObject::kElementsOffset), eax);
- __ mov(ebx, eax);
- __ RecordWriteField(edx,
+ if (FLAG_trace_elements_transitions) {
+ KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
+ } else {
+ Label loop, entry, convert_hole, gc_required;
+
+ __ push(eax);
+ __ push(ebx);
+ __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
+ __ mov(edi, FieldOperand(edi, FixedArray::kLengthOffset));
+
+ // Allocate new FixedDoubleArray.
+ // edx: receiver
+ // edi: length of source FixedArray (smi-tagged)
+ __ lea(esi, Operand(edi, times_4, FixedDoubleArray::kHeaderSize));
+ __ AllocateInNewSpace(esi, eax, ebx, no_reg, &gc_required, TAG_OBJECT);
+
+ // eax: destination FixedDoubleArray
+ // edi: number of elements
+ // edx: receiver
+ __ mov(FieldOperand(eax, HeapObject::kMapOffset),
+
Immediate(masm->isolate()->factory()->fixed_double_array_map()));
+ __ mov(FieldOperand(eax, FixedDoubleArray::kLengthOffset), edi);
+ __ mov(esi, FieldOperand(edx, JSObject::kElementsOffset));
+ // Replace receiver's backing store with newly created
FixedDoubleArray.
+ __ mov(FieldOperand(edx, JSObject::kElementsOffset), eax);
+ __ mov(ebx, eax);
+ __ RecordWriteField(edx,
JSObject::kElementsOffset,
ebx,
edi,
@@ -7083,82 +7092,83 @@
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
- __ mov(edi, FieldOperand(esi, FixedArray::kLengthOffset));
-
- // Prepare for conversion loop.
- ExternalReference canonical_the_hole_nan_reference =
- ExternalReference::address_of_the_hole_nan();
- XMMRegister the_hole_nan = xmm1;
- if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope use_sse2(SSE2);
- __ movdbl(the_hole_nan,
- Operand::StaticVariable(canonical_the_hole_nan_reference));
- }
- __ jmp(&entry);
-
- // Call into runtime if GC is required.
- __ bind(&gc_required);
- // Restore registers before jumping into runtime.
- __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
- __ pop(ebx);
- __ pop(eax);
- KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
-
- // Convert and copy elements
- // esi: source FixedArray
- // edi: number of elements to convert/copy
- __ bind(&loop);
- __ sub(edi, Immediate(Smi::FromInt(1)));
- __ mov(ebx, FieldOperand(esi, edi, times_2, FixedArray::kHeaderSize));
- // ebx: current element from source
- // edi: index of current element
- __ JumpIfNotSmi(ebx, &convert_hole);
-
- // Normal smi, convert it to double and store.
- __ SmiUntag(ebx);
- if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope fscope(SSE2);
- __ cvtsi2sd(xmm0, ebx);
- __ movdbl(FieldOperand(eax, edi, times_4,
FixedDoubleArray::kHeaderSize),
- xmm0);
- } else {
- __ push(ebx);
- __ fild_s(Operand(esp, 0));
- __ pop(ebx);
- __ fstp_d(FieldOperand(eax, edi, times_4,
FixedDoubleArray::kHeaderSize));
- }
- __ jmp(&entry);
-
- // Found hole, store hole_nan_as_double instead.
- __ bind(&convert_hole);
- if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope use_sse2(SSE2);
- __ movdbl(FieldOperand(eax, edi, times_4,
FixedDoubleArray::kHeaderSize),
- the_hole_nan);
- } else {
- __ fld_d(Operand::StaticVariable(canonical_the_hole_nan_reference));
- __ fstp_d(FieldOperand(eax, edi, times_4,
FixedDoubleArray::kHeaderSize));
- }
-
- __ bind(&entry);
- __ test(edi, edi);
- __ j(not_zero, &loop);
-
- __ pop(ebx);
- __ pop(eax);
- // eax: value
- // ebx: target map
- // Set transitioned map.
- __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx);
- __ RecordWriteField(edx,
- HeapObject::kMapOffset,
- ebx,
- edi,
- kDontSaveFPRegs,
- EMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
- // Restore esi.
- __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+ __ mov(edi, FieldOperand(esi, FixedArray::kLengthOffset));
+
+ // Prepare for conversion loop.
+ ExternalReference canonical_the_hole_nan_reference =
+ ExternalReference::address_of_the_hole_nan();
+ XMMRegister the_hole_nan = xmm1;
+ if (CpuFeatures::IsSupported(SSE2)) {
+ CpuFeatures::Scope use_sse2(SSE2);
+ __ movdbl(the_hole_nan,
+ Operand::StaticVariable(canonical_the_hole_nan_reference));
+ }
+ __ jmp(&entry);
+
+ // Call into runtime if GC is required.
+ __ bind(&gc_required);
+ // Restore registers before jumping into runtime.
+ __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+ __ pop(ebx);
+ __ pop(eax);
+ KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
+
+ // Convert and copy elements
+ // esi: source FixedArray
+ // edi: number of elements to convert/copy
+ __ bind(&loop);
+ __ sub(edi, Immediate(Smi::FromInt(1)));
+ __ mov(ebx, FieldOperand(esi, edi, times_2, FixedArray::kHeaderSize));
+ // ebx: current element from source
+ // edi: index of current element
+ __ JumpIfNotSmi(ebx, &convert_hole);
+
+ // Normal smi, convert it to double and store.
+ __ SmiUntag(ebx);
+ if (CpuFeatures::IsSupported(SSE2)) {
+ CpuFeatures::Scope fscope(SSE2);
+ __ cvtsi2sd(xmm0, ebx);
+ __ movdbl(FieldOperand(eax, edi, times_4,
FixedDoubleArray::kHeaderSize),
+ xmm0);
+ } else {
+ __ push(ebx);
+ __ fild_s(Operand(esp, 0));
+ __ pop(ebx);
+ __ fstp_d(FieldOperand(eax, edi, times_4,
FixedDoubleArray::kHeaderSize));
+ }
+ __ jmp(&entry);
+
+ // Found hole, store hole_nan_as_double instead.
+ __ bind(&convert_hole);
+ if (CpuFeatures::IsSupported(SSE2)) {
+ CpuFeatures::Scope use_sse2(SSE2);
+ __ movdbl(FieldOperand(eax, edi, times_4,
FixedDoubleArray::kHeaderSize),
+ the_hole_nan);
+ } else {
+ __ fld_d(Operand::StaticVariable(canonical_the_hole_nan_reference));
+ __ fstp_d(FieldOperand(eax, edi, times_4,
FixedDoubleArray::kHeaderSize));
+ }
+
+ __ bind(&entry);
+ __ test(edi, edi);
+ __ j(not_zero, &loop);
+
+ __ pop(ebx);
+ __ pop(eax);
+ // eax: value
+ // ebx: target map
+ // Set transitioned map.
+ __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx);
+ __ RecordWriteField(edx,
+ HeapObject::kMapOffset,
+ ebx,
+ edi,
+ kDontSaveFPRegs,
+ EMIT_REMEMBERED_SET,
+ OMIT_SMI_CHECK);
+ // Restore esi.
+ __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+ }
}
@@ -7171,105 +7181,111 @@
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
- Label loop, entry, convert_hole, gc_required;
- __ push(eax);
- __ push(edx);
- __ push(ebx);
-
- __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
- __ mov(ebx, FieldOperand(edi, FixedDoubleArray::kLengthOffset));
-
- // Allocate new FixedArray.
- // ebx: length of source FixedDoubleArray (smi-tagged)
- __ lea(edi, Operand(ebx, times_2, FixedArray::kHeaderSize));
- __ AllocateInNewSpace(edi, eax, esi, no_reg, &gc_required, TAG_OBJECT);
-
- // eax: destination FixedArray
- // ebx: number of elements
- __ mov(FieldOperand(eax, HeapObject::kMapOffset),
- Immediate(masm->isolate()->factory()->fixed_array_map()));
- __ mov(FieldOperand(eax, FixedArray::kLengthOffset), ebx);
- __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
-
- __ jmp(&entry);
-
- // Call into runtime if GC is required.
- __ bind(&gc_required);
- __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
- __ pop(ebx);
- __ pop(edx);
- __ pop(eax);
- KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
-
- // Box doubles into heap numbers.
- // edi: source FixedDoubleArray
- // eax: destination FixedArray
- __ bind(&loop);
- __ sub(ebx, Immediate(Smi::FromInt(1)));
- // ebx: index of current element (smi-tagged)
- uint32_t offset = FixedDoubleArray::kHeaderSize +
sizeof(kHoleNanLower32);
- __ cmp(FieldOperand(edi, ebx, times_4, offset),
Immediate(kHoleNanUpper32));
- __ j(equal, &convert_hole);
-
- // Non-hole double, copy value into a heap number.
- __ AllocateHeapNumber(edx, esi, no_reg, &gc_required);
- // edx: new heap number
- if (CpuFeatures::IsSupported(SSE2)) {
- CpuFeatures::Scope fscope(SSE2);
- __ movdbl(xmm0,
- FieldOperand(edi, ebx, times_4,
FixedDoubleArray::kHeaderSize));
- __ movdbl(FieldOperand(edx, HeapNumber::kValueOffset), xmm0);
- } else {
- __ mov(esi, FieldOperand(edi, ebx, times_4,
FixedDoubleArray::kHeaderSize));
- __ mov(FieldOperand(edx, HeapNumber::kValueOffset), esi);
- __ mov(esi, FieldOperand(edi, ebx, times_4, offset));
- __ mov(FieldOperand(edx, HeapNumber::kValueOffset + kPointerSize),
esi);
- }
- __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize), edx);
- __ mov(esi, ebx);
- __ RecordWriteArray(eax,
- edx,
- esi,
- kDontSaveFPRegs,
- EMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
- __ jmp(&entry, Label::kNear);
-
- // Replace the-hole NaN with the-hole pointer.
- __ bind(&convert_hole);
- __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize),
- masm->isolate()->factory()->the_hole_value());
-
- __ bind(&entry);
- __ test(ebx, ebx);
- __ j(not_zero, &loop);
-
- __ pop(ebx);
- __ pop(edx);
- // ebx: target map
- // edx: receiver
- // Set transitioned map.
- __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx);
- __ RecordWriteField(edx,
- HeapObject::kMapOffset,
- ebx,
- edi,
- kDontSaveFPRegs,
- EMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
- // Replace receiver's backing store with newly created and filled
FixedArray.
- __ mov(FieldOperand(edx, JSObject::kElementsOffset), eax);
- __ RecordWriteField(edx,
- JSObject::kElementsOffset,
- eax,
- edi,
- kDontSaveFPRegs,
- EMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
-
- // Restore registers.
- __ pop(eax);
- __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+ if (FLAG_trace_elements_transitions) {
+ KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
+ } else {
+ Label loop, entry, convert_hole, gc_required;
+ __ push(eax);
+ __ push(edx);
+ __ push(ebx);
+
+ __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
+ __ mov(ebx, FieldOperand(edi, FixedDoubleArray::kLengthOffset));
+
+ // Allocate new FixedArray.
+ // ebx: length of source FixedDoubleArray (smi-tagged)
+ __ lea(edi, Operand(ebx, times_2, FixedArray::kHeaderSize));
+ __ AllocateInNewSpace(edi, eax, esi, no_reg, &gc_required, TAG_OBJECT);
+
+ // eax: destination FixedArray
+ // ebx: number of elements
+ __ mov(FieldOperand(eax, HeapObject::kMapOffset),
+ Immediate(masm->isolate()->factory()->fixed_array_map()));
+ __ mov(FieldOperand(eax, FixedArray::kLengthOffset), ebx);
+ __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
+
+ __ jmp(&entry);
+
+ // Call into runtime if GC is required.
+ __ bind(&gc_required);
+ __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+ __ pop(ebx);
+ __ pop(edx);
+ __ pop(eax);
+ KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
+
+ // Box doubles into heap numbers.
+ // edi: source FixedDoubleArray
+ // eax: destination FixedArray
+ __ bind(&loop);
+ __ sub(ebx, Immediate(Smi::FromInt(1)));
+ // ebx: index of current element (smi-tagged)
+ uint32_t offset = FixedDoubleArray::kHeaderSize +
sizeof(kHoleNanLower32);
+ __ cmp(FieldOperand(edi, ebx, times_4, offset),
Immediate(kHoleNanUpper32));
+ __ j(equal, &convert_hole);
+
+ // Non-hole double, copy value into a heap number.
+ __ AllocateHeapNumber(edx, esi, no_reg, &gc_required);
+ // edx: new heap number
+ if (CpuFeatures::IsSupported(SSE2)) {
+ CpuFeatures::Scope fscope(SSE2);
+ __ movdbl(xmm0,
+ FieldOperand(edi, ebx, times_4,
FixedDoubleArray::kHeaderSize));
+ __ movdbl(FieldOperand(edx, HeapNumber::kValueOffset), xmm0);
+ } else {
+ __ mov(esi, FieldOperand(edi, ebx, times_4,
+ FixedDoubleArray::kHeaderSize));
+ __ mov(FieldOperand(edx, HeapNumber::kValueOffset), esi);
+ __ mov(esi, FieldOperand(edi, ebx, times_4, offset));
+ __ mov(FieldOperand(edx, HeapNumber::kValueOffset + kPointerSize),
esi);
+ }
+ __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize), edx);
+ __ mov(esi, ebx);
+ __ RecordWriteArray(eax,
+ edx,
+ esi,
+ kDontSaveFPRegs,
+ EMIT_REMEMBERED_SET,
+ OMIT_SMI_CHECK);
+ __ jmp(&entry, Label::kNear);
+
+ // Replace the-hole NaN with the-hole pointer.
+ __ bind(&convert_hole);
+ __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize),
+ masm->isolate()->factory()->the_hole_value());
+
+ __ bind(&entry);
+ __ test(ebx, ebx);
+ __ j(not_zero, &loop);
+
+ __ pop(ebx);
+ __ pop(edx);
+ // ebx: target map
+ // edx: receiver
+ // Set transitioned map.
+ __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx);
+ __ RecordWriteField(edx,
+ HeapObject::kMapOffset,
+ ebx,
+ edi,
+ kDontSaveFPRegs,
+ EMIT_REMEMBERED_SET,
+ OMIT_SMI_CHECK);
+ // Replace receiver's backing store with newly created and filled
+ // FixedArray.
+ __ mov(FieldOperand(edx, JSObject::kElementsOffset), eax);
+ __ RecordWriteField(edx,
+ JSObject::kElementsOffset,
+ eax,
+ edi,
+ kDontSaveFPRegs,
+ EMIT_REMEMBERED_SET,
+ OMIT_SMI_CHECK);
+
+ // Restore registers.
+ __ pop(eax);
+ __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+ }
}
#undef __
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Wed Oct 19 04:36:55 2011
+++ /branches/bleeding_edge/src/objects-inl.h Thu Oct 20 02:38:24 2011
@@ -110,6 +110,11 @@
void holder::set_##name(bool value) { \
set_##field(BooleanBit::set(field(), offset, value)); \
}
+
+
+bool Object::IsFixedArrayBase() {
+ return IsFixedArray() || IsFixedDoubleArray();
+}
bool Object::IsInstanceOf(FunctionTemplateInfo* expected) {
=======================================
--- /branches/bleeding_edge/src/objects-printer.cc Tue Oct 4 08:54:57 2011
+++ /branches/bleeding_edge/src/objects-printer.cc Thu Oct 20 02:38:24 2011
@@ -245,7 +245,7 @@
}
-static void PrintElementsKind(FILE* out, ElementsKind kind) {
+void PrintElementsKind(FILE* out, ElementsKind kind) {
switch (kind) {
case FAST_SMI_ONLY_ELEMENTS:
PrintF(out, "FAST_SMI_ONLY_ELEMENTS");
=======================================
--- /branches/bleeding_edge/src/objects.cc Thu Oct 20 02:35:47 2011
+++ /branches/bleeding_edge/src/objects.cc Thu Oct 20 02:38:24 2011
@@ -1095,6 +1095,27 @@
}
}
}
+
+
+void JSObject::PrintElementsTransition(
+ FILE* file, ElementsKind from_kind, FixedArrayBase* from_elements,
+ ElementsKind to_kind, FixedArrayBase* to_elements) {
+ if (from_kind != to_kind) {
+ PrintF(file, "elements transition [");
+ PrintElementsKind(file, from_kind);
+ PrintF(file, " -> ");
+ PrintElementsKind(file, to_kind);
+ PrintF(file, "] in ");
+ JavaScriptFrame::PrintTop(file, false, true);
+ PrintF(file, " for ");
+ ShortPrint(file);
+ PrintF(file, " from ");
+ from_elements->ShortPrint(file);
+ PrintF(file, " to ");
+ to_elements->ShortPrint(file);
+ PrintF(file, "\n");
+ }
+}
void HeapObject::HeapObjectShortPrint(StringStream* accumulator) {
@@ -1125,6 +1146,10 @@
case FIXED_ARRAY_TYPE:
accumulator->Add("<FixedArray[%u]>",
FixedArray::cast(this)->length());
break;
+ case FIXED_DOUBLE_ARRAY_TYPE:
+ accumulator->Add("<FixedDoubleArray[%u]>",
+ FixedDoubleArray::cast(this)->length());
+ break;
case BYTE_ARRAY_TYPE:
accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length());
break;
@@ -8038,13 +8063,15 @@
new_map = Map::cast(object);
}
+ FixedArrayBase* old_elements_raw = elements();
ElementsKind elements_kind = GetElementsKind();
switch (elements_kind) {
case FAST_SMI_ONLY_ELEMENTS:
case FAST_ELEMENTS: {
AssertNoAllocation no_gc;
WriteBarrierMode mode(new_elements->GetWriteBarrierMode(no_gc));
- CopyFastElementsToFast(FixedArray::cast(elements()), new_elements,
mode);
+ CopyFastElementsToFast(FixedArray::cast(old_elements_raw),
+ new_elements, mode);
set_map(new_map);
set_elements(new_elements);
break;
@@ -8052,7 +8079,7 @@
case DICTIONARY_ELEMENTS: {
AssertNoAllocation no_gc;
WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc);
- CopySlowElementsToFast(NumberDictionary::cast(elements()),
+ CopySlowElementsToFast(NumberDictionary::cast(old_elements_raw),
new_elements,
mode);
set_map(new_map);
@@ -8064,7 +8091,7 @@
WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc);
// The object's map and the parameter map are unchanged, the
unaliased
// arguments are copied to the new backing store.
- FixedArray* parameter_map = FixedArray::cast(elements());
+ FixedArray* parameter_map = FixedArray::cast(old_elements_raw);
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
if (arguments->IsDictionary()) {
CopySlowElementsToFast(NumberDictionary::cast(arguments),
@@ -8077,7 +8104,7 @@
break;
}
case FAST_DOUBLE_ELEMENTS: {
- FixedDoubleArray* old_elements = FixedDoubleArray::cast(elements());
+ FixedDoubleArray* old_elements =
FixedDoubleArray::cast(old_elements_raw);
uint32_t old_length = static_cast<uint32_t>(old_elements->length());
// Fill out the new array with this content and array holes.
for (uint32_t i = 0; i < old_length; i++) {
@@ -8114,6 +8141,11 @@
UNREACHABLE();
break;
}
+
+ if (FLAG_trace_elements_transitions) {
+ PrintElementsTransition(stdout, elements_kind, old_elements_raw,
+ FAST_ELEMENTS, new_elements);
+ }
// Update the length if necessary.
if (IsJSArray()) {
@@ -8144,25 +8176,32 @@
}
Map* new_map = Map::cast(obj);
+ FixedArrayBase* old_elements = elements();
+ ElementsKind elements_kind(GetElementsKind());
AssertNoAllocation no_gc;
- switch (GetElementsKind()) {
+ switch (elements_kind) {
case FAST_SMI_ONLY_ELEMENTS:
case FAST_ELEMENTS: {
- elems->Initialize(FixedArray::cast(elements()));
+ elems->Initialize(FixedArray::cast(old_elements));
break;
}
case FAST_DOUBLE_ELEMENTS: {
- elems->Initialize(FixedDoubleArray::cast(elements()));
+ elems->Initialize(FixedDoubleArray::cast(old_elements));
break;
}
case DICTIONARY_ELEMENTS: {
- elems->Initialize(NumberDictionary::cast(elements()));
+ elems->Initialize(NumberDictionary::cast(old_elements));
break;
}
default:
UNREACHABLE();
break;
}
+
+ if (FLAG_trace_elements_transitions) {
+ PrintElementsTransition(stdout, elements_kind, old_elements,
+ FAST_DOUBLE_ELEMENTS, elems);
+ }
ASSERT(new_map->has_fast_double_elements());
set_map(new_map);
@@ -8183,13 +8222,14 @@
uint32_t new_length = static_cast<uint32_t>(len->Number());
- switch (GetElementsKind()) {
+ FixedArrayBase* old_elements = elements();
+ ElementsKind elements_kind = GetElementsKind();
+ switch (elements_kind) {
case FAST_SMI_ONLY_ELEMENTS:
case FAST_ELEMENTS:
case FAST_DOUBLE_ELEMENTS: {
// Make sure we never try to shrink dense arrays into sparse arrays.
- ASSERT(static_cast<uint32_t>(
- FixedArrayBase::cast(elements())->length()) <= new_length);
+ ASSERT(static_cast<uint32_t>(old_elements->length()) <= new_length);
MaybeObject* result = NormalizeElements();
if (result->IsFailure()) return result;
@@ -8221,6 +8261,12 @@
UNREACHABLE();
break;
}
+
+ if (FLAG_trace_elements_transitions) {
+ PrintElementsTransition(stdout, elements_kind, old_elements,
+ DICTIONARY_ELEMENTS, elements());
+ }
+
return this;
}
@@ -9148,6 +9194,10 @@
Map* new_map;
if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map;
set_map(new_map);
+ if (FLAG_trace_elements_transitions) {
+ PrintElementsTransition(stdout, FAST_SMI_ONLY_ELEMENTS, elements(),
+ FAST_ELEMENTS, elements());
+ }
}
// Increase backing store capacity if that's been decided previously.
if (new_capacity != capacity) {
=======================================
--- /branches/bleeding_edge/src/objects.h Thu Oct 20 02:35:47 2011
+++ /branches/bleeding_edge/src/objects.h Thu Oct 20 02:38:24 2011
@@ -173,6 +173,8 @@
static const int kElementsKindCount =
LAST_ELEMENTS_KIND - FIRST_ELEMENTS_KIND + 1;
+void PrintElementsKind(FILE* out, ElementsKind kind);
+
// PropertyDetails captures type and attributes for a property.
// They are used both in property dictionaries and instance descriptors.
class PropertyDetails BASE_EMBEDDED {
@@ -857,6 +859,8 @@
HEAP_OBJECT_TYPE_LIST(IS_TYPE_FUNCTION_DECL)
#undef IS_TYPE_FUNCTION_DECL
+ inline bool IsFixedArrayBase();
+
// Returns true if this object is an instance of the specified
// function template.
inline bool IsInstanceOf(FunctionTemplateInfo* type);
@@ -1912,6 +1916,10 @@
void PrintElements(FILE* out);
#endif
+ void PrintElementsTransition(
+ FILE* file, ElementsKind from_kind, FixedArrayBase* from_elements,
+ ElementsKind to_kind, FixedArrayBase* to_elements);
+
#ifdef DEBUG
// Structure for collecting spill information about JSObjects.
class SpillInformation {
=======================================
--- /branches/bleeding_edge/src/runtime.cc Wed Oct 19 05:15:02 2011
+++ /branches/bleeding_edge/src/runtime.cc Thu Oct 20 02:38:24 2011
@@ -9043,42 +9043,6 @@
return Execution::HandleStackGuardInterrupt();
}
-
-
-// NOTE: These PrintXXX functions are defined for all builds (not just
-// DEBUG builds) because we may want to be able to trace function
-// calls in all modes.
-static void PrintString(String* str) {
- // not uncommon to have empty strings
- if (str->length() > 0) {
- SmartArrayPointer<char> s =
- str->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
- PrintF("%s", *s);
- }
-}
-
-
-static void PrintObject(Object* obj) {
- if (obj->IsSmi()) {
- PrintF("%d", Smi::cast(obj)->value());
- } else if (obj->IsString() || obj->IsSymbol()) {
- PrintString(String::cast(obj));
- } else if (obj->IsNumber()) {
- PrintF("%g", obj->Number());
- } else if (obj->IsFailure()) {
- PrintF("<failure>");
- } else if (obj->IsUndefined()) {
- PrintF("<undefined>");
- } else if (obj->IsNull()) {
- PrintF("<null>");
- } else if (obj->IsTrue()) {
- PrintF("<true>");
- } else if (obj->IsFalse()) {
- PrintF("<false>");
- } else {
- PrintF("%p", reinterpret_cast<void*>(obj));
- }
-}
static int StackSize() {
@@ -9099,36 +9063,31 @@
}
if (result == NULL) {
- // constructor calls
- JavaScriptFrameIterator it;
- JavaScriptFrame* frame = it.frame();
- if (frame->IsConstructor()) PrintF("new ");
- // function name
- Object* fun = frame->function();
- if (fun->IsJSFunction()) {
- PrintObject(JSFunction::cast(fun)->shared()->name());
- } else {
- PrintObject(fun);
- }
- // function arguments
- // (we are intentionally only printing the actually
- // supplied parameters, not all parameters required)
- PrintF("(this=");
- PrintObject(frame->receiver());
- const int length = frame->ComputeParametersCount();
- for (int i = 0; i < length; i++) {
- PrintF(", ");
- PrintObject(frame->GetParameter(i));
- }
- PrintF(") {\n");
-
+ JavaScriptFrame::PrintTop(stdout, true, false);
+ PrintF(" {\n");
} else {
// function result
PrintF("} -> ");
- PrintObject(result);
+ result->ShortPrint();
PrintF("\n");
}
}
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceElementsKindTransition) {
+ ASSERT(args.length() == 5);
+ CONVERT_ARG_CHECKED(JSObject, obj, 0);
+ CONVERT_SMI_ARG_CHECKED(from_kind, 1);
+ CONVERT_ARG_CHECKED(FixedArrayBase, from_elements, 2);
+ CONVERT_SMI_ARG_CHECKED(to_kind, 3);
+ CONVERT_ARG_CHECKED(FixedArrayBase, to_elements, 4);
+ NoHandleAllocation ha;
+ PrintF("*");
+ obj->PrintElementsTransition(stdout,
+ static_cast<ElementsKind>(from_kind), *from_elements,
+ static_cast<ElementsKind>(to_kind), *to_elements);
+ return isolate->heap()->undefined_value();
+}
RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceEnter) {
=======================================
--- /branches/bleeding_edge/src/runtime.h Wed Oct 19 05:10:18 2011
+++ /branches/bleeding_edge/src/runtime.h Thu Oct 20 02:38:24 2011
@@ -333,6 +333,7 @@
/* Debugging */ \
F(DebugPrint, 1, 1) \
F(DebugTrace, 0, 1) \
+ F(TraceElementsKindTransition, 5, 1) \
F(TraceEnter, 0, 1) \
F(TraceExit, 1, 1) \
F(Abort, 2, 1) \
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev