Commit fdffe672 authored by yangguo@chromium.org's avatar yangguo@chromium.org

Initialize pre-allocated fields of JSObject with undefined.

BUG=94873

Review URL: http://codereview.chromium.org/7929001

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9335 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 29618c07
......@@ -750,20 +750,22 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// r5: First in-object property of JSObject (not tagged)
__ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object.
ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize);
{ Label loop, entry;
if (count_constructions) {
// To allow for truncation.
__ LoadRoot(r7, Heap::kOnePointerFillerMapRootIndex);
} else {
__ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
__ LoadRoot(r7, Heap::kUndefinedValueRootIndex);
if (count_constructions) {
__ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
__ Ubfx(r0, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
kBitsPerByte);
__ add(r0, r5, Operand(r0, LSL, kPointerSizeLog2));
// r0: offset of first field after pre-allocated fields
if (FLAG_debug_code) {
__ cmp(r0, r6);
__ Assert(le, "Unexpected number of pre-allocated property fields.");
}
__ b(&entry);
__ bind(&loop);
__ str(r7, MemOperand(r5, kPointerSize, PostIndex));
__ bind(&entry);
__ cmp(r5, r6);
__ b(lt, &loop);
__ InitializeFieldsWithFiller(r5, r0, r7);
// To allow for truncation.
__ LoadRoot(r7, Heap::kOnePointerFillerMapRootIndex);
}
__ InitializeFieldsWithFiller(r5, r6, r7);
// Add the object tag to make the JSObject real, so that we can continue
// and jump into the continuation code at any time from now on. Any
......@@ -780,9 +782,11 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// The field instance sizes contains both pre-allocated property fields
// and in-object properties.
__ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
__ Ubfx(r6, r0, Map::kPreAllocatedPropertyFieldsByte * 8, 8);
__ Ubfx(r6, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte,
kBitsPerByte);
__ add(r3, r3, Operand(r6));
__ Ubfx(r6, r0, Map::kInObjectPropertiesByte * 8, 8);
__ Ubfx(r6, r0, Map::kInObjectPropertiesByte * kBitsPerByte,
kBitsPerByte);
__ sub(r3, r3, Operand(r6), SetCC);
// Done if no extra properties are to be allocated.
......
......@@ -3002,6 +3002,19 @@ void MacroAssembler::CopyBytes(Register src,
}
void MacroAssembler::InitializeFieldsWithFiller(Register start_offset,
Register end_offset,
Register filler) {
Label loop, entry;
b(&entry);
bind(&loop);
str(filler, MemOperand(start_offset, kPointerSize, PostIndex));
bind(&entry);
cmp(start_offset, end_offset);
b(lt, &loop);
}
void MacroAssembler::CountLeadingZeros(Register zeros, // Answer.
Register source, // Input.
Register scratch) {
......
......@@ -653,6 +653,13 @@ class MacroAssembler: public Assembler {
Register length,
Register scratch);
// Initialize fields with filler values. Fields starting at |start_offset|
// not including end_offset are overwritten with the value in |filler|. At
// the end the loop, |start_offset| takes the value of |end_offset|.
void InitializeFieldsWithFiller(Register start_offset,
Register end_offset,
Register filler);
// ---------------------------------------------------------------------------
// Support functions.
......
......@@ -3443,6 +3443,9 @@ void Heap::InitializeJSObjectFromMap(JSObject* obj,
// We cannot always fill with one_pointer_filler_map because objects
// created from API functions expect their internal fields to be initialized
// with undefined_value.
// Pre-allocated fields need to be initialized with undefined_value as well
// so that object accesses before the constructor completes (e.g. in the
// debugger) will not cause a crash.
if (map->constructor()->IsJSFunction() &&
JSFunction::cast(map->constructor())->shared()->
IsInobjectSlackTrackingInProgress()) {
......@@ -3452,7 +3455,7 @@ void Heap::InitializeJSObjectFromMap(JSObject* obj,
} else {
filler = Heap::undefined_value();
}
obj->InitializeBody(map->instance_size(), filler);
obj->InitializeBody(map, Heap::undefined_value(), filler);
}
......
......@@ -204,22 +204,23 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// eax: initial map
// ebx: JSObject
// edi: start of next object
{ Label loop, entry;
// To allow for truncation.
if (count_constructions) {
__ mov(edx, factory->one_pointer_filler_map());
} else {
__ mov(edx, factory->undefined_value());
__ lea(ecx, Operand(ebx, JSObject::kHeaderSize));
__ mov(edx, factory->undefined_value());
if (count_constructions) {
__ movzx_b(esi,
FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset));
__ lea(esi,
Operand(ebx, esi, times_pointer_size, JSObject::kHeaderSize));
// esi: offset of first field after pre-allocated fields
if (FLAG_debug_code) {
__ cmp(esi, Operand(edi));
__ Assert(less_equal,
"Unexpected number of pre-allocated property fields.");
}
__ lea(ecx, Operand(ebx, JSObject::kHeaderSize));
__ jmp(&entry);
__ bind(&loop);
__ mov(Operand(ecx, 0), edx);
__ add(Operand(ecx), Immediate(kPointerSize));
__ bind(&entry);
__ cmp(ecx, Operand(edi));
__ j(less, &loop);
__ InitializeFieldsWithFiller(ecx, esi, edx);
__ mov(edx, factory->one_pointer_filler_map());
}
__ InitializeFieldsWithFiller(ecx, edi, edx);
// Add the object tag to make the JSObject real, so that we can continue
// and jump into the continuation code at any time from now on. Any
......
......@@ -1379,6 +1379,20 @@ void MacroAssembler::CopyBytes(Register source,
}
void MacroAssembler::InitializeFieldsWithFiller(Register start_offset,
Register end_offset,
Register filler) {
Label loop, entry;
jmp(&entry);
bind(&loop);
mov(Operand(start_offset, 0), filler);
add(Operand(start_offset), Immediate(kPointerSize));
bind(&entry);
cmp(start_offset, Operand(end_offset));
j(less, &loop);
}
void MacroAssembler::NegativeZeroTest(Register result,
Register op,
Label* then_label) {
......
......@@ -551,6 +551,13 @@ class MacroAssembler: public Assembler {
Register length,
Register scratch);
// Initialize fields with filler values. Fields starting at |start_offset|
// not including end_offset are overwritten with the value in |filler|. At
// the end the loop, |start_offset| takes the value of |end_offset|.
void InitializeFieldsWithFiller(Register start_offset,
Register end_offset,
Register filler);
// ---------------------------------------------------------------------------
// Support functions.
......
......@@ -1493,10 +1493,26 @@ Object* JSObject::InObjectPropertyAtPut(int index,
void JSObject::InitializeBody(int object_size, Object* value) {
ASSERT(!value->IsHeapObject() || !GetHeap()->InNewSpace(value));
for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
WRITE_FIELD(this, offset, value);
void JSObject::InitializeBody(Map* map,
Object* pre_allocated_value,
Object* filler_value) {
ASSERT(!filler_value->IsHeapObject() ||
!GetHeap()->InNewSpace(filler_value));
ASSERT(!pre_allocated_value->IsHeapObject() ||
!GetHeap()->InNewSpace(pre_allocated_value));
int size = map->instance_size();
int offset = kHeaderSize;
if (filler_value != pre_allocated_value) {
int pre_allocated = map->pre_allocated_property_fields();
ASSERT(pre_allocated * kPointerSize + kHeaderSize <= size);
for (int i = 0; i < pre_allocated; i++) {
WRITE_FIELD(this, offset, pre_allocated_value);
offset += kPointerSize;
}
}
while (offset < size) {
WRITE_FIELD(this, offset, filler_value);
offset += kPointerSize;
}
}
......
......@@ -1815,11 +1815,14 @@ class JSObject: public JSReceiver {
WriteBarrierMode mode
= UPDATE_WRITE_BARRIER);
// initializes the body after properties slot, properties slot is
// initialized by set_properties
// Note: this call does not update write barrier, it is caller's
// reponsibility to ensure that *v* can be collected without WB here.
inline void InitializeBody(int object_size, Object* value);
// Initializes the body after properties slot, properties slot is
// initialized by set_properties. Fill the pre-allocated fields with
// pre_allocated_value and the rest with filler_value.
// Note: this call does not update write barrier, the caller is responsible
// to ensure that |filler_value| can be collected without WB here.
inline void InitializeBody(Map* map,
Object* pre_allocated_value,
Object* filler_value);
// Check whether this object references another object
bool ReferencesObject(Object* obj);
......
......@@ -207,22 +207,23 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// rax: initial map
// rbx: JSObject
// rdi: start of next object
{ Label loop, entry;
// To allow for truncation.
if (count_constructions) {
__ LoadRoot(rdx, Heap::kOnePointerFillerMapRootIndex);
} else {
__ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
__ lea(rcx, Operand(rbx, JSObject::kHeaderSize));
__ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
if (count_constructions) {
__ movzxbq(rsi,
FieldOperand(rax, Map::kPreAllocatedPropertyFieldsOffset));
__ lea(rsi,
Operand(rbx, rsi, times_pointer_size, JSObject::kHeaderSize));
// rsi: offset of first field after pre-allocated fields
if (FLAG_debug_code) {
__ cmpq(rsi, rdi);
__ Assert(less_equal,
"Unexpected number of pre-allocated property fields.");
}
__ lea(rcx, Operand(rbx, JSObject::kHeaderSize));
__ jmp(&entry);
__ bind(&loop);
__ movq(Operand(rcx, 0), rdx);
__ addq(rcx, Immediate(kPointerSize));
__ bind(&entry);
__ cmpq(rcx, rdi);
__ j(less, &loop);
__ InitializeFieldsWithFiller(rcx, rsi, rdx);
__ LoadRoot(rdx, Heap::kOnePointerFillerMapRootIndex);
}
__ InitializeFieldsWithFiller(rcx, rdi, rdx);
// Add the object tag to make the JSObject real, so that we can continue
// and jump into the continuation code at any time from now on. Any
......
......@@ -3851,6 +3851,20 @@ void MacroAssembler::CopyBytes(Register destination,
}
void MacroAssembler::InitializeFieldsWithFiller(Register start_offset,
Register end_offset,
Register filler) {
Label loop, entry;
jmp(&entry);
bind(&loop);
movq(Operand(start_offset, 0), filler);
addq(start_offset, Immediate(kPointerSize));
bind(&entry);
cmpq(start_offset, end_offset);
j(less, &loop);
}
void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
if (context_chain_length > 0) {
// Move up the chain of contexts to the context containing the slot.
......
......@@ -1205,6 +1205,13 @@ class MacroAssembler: public Assembler {
int min_length = 0,
Register scratch = kScratchRegister);
// Initialize fields with filler values. Fields starting at |start_offset|
// not including end_offset are overwritten with the value in |filler|. At
// the end the loop, |start_offset| takes the value of |end_offset|.
void InitializeFieldsWithFiller(Register start_offset,
Register end_offset,
Register filler);
// ---------------------------------------------------------------------------
// StatsCounter support
......
// Copyright 2011 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:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --expose-debug-as debug
// Get the Debug object exposed from the debug context global object.
Debug = debug.Debug;
function sendCommand(state, cmd) {
// Get the debug command processor in paused state.
var dcp = state.debugCommandProcessor(false);
var request = JSON.stringify(cmd);
var response = dcp.processDebugJSONRequest(request);
return JSON.parse(response);
}
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
var line = event_data.sourceLineText();
print('break: ' + line);
var frame = sendCommand(exec_state, {
seq: 0,
type: "request",
command: "frame"
});
sendCommand(exec_state, {
seq: 0,
type: "request",
command: "evaluate",
arguments: {
expression: "obj.x.toString()",
additional_context: [{
name: "obj",
handle: frame.body.receiver.ref
}]
}
});
}
} catch (e) {
print(e);
}
}
Debug.setListener(listener);
function a(x, y) {
this.x = x;
this.y = y;
}
Debug.setBreakPoint(a, 0, 0);
new a(1, 2);
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment