Skip to content

Commit

Permalink
Make randomized allocations along 64k granularity boundaries to avoid…
Browse files Browse the repository at this point in the history
… comitting unused memory.

BUG=56036
TEST=None.

Patch by Justin Schuh <jschuh@chromium.org>

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



git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@5883 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
  • Loading branch information
sgjesse@chromium.org committed Nov 24, 2010
1 parent 95ba7f9 commit 61012c5
Show file tree
Hide file tree
Showing 9 changed files with 268 additions and 66 deletions.
1 change: 0 additions & 1 deletion AUTHORS
Expand Up @@ -9,7 +9,6 @@ ARM Ltd.
Hewlett-Packard Development Company, LP

Alexander Botero-Lowry <alexbl@FreeBSD.org>
Alexandre Rames <alexandre.rames@arm.com>
Alexandre Vassalotti <avassalotti@gmail.com>
Andreas Anyuru <andreas.anyuru@gmail.com>
Burcu Dogan <burcujdogan@gmail.com>
Expand Down
6 changes: 2 additions & 4 deletions src/arm/assembler-arm-inl.h
Expand Up @@ -164,7 +164,7 @@ bool RelocInfo::IsPatchedReturnSequence() {

bool RelocInfo::IsPatchedDebugBreakSlotSequence() {
Instr current_instr = Assembler::instr_at(pc_);
return !Assembler::IsNop(current_instr, 2);
return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP);
}


Expand Down Expand Up @@ -288,9 +288,7 @@ Address Assembler::target_address_address_at(Address pc) {
}
#endif

// Verify that the instruction to patch is a
// ldr<cond> <Rd>, [pc +/- offset_12].
ASSERT((instr & 0x0f7f0000) == 0x051f0000);
ASSERT(IsLdrPcImmediateOffset(instr));
int offset = instr & 0xfff; // offset_12 is unsigned
if ((instr & (1 << 23)) == 0) offset = -offset; // U bit defines offset sign
// Verify that the constant pool comes after the instruction referencing it.
Expand Down
25 changes: 16 additions & 9 deletions src/arm/assembler-arm.cc
Expand Up @@ -397,13 +397,6 @@ void Assembler::CodeTargetAlign() {
}


bool Assembler::IsNop(Instr instr, int type) {
// Check for mov rx, rx.
ASSERT(0 <= type && type <= 14); // mov pc, pc is not a nop.
return instr == (al | 13*B21 | type*B12 | type);
}


bool Assembler::IsBranch(Instr instr) {
return (instr & (B27 | B25)) == (B27 | B25);
}
Expand Down Expand Up @@ -510,6 +503,13 @@ bool Assembler::IsLdrRegFpNegOffset(Instr instr) {
}


bool Assembler::IsLdrPcImmediateOffset(Instr instr) {
// Check the instruction is indeed a
// ldr<cond> <Rd>, [pc +/- offset_12].
return (instr & 0x0f7f0000) == 0x051f0000;
}


// Labels refer to positions in the (to be) generated code.
// There are bound, linked, and unused labels.
//
Expand Down Expand Up @@ -1113,8 +1113,8 @@ void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) {
positions_recorder()->WriteRecordedPositions();
}
// Don't allow nop instructions in the form mov rn, rn to be generated using
// the mov instruction. They must be generated using nop(int)
// pseudo instructions.
// the mov instruction. They must be generated using nop(int/NopMarkerTypes)
// or MarkCode(int/NopMarkerTypes) pseudo instructions.
ASSERT(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al));
addrmod1(cond | 13*B21 | s, r0, dst, src);
}
Expand Down Expand Up @@ -2376,6 +2376,13 @@ void Assembler::nop(int type) {
}


bool Assembler::IsNop(Instr instr, int type) {
// Check for mov rx, rx.
ASSERT(0 <= type && type <= 14); // mov pc, pc is not a nop.
return instr == (al | 13*B21 | type*B12 | type);
}


bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) {
uint32_t dummy1;
uint32_t dummy2;
Expand Down
20 changes: 18 additions & 2 deletions src/arm/assembler-arm.h
Expand Up @@ -1079,7 +1079,22 @@ class Assembler : public Malloced {
const Condition cond = al);

// Pseudo instructions
void nop(int type = 0);

// Different nop operations are used by the code generator to detect certain
// states of the generated code.
enum NopMarkerTypes {
NON_MARKING_NOP = 0,
DEBUG_BREAK_NOP,
// IC markers.
PROPERTY_ACCESS_INLINED,
PROPERTY_ACCESS_INLINED_CONTEXT,
PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
// Helper values.
LAST_CODE_MARKER,
FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
};

void nop(int type = 0); // 0 is the default non-marking type.

void push(Register src, Condition cond = al) {
str(src, MemOperand(sp, 4, NegPreIndex), cond);
Expand Down Expand Up @@ -1151,7 +1166,6 @@ class Assembler : public Malloced {
static void instr_at_put(byte* pc, Instr instr) {
*reinterpret_cast<Instr*>(pc) = instr;
}
static bool IsNop(Instr instr, int type = 0);
static bool IsBranch(Instr instr);
static int GetBranchOffset(Instr instr);
static bool IsLdrRegisterImmediate(Instr instr);
Expand All @@ -1168,6 +1182,8 @@ class Assembler : public Malloced {
static bool IsLdrRegFpOffset(Instr instr);
static bool IsStrRegFpNegOffset(Instr instr);
static bool IsLdrRegFpNegOffset(Instr instr);
static bool IsLdrPcImmediateOffset(Instr instr);
static bool IsNop(Instr instr, int type = NON_MARKING_NOP);


protected:
Expand Down
159 changes: 132 additions & 27 deletions src/arm/codegen-arm.cc
Expand Up @@ -6537,16 +6537,29 @@ void CodeGenerator::VisitCompareToNull(CompareToNull* node) {
class DeferredReferenceGetNamedValue: public DeferredCode {
public:
explicit DeferredReferenceGetNamedValue(Register receiver,
Handle<String> name)
: receiver_(receiver), name_(name) {
set_comment("[ DeferredReferenceGetNamedValue");
Handle<String> name,
bool is_contextual)
: receiver_(receiver),
name_(name),
is_contextual_(is_contextual),
is_dont_delete_(false) {
set_comment(is_contextual
? "[ DeferredReferenceGetNamedValue (contextual)"
: "[ DeferredReferenceGetNamedValue");
}

virtual void Generate();

void set_is_dont_delete(bool value) {
ASSERT(is_contextual_);
is_dont_delete_ = value;
}

private:
Register receiver_;
Handle<String> name_;
bool is_contextual_;
bool is_dont_delete_;
};


Expand All @@ -6573,10 +6586,20 @@ void DeferredReferenceGetNamedValue::Generate() {
// The rest of the instructions in the deferred code must be together.
{ Assembler::BlockConstPoolScope block_const_pool(masm_);
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET);
// The call must be followed by a nop(1) instruction to indicate that the
// in-object has been inlined.
__ nop(PROPERTY_ACCESS_INLINED);
RelocInfo::Mode mode = is_contextual_
? RelocInfo::CODE_TARGET_CONTEXT
: RelocInfo::CODE_TARGET;
__ Call(ic, mode);
// We must mark the code just after the call with the correct marker.
MacroAssembler::NopMarkerTypes code_marker;
if (is_contextual_) {
code_marker = is_dont_delete_
? MacroAssembler::PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE
: MacroAssembler::PROPERTY_ACCESS_INLINED_CONTEXT;
} else {
code_marker = MacroAssembler::PROPERTY_ACCESS_INLINED;
}
__ MarkCode(code_marker);

// At this point the answer is in r0. We move it to the expected register
// if necessary.
Expand Down Expand Up @@ -6640,7 +6663,7 @@ void DeferredReferenceGetKeyedValue::Generate() {
__ Call(ic, RelocInfo::CODE_TARGET);
// The call must be followed by a nop instruction to indicate that the
// keyed load has been inlined.
__ nop(PROPERTY_ACCESS_INLINED);
__ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED);

// Now go back to the frame that we entered with. This will not overwrite
// the receiver or key registers since they were not in use when we came
Expand Down Expand Up @@ -6697,7 +6720,7 @@ void DeferredReferenceSetKeyedValue::Generate() {
__ Call(ic, RelocInfo::CODE_TARGET);
// The call must be followed by a nop instruction to indicate that the
// keyed store has been inlined.
__ nop(PROPERTY_ACCESS_INLINED);
__ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED);

// Block the constant pool for one more instruction after leaving this
// constant pool block scope to include the branch instruction ending the
Expand Down Expand Up @@ -6745,7 +6768,7 @@ void DeferredReferenceSetNamedValue::Generate() {
__ Call(ic, RelocInfo::CODE_TARGET);
// The call must be followed by a nop instruction to indicate that the
// named store has been inlined.
__ nop(PROPERTY_ACCESS_INLINED);
__ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED);

// Go back to the frame we entered with. The instructions
// generated by this merge are skipped over by the inline store
Expand All @@ -6763,7 +6786,14 @@ void DeferredReferenceSetNamedValue::Generate() {

// Consumes the top of stack (the receiver) and pushes the result instead.
void CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) {
if (is_contextual || scope()->is_global_scope() || loop_nesting() == 0) {
bool contextual_load_in_builtin =
is_contextual &&
(Bootstrapper::IsActive() ||
(!info_->closure().is_null() && info_->closure()->IsBuiltin()));

if (scope()->is_global_scope() ||
loop_nesting() == 0 ||
contextual_load_in_builtin) {
Comment cmnt(masm(), "[ Load from named Property");
// Setup the name register and call load IC.
frame_->CallLoadIC(name,
Expand All @@ -6773,12 +6803,19 @@ void CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) {
frame_->EmitPush(r0); // Push answer.
} else {
// Inline the in-object property case.
Comment cmnt(masm(), "[ Inlined named property load");
Comment cmnt(masm(), is_contextual
? "[ Inlined contextual property load"
: "[ Inlined named property load");

// Counter will be decremented in the deferred code. Placed here to avoid
// having it in the instruction stream below where patching will occur.
__ IncrementCounter(&Counters::named_load_inline, 1,
frame_->scratch0(), frame_->scratch1());
if (is_contextual) {
__ IncrementCounter(&Counters::named_load_global_inline, 1,
frame_->scratch0(), frame_->scratch1());
} else {
__ IncrementCounter(&Counters::named_load_inline, 1,
frame_->scratch0(), frame_->scratch1());
}

// The following instructions are the inlined load of an in-object property.
// Parts of this code is patched, so the exact instructions generated needs
Expand All @@ -6789,19 +6826,57 @@ void CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) {
Register receiver = frame_->PopToRegister();

DeferredReferenceGetNamedValue* deferred =
new DeferredReferenceGetNamedValue(receiver, name);
new DeferredReferenceGetNamedValue(receiver, name, is_contextual);

bool is_dont_delete = false;
if (is_contextual) {
if (!info_->closure().is_null()) {
// When doing lazy compilation we can check if the global cell
// already exists and use its "don't delete" status as a hint.
AssertNoAllocation no_gc;
v8::internal::GlobalObject* global_object =
info_->closure()->context()->global();
LookupResult lookup;
global_object->LocalLookupRealNamedProperty(*name, &lookup);
if (lookup.IsProperty() && lookup.type() == NORMAL) {
ASSERT(lookup.holder() == global_object);
ASSERT(global_object->property_dictionary()->ValueAt(
lookup.GetDictionaryEntry())->IsJSGlobalPropertyCell());
is_dont_delete = lookup.IsDontDelete();
}
}
if (is_dont_delete) {
__ IncrementCounter(&Counters::dont_delete_hint_hit, 1,
frame_->scratch0(), frame_->scratch1());
}
}

{ Assembler::BlockConstPoolScope block_const_pool(masm_);
if (!is_contextual) {
// Check that the receiver is a heap object.
__ tst(receiver, Operand(kSmiTagMask));
deferred->Branch(eq);
}

// Check for the_hole_value if necessary.
// Below we rely on the number of instructions generated, and we can't
// cope with the Check macro which does not generate a fixed number of
// instructions.
Label skip, check_the_hole, cont;
if (FLAG_debug_code && is_contextual && is_dont_delete) {
__ b(&skip);
__ bind(&check_the_hole);
__ Check(ne, "DontDelete cells can't contain the hole");
__ b(&cont);
__ bind(&skip);
}

#ifdef DEBUG
int kInlinedNamedLoadInstructions = 7;
Label check_inlined_codesize;
masm_->bind(&check_inlined_codesize);
int InlinedNamedLoadInstructions = 5;
Label check_inlined_codesize;
masm_->bind(&check_inlined_codesize);
#endif

{ Assembler::BlockConstPoolScope block_const_pool(masm_);
// Check that the receiver is a heap object.
__ tst(receiver, Operand(kSmiTagMask));
deferred->Branch(eq);

Register scratch = VirtualFrame::scratch0();
Register scratch2 = VirtualFrame::scratch1();

Expand All @@ -6812,12 +6887,42 @@ void CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) {
__ cmp(scratch, scratch2);
deferred->Branch(ne);

// Initially use an invalid index. The index will be patched by the
// inline cache code.
__ ldr(receiver, MemOperand(receiver, 0));
if (is_contextual) {
#ifdef DEBUG
InlinedNamedLoadInstructions += 1;
#endif
// Load the (initially invalid) cell and get its value.
masm()->mov(receiver, Operand(Factory::null_value()));
__ ldr(receiver,
FieldMemOperand(receiver, JSGlobalPropertyCell::kValueOffset));

deferred->set_is_dont_delete(is_dont_delete);

if (!is_dont_delete) {
#ifdef DEBUG
InlinedNamedLoadInstructions += 3;
#endif
__ cmp(receiver, Operand(Factory::the_hole_value()));
deferred->Branch(eq);
} else if (FLAG_debug_code) {
#ifdef DEBUG
InlinedNamedLoadInstructions += 3;
#endif
__ cmp(receiver, Operand(Factory::the_hole_value()));
__ b(&check_the_hole, eq);
__ bind(&cont);
}
} else {
// Initially use an invalid index. The index will be patched by the
// inline cache code.
__ ldr(receiver, MemOperand(receiver, 0));
}

// Make sure that the expected number of instructions are generated.
ASSERT_EQ(kInlinedNamedLoadInstructions,
// If the code before is updated, the offsets in ic-arm.cc
// LoadIC::PatchInlinedContextualLoad and PatchInlinedLoad need
// to be updated.
ASSERT_EQ(InlinedNamedLoadInstructions,
masm_->InstructionsGeneratedSince(&check_inlined_codesize));
}

Expand Down
8 changes: 0 additions & 8 deletions src/arm/codegen-arm.h
Expand Up @@ -194,14 +194,6 @@ enum ArgumentsAllocationMode {
};


// Different nop operations are used by the code generator to detect certain
// states of the generated code.
enum NopMarkerTypes {
NON_MARKING_NOP = 0,
PROPERTY_ACCESS_INLINED
};


// -------------------------------------------------------------------------
// CodeGenerator

Expand Down
2 changes: 1 addition & 1 deletion src/arm/debug-arm.cc
Expand Up @@ -279,7 +279,7 @@ void Debug::GenerateSlot(MacroAssembler* masm) {
__ bind(&check_codesize);
__ RecordDebugBreakSlot();
for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) {
__ nop(2);
__ nop(MacroAssembler::DEBUG_BREAK_NOP);
}
ASSERT_EQ(Assembler::kDebugBreakSlotInstructions,
masm->InstructionsGeneratedSince(&check_codesize));
Expand Down

0 comments on commit 61012c5

Please sign in to comment.