Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Upgrade V8 to 3.6.6.19

  • Loading branch information...
commit 4afc46d7bcbb1caec986ddba642c943d79b83105 1 parent 4fdec07
@isaacs isaacs authored
Showing with 586 additions and 834 deletions.
  1. +8 −1 deps/v8/src/arm/assembler-arm-inl.h
  2. +4 −6 deps/v8/src/arm/assembler-arm.h
  3. +3 −4 deps/v8/src/arm/code-stubs-arm.cc
  4. +22 −54 deps/v8/src/arm/deoptimizer-arm.cc
  5. +98 −124 deps/v8/src/arm/lithium-codegen-arm.cc
  6. +16 −14 deps/v8/src/arm/lithium-codegen-arm.h
  7. +9 −12 deps/v8/src/arm/lithium-gap-resolver-arm.cc
  8. +2 −16 deps/v8/src/deoptimizer.cc
  9. +1 −0  deps/v8/src/hydrogen-instructions.h
  10. +2 −4 deps/v8/src/ia32/code-stubs-ia32.cc
  11. +47 −69 deps/v8/src/ia32/deoptimizer-ia32.cc
  12. +98 −114 deps/v8/src/ia32/lithium-codegen-ia32.cc
  13. +13 −21 deps/v8/src/ia32/lithium-codegen-ia32.h
  14. +0 −10 deps/v8/src/ia32/lithium-ia32.h
  15. +7 −1 deps/v8/src/lithium.h
  16. +1 −1  deps/v8/src/mips/code-stubs-mips.cc
  17. +7 −4 deps/v8/src/objects.cc
  18. +8 −1 deps/v8/src/objects.h
  19. +24 −36 deps/v8/src/safepoint-table.cc
  20. +29 −49 deps/v8/src/safepoint-table.h
  21. +2 −2 deps/v8/src/version.cc
  22. +2 −3 deps/v8/src/x64/code-stubs-x64.cc
  23. +16 −131 deps/v8/src/x64/deoptimizer-x64.cc
  24. +96 −140 deps/v8/src/x64/lithium-codegen-x64.cc
  25. +15 −14 deps/v8/src/x64/lithium-codegen-x64.h
  26. +8 −3 deps/v8/test/mjsunit/compiler/regress-funcaller.js
  27. +48 −0 deps/v8/test/mjsunit/compiler/regress-lazy-deopt.js
View
9 deps/v8/src/arm/assembler-arm-inl.h
@@ -32,7 +32,7 @@
// The original source code covered by the above license above has been modified
// significantly by Google Inc.
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
#ifndef V8_ARM_ASSEMBLER_ARM_INL_H_
#define V8_ARM_ASSEMBLER_ARM_INL_H_
@@ -46,6 +46,13 @@ namespace v8 {
namespace internal {
+int DwVfpRegister::ToAllocationIndex(DwVfpRegister reg) {
+ ASSERT(!reg.is(kDoubleRegZero));
+ ASSERT(!reg.is(kScratchDoubleReg));
+ return reg.code();
+}
+
+
void RelocInfo::apply(intptr_t delta) {
if (RelocInfo::IsInternalReference(rmode_)) {
// absolute code pointer inside code object moves with the code object.
View
10 deps/v8/src/arm/assembler-arm.h
@@ -32,7 +32,7 @@
// The original source code covered by the above license above has been
// modified significantly by Google Inc.
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
// A light-weight ARM Assembler
// Generates user mode instructions for the ARM architecture up to version 5
@@ -176,14 +176,11 @@ struct DwVfpRegister {
static const int kNumAllocatableRegisters = kNumRegisters -
kNumReservedRegisters;
- static int ToAllocationIndex(DwVfpRegister reg) {
- ASSERT(reg.code() != 0);
- return reg.code() - 1;
- }
+ inline static int ToAllocationIndex(DwVfpRegister reg);
static DwVfpRegister FromAllocationIndex(int index) {
ASSERT(index >= 0 && index < kNumAllocatableRegisters);
- return from_code(index + 1);
+ return from_code(index);
}
static const char* AllocationIndexToString(int index) {
@@ -307,6 +304,7 @@ const DwVfpRegister d15 = { 15 };
const DwVfpRegister kFirstCalleeSavedDoubleReg = d8;
const DwVfpRegister kLastCalleeSavedDoubleReg = d15;
const DwVfpRegister kDoubleRegZero = d14;
+const DwVfpRegister kScratchDoubleReg = d15;
// Coprocessor register
View
7 deps/v8/src/arm/code-stubs-arm.cc
@@ -5392,13 +5392,12 @@ void StringHelper::GenerateHashGetHash(MacroAssembler* masm,
// hash ^= hash >> 11;
__ eor(hash, hash, Operand(hash, LSR, 11));
// hash += hash << 15;
- __ add(hash, hash, Operand(hash, LSL, 15), SetCC);
+ __ add(hash, hash, Operand(hash, LSL, 15));
- uint32_t kHashShiftCutOffMask = (1 << (32 - String::kHashShift)) - 1;
- __ and_(hash, hash, Operand(kHashShiftCutOffMask));
+ __ and_(hash, hash, Operand(String::kHashBitMask), SetCC);
// if (hash == 0) hash = 27;
- __ mov(hash, Operand(27), LeaveCC, eq);
+ __ mov(hash, Operand(StringHasher::kZeroHash), LeaveCC, eq);
}
View
76 deps/v8/src/arm/deoptimizer-arm.cc
@@ -44,12 +44,6 @@ int Deoptimizer::patch_size() {
}
-void Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code) {
- // Nothing to do. No new relocation information is written for lazy
- // deoptimization on ARM.
-}
-
-
void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
HandleScope scope;
AssertNoAllocation no_allocation;
@@ -58,59 +52,38 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
// Get the optimized code.
Code* code = function->code();
+ Address code_start_address = code->instruction_start();
// Invalidate the relocation information, as it will become invalid by the
// code patching below, and is not needed any more.
code->InvalidateRelocation();
- // For each return after a safepoint insert an absolute call to the
- // corresponding deoptimization entry.
- unsigned last_pc_offset = 0;
- SafepointTable table(function->code());
- for (unsigned i = 0; i < table.length(); i++) {
- unsigned pc_offset = table.GetPcOffset(i);
- SafepointEntry safepoint_entry = table.GetEntry(i);
- int deoptimization_index = safepoint_entry.deoptimization_index();
- int gap_code_size = safepoint_entry.gap_code_size();
- // Check that we did not shoot past next safepoint.
- CHECK(pc_offset >= last_pc_offset);
+ // For each LLazyBailout instruction insert a call to the corresponding
+ // deoptimization entry.
+ DeoptimizationInputData* deopt_data =
+ DeoptimizationInputData::cast(code->deoptimization_data());
#ifdef DEBUG
- // Destroy the code which is not supposed to be run again.
- int instructions = (pc_offset - last_pc_offset) / Assembler::kInstrSize;
- CodePatcher destroyer(code->instruction_start() + last_pc_offset,
- instructions);
- for (int x = 0; x < instructions; x++) {
- destroyer.masm()->bkpt(0);
- }
+ Address prev_call_address = NULL;
#endif
- last_pc_offset = pc_offset;
- if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) {
- Address deoptimization_entry = Deoptimizer::GetDeoptimizationEntry(
- deoptimization_index, Deoptimizer::LAZY);
- last_pc_offset += gap_code_size;
- int call_size_in_bytes = MacroAssembler::CallSize(deoptimization_entry,
- RelocInfo::NONE);
- int call_size_in_words = call_size_in_bytes / Assembler::kInstrSize;
- ASSERT(call_size_in_bytes % Assembler::kInstrSize == 0);
- ASSERT(call_size_in_bytes <= patch_size());
- CodePatcher patcher(code->instruction_start() + last_pc_offset,
- call_size_in_words);
- patcher.masm()->Call(deoptimization_entry, RelocInfo::NONE);
- last_pc_offset += call_size_in_bytes;
- }
- }
-
+ for (int i = 0; i < deopt_data->DeoptCount(); i++) {
+ if (deopt_data->Pc(i)->value() == -1) continue;
+ Address call_address = code_start_address + deopt_data->Pc(i)->value();
+ Address deopt_entry = GetDeoptimizationEntry(i, LAZY);
+ int call_size_in_bytes = MacroAssembler::CallSize(deopt_entry,
+ RelocInfo::NONE);
+ int call_size_in_words = call_size_in_bytes / Assembler::kInstrSize;
+ ASSERT(call_size_in_bytes % Assembler::kInstrSize == 0);
+ ASSERT(call_size_in_bytes <= patch_size());
+ CodePatcher patcher(call_address, call_size_in_words);
+ patcher.masm()->Call(deopt_entry, RelocInfo::NONE);
+ ASSERT(prev_call_address == NULL ||
+ call_address >= prev_call_address + patch_size());
+ ASSERT(call_address + patch_size() <= code->instruction_end());
#ifdef DEBUG
- // Destroy the code which is not supposed to be run again.
- int instructions =
- (code->safepoint_table_offset() - last_pc_offset) / Assembler::kInstrSize;
- CodePatcher destroyer(code->instruction_start() + last_pc_offset,
- instructions);
- for (int x = 0; x < instructions; x++) {
- destroyer.masm()->bkpt(0);
- }
+ prev_call_address = call_address;
#endif
+ }
// Add the deoptimizing code to the list.
DeoptimizingCodeListNode* node = new DeoptimizingCodeListNode(code);
@@ -125,11 +98,6 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
PrintF("[forced deoptimization: ");
function->PrintName();
PrintF(" / %x]\n", reinterpret_cast<uint32_t>(function));
-#ifdef DEBUG
- if (FLAG_print_code) {
- code->PrintLn();
- }
-#endif
}
}
View
222 deps/v8/src/arm/lithium-codegen-arm.cc
@@ -40,37 +40,22 @@ class SafepointGenerator : public CallWrapper {
public:
SafepointGenerator(LCodeGen* codegen,
LPointerMap* pointers,
- int deoptimization_index)
+ Safepoint::DeoptMode mode)
: codegen_(codegen),
pointers_(pointers),
- deoptimization_index_(deoptimization_index) { }
+ deopt_mode_(mode) { }
virtual ~SafepointGenerator() { }
- virtual void BeforeCall(int call_size) const {
- ASSERT(call_size >= 0);
- // Ensure that we have enough space after the previous safepoint position
- // for the generated code there.
- int call_end = codegen_->masm()->pc_offset() + call_size;
- int prev_jump_end =
- codegen_->LastSafepointEnd() + Deoptimizer::patch_size();
- if (call_end < prev_jump_end) {
- int padding_size = prev_jump_end - call_end;
- ASSERT_EQ(0, padding_size % Assembler::kInstrSize);
- while (padding_size > 0) {
- codegen_->masm()->nop();
- padding_size -= Assembler::kInstrSize;
- }
- }
- }
+ virtual void BeforeCall(int call_size) const { }
virtual void AfterCall() const {
- codegen_->RecordSafepoint(pointers_, deoptimization_index_);
+ codegen_->RecordSafepoint(pointers_, deopt_mode_);
}
private:
LCodeGen* codegen_;
LPointerMap* pointers_;
- int deoptimization_index_;
+ Safepoint::DeoptMode deopt_mode_;
};
@@ -95,7 +80,6 @@ void LCodeGen::FinishCode(Handle<Code> code) {
code->set_stack_slots(GetStackSlotCount());
code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
PopulateDeoptimizationData(code);
- Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
}
@@ -192,7 +176,7 @@ bool LCodeGen::GeneratePrologue() {
} else {
__ CallRuntime(Runtime::kNewFunctionContext, 1);
}
- RecordSafepoint(Safepoint::kNoDeoptimizationIndex);
+ RecordSafepoint(Safepoint::kNoLazyDeopt);
// Context is returned in both r0 and cp. It replaces the context
// passed to us. It's saved in the stack and kept live in cp.
__ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
@@ -243,19 +227,11 @@ bool LCodeGen::GenerateBody() {
instr->CompileToNative(this);
}
}
+ EnsureSpaceForLazyDeopt();
return !is_aborted();
}
-LInstruction* LCodeGen::GetNextInstruction() {
- if (current_instruction_ < instructions_->length() - 1) {
- return instructions_->at(current_instruction_ + 1);
- } else {
- return NULL;
- }
-}
-
-
bool LCodeGen::GenerateDeferredCode() {
ASSERT(is_generating());
if (deferred_.length() > 0) {
@@ -265,13 +241,6 @@ bool LCodeGen::GenerateDeferredCode() {
code->Generate();
__ jmp(code->exit());
}
-
- // Pad code to ensure that the last piece of deferred code have
- // room for lazy bailout.
- while ((masm()->pc_offset() - LastSafepointEnd())
- < Deoptimizer::patch_size()) {
- __ nop();
- }
}
// Force constant pool emission at the end of the deferred code to make
@@ -551,7 +520,7 @@ void LCodeGen::CallCodeGeneric(Handle<Code> code,
LPointerMap* pointers = instr->pointer_map();
RecordPosition(pointers->position());
__ Call(code, mode);
- RegisterLazyDeoptimization(instr, safepoint_mode);
+ RecordSafepointWithLazyDeopt(instr, safepoint_mode);
// Signal that we don't inline smi code before these stubs in the
// optimizing code generator.
@@ -571,7 +540,7 @@ void LCodeGen::CallRuntime(const Runtime::Function* function,
RecordPosition(pointers->position());
__ CallRuntime(function, num_arguments);
- RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT);
+ RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
}
@@ -580,37 +549,12 @@ void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
LInstruction* instr) {
__ CallRuntimeSaveDoubles(id);
RecordSafepointWithRegisters(
- instr->pointer_map(), argc, Safepoint::kNoDeoptimizationIndex);
+ instr->pointer_map(), argc, Safepoint::kNoLazyDeopt);
}
-void LCodeGen::RegisterLazyDeoptimization(LInstruction* instr,
- SafepointMode safepoint_mode) {
- // Create the environment to bailout to. If the call has side effects
- // execution has to continue after the call otherwise execution can continue
- // from a previous bailout point repeating the call.
- LEnvironment* deoptimization_environment;
- if (instr->HasDeoptimizationEnvironment()) {
- deoptimization_environment = instr->deoptimization_environment();
- } else {
- deoptimization_environment = instr->environment();
- }
-
- RegisterEnvironmentForDeoptimization(deoptimization_environment);
- if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
- RecordSafepoint(instr->pointer_map(),
- deoptimization_environment->deoptimization_index());
- } else {
- ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
- RecordSafepointWithRegisters(
- instr->pointer_map(),
- 0,
- deoptimization_environment->deoptimization_index());
- }
-}
-
-
-void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment) {
+void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
+ Safepoint::DeoptMode mode) {
if (!environment->HasBeenRegistered()) {
// Physical stack frame layout:
// -x ............. -4 0 ..................................... y
@@ -632,14 +576,17 @@ void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment) {
Translation translation(&translations_, frame_count);
WriteTranslation(environment, &translation);
int deoptimization_index = deoptimizations_.length();
- environment->Register(deoptimization_index, translation.index());
+ int pc_offset = masm()->pc_offset();
+ environment->Register(deoptimization_index,
+ translation.index(),
+ (mode == Safepoint::kLazyDeopt) ? pc_offset : -1);
deoptimizations_.Add(environment);
}
}
void LCodeGen::DeoptimizeIf(Condition cc, LEnvironment* environment) {
- RegisterEnvironmentForDeoptimization(environment);
+ RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
ASSERT(environment->HasBeenRegistered());
int id = environment->deoptimization_index();
Address entry = Deoptimizer::GetDeoptimizationEntry(id, Deoptimizer::EAGER);
@@ -701,6 +648,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
data->SetTranslationIndex(i, Smi::FromInt(env->translation_index()));
data->SetArgumentsStackHeight(i,
Smi::FromInt(env->arguments_stack_height()));
+ data->SetPc(i, Smi::FromInt(env->pc_offset()));
}
code->set_deoptimization_data(*data);
}
@@ -732,16 +680,28 @@ void LCodeGen::PopulateDeoptimizationLiteralsWithInlinedFunctions() {
}
+void LCodeGen::RecordSafepointWithLazyDeopt(
+ LInstruction* instr, SafepointMode safepoint_mode) {
+ if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
+ RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt);
+ } else {
+ ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
+ RecordSafepointWithRegisters(
+ instr->pointer_map(), 0, Safepoint::kLazyDeopt);
+ }
+}
+
+
void LCodeGen::RecordSafepoint(
LPointerMap* pointers,
Safepoint::Kind kind,
int arguments,
- int deoptimization_index) {
+ Safepoint::DeoptMode deopt_mode) {
ASSERT(expected_safepoint_kind_ == kind);
const ZoneList<LOperand*>* operands = pointers->operands();
Safepoint safepoint = safepoints_.DefineSafepoint(masm(),
- kind, arguments, deoptimization_index);
+ kind, arguments, deopt_mode);
for (int i = 0; i < operands->length(); i++) {
LOperand* pointer = operands->at(i);
if (pointer->IsStackSlot()) {
@@ -758,31 +718,31 @@ void LCodeGen::RecordSafepoint(
void LCodeGen::RecordSafepoint(LPointerMap* pointers,
- int deoptimization_index) {
- RecordSafepoint(pointers, Safepoint::kSimple, 0, deoptimization_index);
+ Safepoint::DeoptMode deopt_mode) {
+ RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode);
}
-void LCodeGen::RecordSafepoint(int deoptimization_index) {
+void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) {
LPointerMap empty_pointers(RelocInfo::kNoPosition);
- RecordSafepoint(&empty_pointers, deoptimization_index);
+ RecordSafepoint(&empty_pointers, deopt_mode);
}
void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
int arguments,
- int deoptimization_index) {
- RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments,
- deoptimization_index);
+ Safepoint::DeoptMode deopt_mode) {
+ RecordSafepoint(
+ pointers, Safepoint::kWithRegisters, arguments, deopt_mode);
}
void LCodeGen::RecordSafepointWithRegistersAndDoubles(
LPointerMap* pointers,
int arguments,
- int deoptimization_index) {
- RecordSafepoint(pointers, Safepoint::kWithRegistersAndDoubles, arguments,
- deoptimization_index);
+ Safepoint::DeoptMode deopt_mode) {
+ RecordSafepoint(
+ pointers, Safepoint::kWithRegistersAndDoubles, arguments, deopt_mode);
}
@@ -817,12 +777,6 @@ void LCodeGen::DoGap(LGap* gap) {
LParallelMove* move = gap->GetParallelMove(inner_pos);
if (move != NULL) DoParallelMove(move);
}
-
- LInstruction* next = GetNextInstruction();
- if (next != NULL && next->IsLazyBailout()) {
- int pc = masm()->pc_offset();
- safepoints_.SetPcAfterGap(pc);
- }
}
@@ -1129,7 +1083,7 @@ void LCodeGen::DoDeferredBinaryOpStub(LTemplateInstruction<1, 2, T>* instr,
__ CallStub(&stub);
RecordSafepointWithRegistersAndDoubles(instr->pointer_map(),
0,
- Safepoint::kNoDeoptimizationIndex);
+ Safepoint::kNoLazyDeopt);
// Overwrite the stored value of r0 with the result of the stub.
__ StoreToSafepointRegistersAndDoublesSlot(r0, r0);
}
@@ -2014,7 +1968,7 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
LInstanceOfKnownGlobal* instr)
: LDeferredCode(codegen), instr_(instr) { }
virtual void Generate() {
- codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_);
+ codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_);
}
Label* map_check() { return &map_check_; }
@@ -2082,8 +2036,8 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
}
-void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
- Label* map_check) {
+void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
+ Label* map_check) {
Register result = ToRegister(instr->result());
ASSERT(result.is(r0));
@@ -2115,6 +2069,9 @@ void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
RelocInfo::CODE_TARGET,
instr,
RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
+ ASSERT(instr->HasDeoptimizationEnvironment());
+ LEnvironment* env = instr->deoptimization_environment();
+ safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
// Put the result value into the result register slot and
// restore all registers.
__ StoreToSafepointRegisterSlot(result, result);
@@ -2712,12 +2669,9 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
__ bind(&invoke);
ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
LPointerMap* pointers = instr->pointer_map();
- LEnvironment* env = instr->deoptimization_environment();
RecordPosition(pointers->position());
- RegisterEnvironmentForDeoptimization(env);
- SafepointGenerator safepoint_generator(this,
- pointers,
- env->deoptimization_index());
+ SafepointGenerator safepoint_generator(
+ this, pointers, Safepoint::kLazyDeopt);
// The number of arguments is stored in receiver which is r0, as expected
// by InvokeFunction.
v8::internal::ParameterCount actual(receiver);
@@ -2799,7 +2753,7 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
__ Call(ip);
// Setup deoptimization.
- RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT);
+ RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
// Restore context.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
@@ -3163,10 +3117,8 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
ASSERT(instr->HasPointerMap());
ASSERT(instr->HasDeoptimizationEnvironment());
LPointerMap* pointers = instr->pointer_map();
- LEnvironment* env = instr->deoptimization_environment();
RecordPosition(pointers->position());
- RegisterEnvironmentForDeoptimization(env);
- SafepointGenerator generator(this, pointers, env->deoptimization_index());
+ SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
ParameterCount count(instr->arity());
__ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
@@ -4403,9 +4355,29 @@ void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) {
}
+void LCodeGen::EnsureSpaceForLazyDeopt() {
+ // Ensure that we have enough space after the previous lazy-bailout
+ // instruction for patching the code here.
+ int current_pc = masm()->pc_offset();
+ int patch_size = Deoptimizer::patch_size();
+ if (current_pc < last_lazy_deopt_pc_ + patch_size) {
+ int padding_size = last_lazy_deopt_pc_ + patch_size - current_pc;
+ ASSERT_EQ(0, padding_size % Assembler::kInstrSize);
+ while (padding_size > 0) {
+ __ nop();
+ padding_size -= Assembler::kInstrSize;
+ }
+ }
+ last_lazy_deopt_pc_ = masm()->pc_offset();
+}
+
+
void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
- // No code for lazy bailout instruction. Used to capture environment after a
- // call for populating the safepoint data with deoptimization data.
+ EnsureSpaceForLazyDeopt();
+ ASSERT(instr->HasEnvironment());
+ LEnvironment* env = instr->environment();
+ RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
+ safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
}
@@ -4422,12 +4394,9 @@ void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
__ Push(object, key, strict);
ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
LPointerMap* pointers = instr->pointer_map();
- LEnvironment* env = instr->deoptimization_environment();
RecordPosition(pointers->position());
- RegisterEnvironmentForDeoptimization(env);
- SafepointGenerator safepoint_generator(this,
- pointers,
- env->deoptimization_index());
+ SafepointGenerator safepoint_generator(
+ this, pointers, Safepoint::kLazyDeopt);
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator);
}
@@ -4438,27 +4407,20 @@ void LCodeGen::DoIn(LIn* instr) {
__ Push(key, obj);
ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
LPointerMap* pointers = instr->pointer_map();
- LEnvironment* env = instr->deoptimization_environment();
RecordPosition(pointers->position());
- RegisterEnvironmentForDeoptimization(env);
- SafepointGenerator safepoint_generator(this,
- pointers,
- env->deoptimization_index());
+ SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt);
__ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator);
}
void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
- {
- PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
- __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
- RegisterLazyDeoptimization(
- instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
- }
-
- // The gap code includes the restoring of the safepoint registers.
- int pc = masm()->pc_offset();
- safepoints_.SetPcAfterGap(pc);
+ PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
+ __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
+ RecordSafepointWithLazyDeopt(
+ instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
+ ASSERT(instr->HasEnvironment());
+ LEnvironment* env = instr->environment();
+ safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
}
@@ -4472,6 +4434,10 @@ void LCodeGen::DoStackCheck(LStackCheck* instr) {
LStackCheck* instr_;
};
+ ASSERT(instr->HasEnvironment());
+ LEnvironment* env = instr->environment();
+ // There is no LLazyBailout instruction for stack-checks. We have to
+ // prepare for lazy deoptimization explicitly here.
if (instr->hydrogen()->is_function_entry()) {
// Perform stack overflow check.
Label done;
@@ -4480,7 +4446,10 @@ void LCodeGen::DoStackCheck(LStackCheck* instr) {
__ b(hs, &done);
StackCheckStub stub;
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ EnsureSpaceForLazyDeopt();
__ bind(&done);
+ RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
+ safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
} else {
ASSERT(instr->hydrogen()->is_backwards_branch());
// Perform stack overflow check if this goto needs it before jumping.
@@ -4489,8 +4458,13 @@ void LCodeGen::DoStackCheck(LStackCheck* instr) {
__ LoadRoot(ip, Heap::kStackLimitRootIndex);
__ cmp(sp, Operand(ip));
__ b(lo, deferred_stack_check->entry());
+ EnsureSpaceForLazyDeopt();
__ bind(instr->done_label());
deferred_stack_check->SetExit(instr->done_label());
+ RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
+ // Don't record a deoptimization index for the safepoint here.
+ // This will be done explicitly when emitting call and the safepoint in
+ // the deferred code.
}
}
@@ -4506,7 +4480,7 @@ void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
// If the environment were already registered, we would have no way of
// backpatching it with the spill slot operands.
ASSERT(!environment->HasBeenRegistered());
- RegisterEnvironmentForDeoptimization(environment);
+ RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
ASSERT(osr_pc_offset_ == -1);
osr_pc_offset_ = masm()->pc_offset();
}
View
30 deps/v8/src/arm/lithium-codegen-arm.h
@@ -58,6 +58,7 @@ class LCodeGen BASE_EMBEDDED {
status_(UNUSED),
deferred_(8),
osr_pc_offset_(-1),
+ last_lazy_deopt_pc_(0),
resolver_(this),
expected_safepoint_kind_(Safepoint::kSimple) {
PopulateDeoptimizationLiteralsWithInlinedFunctions();
@@ -111,8 +112,8 @@ class LCodeGen BASE_EMBEDDED {
void DoDeferredStackCheck(LStackCheck* instr);
void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
- void DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
- Label* map_check);
+ void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
+ Label* map_check);
// Parallel move support.
void DoParallelMove(LParallelMove* move);
@@ -148,7 +149,7 @@ class LCodeGen BASE_EMBEDDED {
HGraph* graph() const { return chunk_->graph(); }
Register scratch0() { return r9; }
- DwVfpRegister double_scratch0() { return d15; }
+ DwVfpRegister double_scratch0() { return kScratchDoubleReg; }
int GetNextEmittedBlock(int block);
LInstruction* GetNextInstruction();
@@ -214,10 +215,11 @@ class LCodeGen BASE_EMBEDDED {
void LoadHeapObject(Register result, Handle<HeapObject> object);
- void RegisterLazyDeoptimization(LInstruction* instr,
- SafepointMode safepoint_mode);
+ void RecordSafepointWithLazyDeopt(LInstruction* instr,
+ SafepointMode safepoint_mode);
- void RegisterEnvironmentForDeoptimization(LEnvironment* environment);
+ void RegisterEnvironmentForDeoptimization(LEnvironment* environment,
+ Safepoint::DeoptMode mode);
void DeoptimizeIf(Condition cc, LEnvironment* environment);
void AddToTranslation(Translation* translation,
@@ -246,19 +248,16 @@ class LCodeGen BASE_EMBEDDED {
void RecordSafepoint(LPointerMap* pointers,
Safepoint::Kind kind,
int arguments,
- int deoptimization_index);
- void RecordSafepoint(LPointerMap* pointers, int deoptimization_index);
- void RecordSafepoint(int deoptimization_index);
+ Safepoint::DeoptMode mode);
+ void RecordSafepoint(LPointerMap* pointers, Safepoint::DeoptMode mode);
+ void RecordSafepoint(Safepoint::DeoptMode mode);
void RecordSafepointWithRegisters(LPointerMap* pointers,
int arguments,
- int deoptimization_index);
+ Safepoint::DeoptMode mode);
void RecordSafepointWithRegistersAndDoubles(LPointerMap* pointers,
int arguments,
- int deoptimization_index);
+ Safepoint::DeoptMode mode);
void RecordPosition(int position);
- int LastSafepointEnd() {
- return static_cast<int>(safepoints_.GetPcAfterGap());
- }
static Condition TokenToCondition(Token::Value op, bool is_unsigned);
void EmitGoto(int block);
@@ -300,6 +299,8 @@ class LCodeGen BASE_EMBEDDED {
Address address;
};
+ void EnsureSpaceForLazyDeopt();
+
LChunk* const chunk_;
MacroAssembler* const masm_;
CompilationInfo* const info_;
@@ -316,6 +317,7 @@ class LCodeGen BASE_EMBEDDED {
TranslationBuffer translations_;
ZoneList<LDeferredCode*> deferred_;
int osr_pc_offset_;
+ int last_lazy_deopt_pc_;
// Builder that keeps track of safepoints in the code. The table
// itself is emitted at the end of the generated code.
View
21 deps/v8/src/arm/lithium-gap-resolver-arm.cc
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 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:
@@ -34,7 +34,6 @@ namespace v8 {
namespace internal {
static const Register kSavedValueRegister = { 9 };
-static const DoubleRegister kSavedDoubleValueRegister = { 0 };
LGapResolver::LGapResolver(LCodeGen* owner)
: cgen_(owner), moves_(32), root_index_(0), in_cycle_(false),
@@ -172,9 +171,9 @@ void LGapResolver::BreakCycle(int index) {
} else if (source->IsStackSlot()) {
__ ldr(kSavedValueRegister, cgen_->ToMemOperand(source));
} else if (source->IsDoubleRegister()) {
- __ vmov(kSavedDoubleValueRegister, cgen_->ToDoubleRegister(source));
+ __ vmov(kScratchDoubleReg, cgen_->ToDoubleRegister(source));
} else if (source->IsDoubleStackSlot()) {
- __ vldr(kSavedDoubleValueRegister, cgen_->ToMemOperand(source));
+ __ vldr(kScratchDoubleReg, cgen_->ToMemOperand(source));
} else {
UNREACHABLE();
}
@@ -193,11 +192,9 @@ void LGapResolver::RestoreValue() {
} else if (saved_destination_->IsStackSlot()) {
__ str(kSavedValueRegister, cgen_->ToMemOperand(saved_destination_));
} else if (saved_destination_->IsDoubleRegister()) {
- __ vmov(cgen_->ToDoubleRegister(saved_destination_),
- kSavedDoubleValueRegister);
+ __ vmov(cgen_->ToDoubleRegister(saved_destination_), kScratchDoubleReg);
} else if (saved_destination_->IsDoubleStackSlot()) {
- __ vstr(kSavedDoubleValueRegister,
- cgen_->ToMemOperand(saved_destination_));
+ __ vstr(kScratchDoubleReg, cgen_->ToMemOperand(saved_destination_));
} else {
UNREACHABLE();
}
@@ -235,8 +232,8 @@ void LGapResolver::EmitMove(int index) {
// ip is overwritten while saving the value to the destination.
// Therefore we can't use ip. It is OK if the read from the source
// destroys ip, since that happens before the value is read.
- __ vldr(kSavedDoubleValueRegister.low(), source_operand);
- __ vstr(kSavedDoubleValueRegister.low(), destination_operand);
+ __ vldr(kScratchDoubleReg.low(), source_operand);
+ __ vstr(kScratchDoubleReg.low(), destination_operand);
} else {
__ ldr(ip, source_operand);
__ str(ip, destination_operand);
@@ -286,8 +283,8 @@ void LGapResolver::EmitMove(int index) {
__ ldr(kSavedValueRegister, source_high_operand);
__ str(kSavedValueRegister, destination_high_operand);
} else {
- __ vldr(kSavedDoubleValueRegister, source_operand);
- __ vstr(kSavedDoubleValueRegister, destination_operand);
+ __ vldr(kScratchDoubleReg, source_operand);
+ __ vstr(kScratchDoubleReg, destination_operand);
}
}
} else {
View
18 deps/v8/src/deoptimizer.cc
@@ -112,25 +112,11 @@ DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame(
// Get the function and code from the frame.
JSFunction* function = JSFunction::cast(frame->function());
Code* code = frame->LookupCode();
- Address code_start_address = code->instruction_start();
// Locate the deoptimization point in the code. As we are at a call the
// return address must be at a place in the code with deoptimization support.
- int deoptimization_index = Safepoint::kNoDeoptimizationIndex;
- // Scope this as the safe point constructor will disallow allocation.
- {
- SafepointTable table(code);
- for (unsigned i = 0; i < table.length(); ++i) {
- Address address = code_start_address + table.GetPcOffset(i);
- if (address == frame->pc()) {
- SafepointEntry safepoint_entry = table.GetEntry(i);
- ASSERT(safepoint_entry.deoptimization_index() !=
- Safepoint::kNoDeoptimizationIndex);
- deoptimization_index = safepoint_entry.deoptimization_index();
- break;
- }
- }
- }
+ SafepointEntry safepoint_entry = code->GetSafepointEntry(frame->pc());
+ int deoptimization_index = safepoint_entry.deoptimization_index();
ASSERT(deoptimization_index != Safepoint::kNoDeoptimizationIndex);
// Always use the actual stack slots when calculating the fp to sp
View
1  deps/v8/src/hydrogen-instructions.h
@@ -4058,6 +4058,7 @@ class HRegExpLiteral: public HMaterializedLiteral<1> {
pattern_(pattern),
flags_(flags) {
SetOperandAt(0, context);
+ SetAllSideEffects();
}
HValue* context() { return OperandAt(0); }
View
6 deps/v8/src/ia32/code-stubs-ia32.cc
@@ -5665,14 +5665,12 @@ void StringHelper::GenerateHashGetHash(MacroAssembler* masm,
__ shl(scratch, 15);
__ add(hash, Operand(scratch));
- uint32_t kHashShiftCutOffMask = (1 << (32 - String::kHashShift)) - 1;
- __ and_(hash, kHashShiftCutOffMask);
+ __ and_(hash, String::kHashBitMask);
// if (hash == 0) hash = 27;
Label hash_not_zero;
- __ test(hash, Operand(hash));
__ j(not_zero, &hash_not_zero, Label::kNear);
- __ mov(hash, Immediate(27));
+ __ mov(hash, Immediate(StringHasher::kZeroHash));
__ bind(&hash_not_zero);
}
View
116 deps/v8/src/ia32/deoptimizer-ia32.cc
@@ -45,16 +45,6 @@ int Deoptimizer::patch_size() {
}
-static void ZapCodeRange(Address start, Address end) {
-#ifdef DEBUG
- ASSERT(start <= end);
- int size = end - start;
- CodePatcher destroyer(start, size);
- while (size-- > 0) destroyer.masm()->int3();
-#endif
-}
-
-
void Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code) {
Isolate* isolate = code->GetIsolate();
HandleScope scope(isolate);
@@ -62,30 +52,23 @@ void Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code) {
// Compute the size of relocation information needed for the code
// patching in Deoptimizer::DeoptimizeFunction.
int min_reloc_size = 0;
- Address prev_reloc_address = code->instruction_start();
- Address code_start_address = code->instruction_start();
- SafepointTable table(*code);
- for (unsigned i = 0; i < table.length(); ++i) {
- Address curr_reloc_address = code_start_address + table.GetPcOffset(i);
- ASSERT_GE(curr_reloc_address, prev_reloc_address);
- SafepointEntry safepoint_entry = table.GetEntry(i);
- int deoptimization_index = safepoint_entry.deoptimization_index();
- if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) {
- // The gap code is needed to get to the state expected at the
- // bailout and we need to skip the call opcode to get to the
- // address that needs reloc.
- curr_reloc_address += safepoint_entry.gap_code_size() + 1;
- int pc_delta = curr_reloc_address - prev_reloc_address;
- // We use RUNTIME_ENTRY reloc info which has a size of 2 bytes
- // if encodable with small pc delta encoding and up to 6 bytes
- // otherwise.
- if (pc_delta <= RelocInfo::kMaxSmallPCDelta) {
- min_reloc_size += 2;
- } else {
- min_reloc_size += 6;
- }
- prev_reloc_address = curr_reloc_address;
+ int prev_pc_offset = 0;
+ DeoptimizationInputData* deopt_data =
+ DeoptimizationInputData::cast(code->deoptimization_data());
+ for (int i = 0; i < deopt_data->DeoptCount(); i++) {
+ int pc_offset = deopt_data->Pc(i)->value();
+ if (pc_offset == -1) continue;
+ ASSERT_GE(pc_offset, prev_pc_offset);
+ int pc_delta = pc_offset - prev_pc_offset;
+ // We use RUNTIME_ENTRY reloc info which has a size of 2 bytes
+ // if encodable with small pc delta encoding and up to 6 bytes
+ // otherwise.
+ if (pc_delta <= RelocInfo::kMaxSmallPCDelta) {
+ min_reloc_size += 2;
+ } else {
+ min_reloc_size += 6;
}
+ prev_pc_offset = pc_offset;
}
// If the relocation information is not big enough we create a new
@@ -150,40 +133,40 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
Address reloc_end_address = reloc_info->address() + reloc_info->Size();
RelocInfoWriter reloc_info_writer(reloc_end_address, code_start_address);
- // For each return after a safepoint insert a call to the corresponding
- // deoptimization entry. Since the call is a relative encoding, write new
+ // For each LLazyBailout instruction insert a call to the corresponding
+ // deoptimization entry.
+
+ // Since the call is a relative encoding, write new
// reloc info. We do not need any of the existing reloc info because the
// existing code will not be used again (we zap it in debug builds).
- SafepointTable table(code);
- Address prev_address = code_start_address;
- for (unsigned i = 0; i < table.length(); ++i) {
- Address curr_address = code_start_address + table.GetPcOffset(i);
- ASSERT_GE(curr_address, prev_address);
- ZapCodeRange(prev_address, curr_address);
-
- SafepointEntry safepoint_entry = table.GetEntry(i);
- int deoptimization_index = safepoint_entry.deoptimization_index();
- if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) {
- // The gap code is needed to get to the state expected at the bailout.
- curr_address += safepoint_entry.gap_code_size();
-
- CodePatcher patcher(curr_address, patch_size());
- Address deopt_entry = GetDeoptimizationEntry(deoptimization_index, LAZY);
- patcher.masm()->call(deopt_entry, RelocInfo::NONE);
-
- // We use RUNTIME_ENTRY for deoptimization bailouts.
- RelocInfo rinfo(curr_address + 1, // 1 after the call opcode.
- RelocInfo::RUNTIME_ENTRY,
- reinterpret_cast<intptr_t>(deopt_entry));
- reloc_info_writer.Write(&rinfo);
- ASSERT_GE(reloc_info_writer.pos(),
- reloc_info->address() + ByteArray::kHeaderSize);
- curr_address += patch_size();
- }
- prev_address = curr_address;
+ //
+ // Emit call to lazy deoptimization at all lazy deopt points.
+ DeoptimizationInputData* deopt_data =
+ DeoptimizationInputData::cast(code->deoptimization_data());
+#ifdef DEBUG
+ Address prev_call_address = NULL;
+#endif
+ for (int i = 0; i < deopt_data->DeoptCount(); i++) {
+ if (deopt_data->Pc(i)->value() == -1) continue;
+ // Patch lazy deoptimization entry.
+ Address call_address = code_start_address + deopt_data->Pc(i)->value();
+ CodePatcher patcher(call_address, patch_size());
+ Address deopt_entry = GetDeoptimizationEntry(i, LAZY);
+ patcher.masm()->call(deopt_entry, RelocInfo::NONE);
+ // We use RUNTIME_ENTRY for deoptimization bailouts.
+ RelocInfo rinfo(call_address + 1, // 1 after the call opcode.
+ RelocInfo::RUNTIME_ENTRY,
+ reinterpret_cast<intptr_t>(deopt_entry));
+ reloc_info_writer.Write(&rinfo);
+ ASSERT_GE(reloc_info_writer.pos(),
+ reloc_info->address() + ByteArray::kHeaderSize);
+ ASSERT(prev_call_address == NULL ||
+ call_address >= prev_call_address + patch_size());
+ ASSERT(call_address + patch_size() <= code->instruction_end());
+#ifdef DEBUG
+ prev_call_address = call_address;
+#endif
}
- ZapCodeRange(prev_address,
- code_start_address + code->safepoint_table_offset());
// Move the relocation info to the beginning of the byte array.
int new_reloc_size = reloc_end_address - reloc_info_writer.pos();
@@ -212,11 +195,6 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
PrintF("[forced deoptimization: ");
function->PrintName();
PrintF(" / %x]\n", reinterpret_cast<uint32_t>(function));
-#ifdef DEBUG
- if (FLAG_print_code) {
- code->PrintLn();
- }
-#endif
}
}
View
212 deps/v8/src/ia32/lithium-codegen-ia32.cc
@@ -44,22 +44,22 @@ class SafepointGenerator : public CallWrapper {
public:
SafepointGenerator(LCodeGen* codegen,
LPointerMap* pointers,
- int deoptimization_index)
+ Safepoint::DeoptMode mode)
: codegen_(codegen),
pointers_(pointers),
- deoptimization_index_(deoptimization_index) {}
+ deopt_mode_(mode) {}
virtual ~SafepointGenerator() { }
virtual void BeforeCall(int call_size) const {}
virtual void AfterCall() const {
- codegen_->RecordSafepoint(pointers_, deoptimization_index_);
+ codegen_->RecordSafepoint(pointers_, deopt_mode_);
}
private:
LCodeGen* codegen_;
LPointerMap* pointers_;
- int deoptimization_index_;
+ Safepoint::DeoptMode deopt_mode_;
};
@@ -187,7 +187,7 @@ bool LCodeGen::GeneratePrologue() {
} else {
__ CallRuntime(Runtime::kNewFunctionContext, 1);
}
- RecordSafepoint(Safepoint::kNoDeoptimizationIndex);
+ RecordSafepoint(Safepoint::kNoLazyDeopt);
// Context is returned in both eax and esi. It replaces the context
// passed to us. It's saved in the stack and kept live in esi.
__ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
@@ -241,19 +241,11 @@ bool LCodeGen::GenerateBody() {
instr->CompileToNative(this);
}
}
+ EnsureSpaceForLazyDeopt();
return !is_aborted();
}
-LInstruction* LCodeGen::GetNextInstruction() {
- if (current_instruction_ < instructions_->length() - 1) {
- return instructions_->at(current_instruction_ + 1);
- } else {
- return NULL;
- }
-}
-
-
bool LCodeGen::GenerateDeferredCode() {
ASSERT(is_generating());
if (deferred_.length() > 0) {
@@ -263,13 +255,6 @@ bool LCodeGen::GenerateDeferredCode() {
code->Generate();
__ jmp(code->exit());
}
-
- // Pad code to ensure that the last piece of deferred code have
- // room for lazy bailout.
- while ((masm()->pc_offset() - LastSafepointEnd())
- < Deoptimizer::patch_size()) {
- __ nop();
- }
}
// Deferred code is the last part of the instruction sequence. Mark
@@ -442,10 +427,8 @@ void LCodeGen::CallCodeGeneric(Handle<Code> code,
ASSERT(instr != NULL);
LPointerMap* pointers = instr->pointer_map();
RecordPosition(pointers->position());
-
__ call(code, mode);
-
- RegisterLazyDeoptimization(instr, safepoint_mode);
+ RecordSafepointWithLazyDeopt(instr, safepoint_mode);
// Signal that we don't inline smi code before these stubs in the
// optimizing code generator.
@@ -473,7 +456,7 @@ void LCodeGen::CallRuntime(const Runtime::Function* fun,
__ CallRuntime(fun, argc);
- RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT);
+ RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
}
@@ -493,37 +476,12 @@ void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
__ CallRuntimeSaveDoubles(id);
RecordSafepointWithRegisters(
- instr->pointer_map(), argc, Safepoint::kNoDeoptimizationIndex);
+ instr->pointer_map(), argc, Safepoint::kNoLazyDeopt);
}
-void LCodeGen::RegisterLazyDeoptimization(LInstruction* instr,
- SafepointMode safepoint_mode) {
- // Create the environment to bailout to. If the call has side effects
- // execution has to continue after the call otherwise execution can continue
- // from a previous bailout point repeating the call.
- LEnvironment* deoptimization_environment;
- if (instr->HasDeoptimizationEnvironment()) {
- deoptimization_environment = instr->deoptimization_environment();
- } else {
- deoptimization_environment = instr->environment();
- }
-
- RegisterEnvironmentForDeoptimization(deoptimization_environment);
- if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
- RecordSafepoint(instr->pointer_map(),
- deoptimization_environment->deoptimization_index());
- } else {
- ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
- RecordSafepointWithRegisters(
- instr->pointer_map(),
- 0,
- deoptimization_environment->deoptimization_index());
- }
-}
-
-
-void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment) {
+void LCodeGen::RegisterEnvironmentForDeoptimization(
+ LEnvironment* environment, Safepoint::DeoptMode mode) {
if (!environment->HasBeenRegistered()) {
// Physical stack frame layout:
// -x ............. -4 0 ..................................... y
@@ -545,14 +503,17 @@ void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment) {
Translation translation(&translations_, frame_count);
WriteTranslation(environment, &translation);
int deoptimization_index = deoptimizations_.length();
- environment->Register(deoptimization_index, translation.index());
+ int pc_offset = masm()->pc_offset();
+ environment->Register(deoptimization_index,
+ translation.index(),
+ (mode == Safepoint::kLazyDeopt) ? pc_offset : -1);
deoptimizations_.Add(environment);
}
}
void LCodeGen::DeoptimizeIf(Condition cc, LEnvironment* environment) {
- RegisterEnvironmentForDeoptimization(environment);
+ RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
ASSERT(environment->HasBeenRegistered());
int id = environment->deoptimization_index();
Address entry = Deoptimizer::GetDeoptimizationEntry(id, Deoptimizer::EAGER);
@@ -632,6 +593,7 @@ void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
data->SetTranslationIndex(i, Smi::FromInt(env->translation_index()));
data->SetArgumentsStackHeight(i,
Smi::FromInt(env->arguments_stack_height()));
+ data->SetPc(i, Smi::FromInt(env->pc_offset()));
}
code->set_deoptimization_data(*data);
}
@@ -663,15 +625,27 @@ void LCodeGen::PopulateDeoptimizationLiteralsWithInlinedFunctions() {
}
+void LCodeGen::RecordSafepointWithLazyDeopt(
+ LInstruction* instr, SafepointMode safepoint_mode) {
+ if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
+ RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt);
+ } else {
+ ASSERT(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
+ RecordSafepointWithRegisters(
+ instr->pointer_map(), 0, Safepoint::kLazyDeopt);
+ }
+}
+
+
void LCodeGen::RecordSafepoint(
LPointerMap* pointers,
Safepoint::Kind kind,
int arguments,
- int deoptimization_index) {
+ Safepoint::DeoptMode deopt_mode) {
ASSERT(kind == expected_safepoint_kind_);
const ZoneList<LOperand*>* operands = pointers->operands();
- Safepoint safepoint = safepoints_.DefineSafepoint(masm(),
- kind, arguments, deoptimization_index);
+ Safepoint safepoint =
+ safepoints_.DefineSafepoint(masm(), kind, arguments, deopt_mode);
for (int i = 0; i < operands->length(); i++) {
LOperand* pointer = operands->at(i);
if (pointer->IsStackSlot()) {
@@ -684,22 +658,21 @@ void LCodeGen::RecordSafepoint(
void LCodeGen::RecordSafepoint(LPointerMap* pointers,
- int deoptimization_index) {
- RecordSafepoint(pointers, Safepoint::kSimple, 0, deoptimization_index);
+ Safepoint::DeoptMode mode) {
+ RecordSafepoint(pointers, Safepoint::kSimple, 0, mode);
}
-void LCodeGen::RecordSafepoint(int deoptimization_index) {
+void LCodeGen::RecordSafepoint(Safepoint::DeoptMode mode) {
LPointerMap empty_pointers(RelocInfo::kNoPosition);
- RecordSafepoint(&empty_pointers, deoptimization_index);
+ RecordSafepoint(&empty_pointers, mode);
}
void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
int arguments,
- int deoptimization_index) {
- RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments,
- deoptimization_index);
+ Safepoint::DeoptMode mode) {
+ RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, mode);
}
@@ -734,12 +707,6 @@ void LCodeGen::DoGap(LGap* gap) {
LParallelMove* move = gap->GetParallelMove(inner_pos);
if (move != NULL) DoParallelMove(move);
}
-
- LInstruction* next = GetNextInstruction();
- if (next != NULL && next->IsLazyBailout()) {
- int pc = masm()->pc_offset();
- safepoints_.SetPcAfterGap(pc);
- }
}
@@ -1849,7 +1816,7 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
LInstanceOfKnownGlobal* instr)
: LDeferredCode(codegen), instr_(instr) { }
virtual void Generate() {
- codegen()->DoDeferredLInstanceOfKnownGlobal(instr_, &map_check_);
+ codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_);
}
Label* map_check() { return &map_check_; }
@@ -1905,8 +1872,8 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
}
-void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
- Label* map_check) {
+void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
+ Label* map_check) {
PushSafepointRegistersScope scope(this);
InstanceofStub::Flags flags = InstanceofStub::kNoFlags;
@@ -1933,6 +1900,10 @@ void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
RelocInfo::CODE_TARGET,
instr,
RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
+ ASSERT(instr->HasDeoptimizationEnvironment());
+ LEnvironment* env = instr->deoptimization_environment();
+ safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
+
// Put the result value into the eax slot and restore all registers.
__ StoreToSafepointRegisterSlot(eax, eax);
}
@@ -2502,12 +2473,9 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
__ bind(&invoke);
ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
LPointerMap* pointers = instr->pointer_map();
- LEnvironment* env = instr->deoptimization_environment();
RecordPosition(pointers->position());
- RegisterEnvironmentForDeoptimization(env);
- SafepointGenerator safepoint_generator(this,
- pointers,
- env->deoptimization_index());
+ SafepointGenerator safepoint_generator(
+ this, pointers, Safepoint::kLazyDeopt);
ParameterCount actual(eax);
__ InvokeFunction(function, actual, CALL_FUNCTION,
safepoint_generator, CALL_AS_METHOD);
@@ -2590,8 +2558,7 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
__ call(FieldOperand(edi, JSFunction::kCodeEntryOffset));
}
- // Setup deoptimization.
- RegisterLazyDeoptimization(instr, RECORD_SIMPLE_SAFEPOINT);
+ RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
}
@@ -2966,10 +2933,9 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
ASSERT(instr->HasPointerMap());
ASSERT(instr->HasDeoptimizationEnvironment());
LPointerMap* pointers = instr->pointer_map();
- LEnvironment* env = instr->deoptimization_environment();
RecordPosition(pointers->position());
- RegisterEnvironmentForDeoptimization(env);
- SafepointGenerator generator(this, pointers, env->deoptimization_index());
+ SafepointGenerator generator(
+ this, pointers, Safepoint::kLazyDeopt);
ParameterCount count(instr->arity());
__ InvokeFunction(edi, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
}
@@ -3463,7 +3429,7 @@ void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) {
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
RecordSafepointWithRegisters(
- instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
+ instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
if (!reg.is(eax)) __ mov(reg, eax);
// Done. Put the value in xmm0 into the value of the allocated heap
@@ -3514,8 +3480,8 @@ void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
// not have easy access to the local context.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
- RecordSafepointWithRegisters(instr->pointer_map(), 0,
- Safepoint::kNoDeoptimizationIndex);
+ RecordSafepointWithRegisters(
+ instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
__ StoreToSafepointRegisterSlot(reg, eax);
}
@@ -4246,9 +4212,27 @@ void LCodeGen::EmitIsConstructCall(Register temp) {
}
+void LCodeGen::EnsureSpaceForLazyDeopt() {
+ // Ensure that we have enough space after the previous lazy-bailout
+ // instruction for patching the code here.
+ int current_pc = masm()->pc_offset();
+ int patch_size = Deoptimizer::patch_size();
+ if (current_pc < last_lazy_deopt_pc_ + patch_size) {
+ int padding_size = last_lazy_deopt_pc_ + patch_size - current_pc;
+ while (padding_size-- > 0) {
+ __ nop();
+ }
+ }
+ last_lazy_deopt_pc_ = masm()->pc_offset();
+}
+
+
void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
- // No code for lazy bailout instruction. Used to capture environment after a
- // call for populating the safepoint data with deoptimization data.
+ EnsureSpaceForLazyDeopt();
+ ASSERT(instr->HasEnvironment());
+ LEnvironment* env = instr->environment();
+ RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
+ safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
}
@@ -4268,32 +4252,26 @@ void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
}
ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
LPointerMap* pointers = instr->pointer_map();
- LEnvironment* env = instr->deoptimization_environment();
RecordPosition(pointers->position());
- RegisterEnvironmentForDeoptimization(env);
// Create safepoint generator that will also ensure enough space in the
// reloc info for patching in deoptimization (since this is invoking a
// builtin)
- SafepointGenerator safepoint_generator(this,
- pointers,
- env->deoptimization_index());
+ SafepointGenerator safepoint_generator(
+ this, pointers, Safepoint::kLazyDeopt);
__ push(Immediate(Smi::FromInt(strict_mode_flag())));
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator);
}
void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
- {
- PushSafepointRegistersScope scope(this);
- __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
- __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
- RegisterLazyDeoptimization(
- instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
- }
-
- // The gap code includes the restoring of the safepoint registers.
- int pc = masm()->pc_offset();
- safepoints_.SetPcAfterGap(pc);
+ PushSafepointRegistersScope scope(this);
+ __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+ __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
+ RecordSafepointWithLazyDeopt(
+ instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
+ ASSERT(instr->HasEnvironment());
+ LEnvironment* env = instr->environment();
+ safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
}
@@ -4307,6 +4285,10 @@ void LCodeGen::DoStackCheck(LStackCheck* instr) {
LStackCheck* instr_;
};
+ ASSERT(instr->HasEnvironment());
+ LEnvironment* env = instr->environment();
+ // There is no LLazyBailout instruction for stack-checks. We have to
+ // prepare for lazy deoptimization explicitly here.
if (instr->hydrogen()->is_function_entry()) {
// Perform stack overflow check.
Label done;
@@ -4319,7 +4301,10 @@ void LCodeGen::DoStackCheck(LStackCheck* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
StackCheckStub stub;
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ EnsureSpaceForLazyDeopt();
__ bind(&done);
+ RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
+ safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
} else {
ASSERT(instr->hydrogen()->is_backwards_branch());
// Perform stack overflow check if this goto needs it before jumping.
@@ -4329,8 +4314,13 @@ void LCodeGen::DoStackCheck(LStackCheck* instr) {
ExternalReference::address_of_stack_limit(isolate());
__ cmp(esp, Operand::StaticVariable(stack_limit));
__ j(below, deferred_stack_check->entry());
+ EnsureSpaceForLazyDeopt();
__ bind(instr->done_label());
deferred_stack_check->SetExit(instr->done_label());
+ RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
+ // Don't record a deoptimization index for the safepoint here.
+ // This will be done explicitly when emitting call and the safepoint in
+ // the deferred code.
}
}
@@ -4346,7 +4336,7 @@ void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
// If the environment were already registered, we would have no way of
// backpatching it with the spill slot operands.
ASSERT(!environment->HasBeenRegistered());
- RegisterEnvironmentForDeoptimization(environment);
+ RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
ASSERT(osr_pc_offset_ == -1);
osr_pc_offset_ = masm()->pc_offset();
}
@@ -4367,15 +4357,9 @@ void LCodeGen::DoIn(LIn* instr) {
}
ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
LPointerMap* pointers = instr->pointer_map();
- LEnvironment* env = instr->deoptimization_environment();
RecordPosition(pointers->position());
- RegisterEnvironmentForDeoptimization(env);
- // Create safepoint generator that will also ensure enough space in the
- // reloc info for patching in deoptimization (since this is invoking a
- // builtin)
- SafepointGenerator safepoint_generator(this,
- pointers,
- env->deoptimization_index());
+ SafepointGenerator safepoint_generator(
+ this, pointers, Safepoint::kLazyDeopt);
__ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator);
}
View
34 deps/v8/src/ia32/lithium-codegen-ia32.h
@@ -60,7 +60,7 @@ class LCodeGen BASE_EMBEDDED {
status_(UNUSED),
deferred_(8),
osr_pc_offset_(-1),
- deoptimization_reloc_size(),
+ last_lazy_deopt_pc_(0),
resolver_(this),
expected_safepoint_kind_(Safepoint::kSimple) {
PopulateDeoptimizationLiteralsWithInlinedFunctions();
@@ -100,8 +100,8 @@ class LCodeGen BASE_EMBEDDED {
void DoDeferredStackCheck(LStackCheck* instr);
void DoDeferredStringCharCodeAt(LStringCharCodeAt* instr);
void DoDeferredStringCharFromCode(LStringCharFromCode* instr);
- void DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
- Label* map_check);
+ void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
+ Label* map_check);
// Parallel move support.
void DoParallelMove(LParallelMove* move);
@@ -139,7 +139,6 @@ class LCodeGen BASE_EMBEDDED {
HGraph* graph() const { return chunk_->graph(); }
int GetNextEmittedBlock(int block);
- LInstruction* GetNextInstruction();
void EmitClassOfTest(Label* if_true,
Label* if_false,
@@ -205,10 +204,11 @@ class LCodeGen BASE_EMBEDDED {
void LoadHeapObject(Register result, Handle<HeapObject> object);
- void RegisterLazyDeoptimization(LInstruction* instr,
- SafepointMode safepoint_mode);
+ void RecordSafepointWithLazyDeopt(LInstruction* instr,
+ SafepointMode safepoint_mode);
- void RegisterEnvironmentForDeoptimization(LEnvironment* environment);
+ void RegisterEnvironmentForDeoptimization(LEnvironment* environment,
+ Safepoint::DeoptMode mode);
void DeoptimizeIf(Condition cc, LEnvironment* environment);
void AddToTranslation(Translation* translation,
@@ -242,16 +242,13 @@ class LCodeGen BASE_EMBEDDED {
void RecordSafepoint(LPointerMap* pointers,
Safepoint::Kind kind,
int arguments,
- int deoptimization_index);
- void RecordSafepoint(LPointerMap* pointers, int deoptimization_index);
- void RecordSafepoint(int deoptimization_index);
+ Safepoint::DeoptMode mode);
+ void RecordSafepoint(LPointerMap* pointers, Safepoint::DeoptMode mode);
+ void RecordSafepoint(Safepoint::DeoptMode mode);
void RecordSafepointWithRegisters(LPointerMap* pointers,
int arguments,
- int deoptimization_index);
+ Safepoint::DeoptMode mode);
void RecordPosition(int position);
- int LastSafepointEnd() {
- return static_cast<int>(safepoints_.GetPcAfterGap());
- }
static Condition TokenToCondition(Token::Value op, bool is_unsigned);
void EmitGoto(int block);
@@ -284,6 +281,7 @@ class LCodeGen BASE_EMBEDDED {
Register object,
Handle<Map> type,
Handle<String> name);
+ void EnsureSpaceForLazyDeopt();
LChunk* const chunk_;
MacroAssembler* const masm_;
@@ -300,13 +298,7 @@ class LCodeGen BASE_EMBEDDED {
TranslationBuffer translations_;
ZoneList<LDeferredCode*> deferred_;
int osr_pc_offset_;
-
- struct DeoptimizationRelocSize {
- int min_size;
- int last_pc_offset;
- };
-
- DeoptimizationRelocSize deoptimization_reloc_size;
+ int last_lazy_deopt_pc_;
// Builder that keeps track of safepoints in the code. The table
// itself is emitted at the end of the generated code.
View
10 deps/v8/src/ia32/lithium-ia32.h
@@ -368,17 +368,7 @@ class LGoto: public LTemplateInstruction<0, 0, 0> {
class LLazyBailout: public LTemplateInstruction<0, 0, 0> {
public:
- LLazyBailout() : gap_instructions_size_(0) { }
-
DECLARE_CONCRETE_INSTRUCTION(LazyBailout, "lazy-bailout")
-
- void set_gap_instructions_size(int gap_instructions_size) {
- gap_instructions_size_ = gap_instructions_size;
- }
- int gap_instructions_size() { return gap_instructions_size_; }
-
- private:
- int gap_instructions_size_;
};
View
8 deps/v8/src/lithium.h
@@ -442,6 +442,7 @@ class LEnvironment: public ZoneObject {
translation_index_(-1),
ast_id_(ast_id),
parameter_count_(parameter_count),
+ pc_offset_(-1),
values_(value_count),
representations_(value_count),
spilled_registers_(NULL),
@@ -455,6 +456,7 @@ class LEnvironment: public ZoneObject {
int translation_index() const { return translation_index_; }
int ast_id() const { return ast_id_; }
int parameter_count() const { return parameter_count_; }
+ int pc_offset() const { return pc_offset_; }
LOperand** spilled_registers() const { return spilled_registers_; }
LOperand** spilled_double_registers() const {
return spilled_double_registers_;
@@ -471,10 +473,13 @@ class LEnvironment: public ZoneObject {
return representations_[index].IsTagged();
}
- void Register(int deoptimization_index, int translation_index) {
+ void Register(int deoptimization_index,
+ int translation_index,
+ int pc_offset) {
ASSERT(!HasBeenRegistered());
deoptimization_index_ = deoptimization_index;
translation_index_ = translation_index;
+ pc_offset_ = pc_offset;
}
bool HasBeenRegistered() const {
return deoptimization_index_ != Safepoint::kNoDeoptimizationIndex;
@@ -495,6 +500,7 @@ class LEnvironment: public ZoneObject {
int translation_index_;
int ast_id_;
int parameter_count_;
+ int pc_offset_;
ZoneList<LOperand*> values_;
ZoneList<Representation> representations_;
View
2  deps/v8/src/mips/code-stubs-mips.cc
@@ -5607,7 +5607,7 @@ void StringHelper::GenerateHashAddCharacter(MacroAssembler* masm,
void StringHelper::GenerateHashGetHash(MacroAssembler* masm,
- Register hash) {
+ Register hash) {
// hash += hash << 3;
__ sll(at, hash, 3);
__ addu(hash, hash, at);
View
11 deps/v8/src/objects.cc
@@ -6995,11 +6995,14 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint(FILE* out) {
PrintF(out, "Deoptimization Input Data (deopt points = %d)\n", deopt_count);
if (0 == deopt_count) return;
- PrintF(out, "%6s %6s %6s %12s\n", "index", "ast id", "argc",
+ PrintF(out, "%6s %6s %6s %6s %12s\n", "index", "ast id", "argc", "pc",
FLAG_print_code_verbose ? "commands" : "");
for (int i = 0; i < deopt_count; i++) {
- PrintF(out, "%6d %6d %6d",
- i, AstId(i)->value(), ArgumentsStackHeight(i)->value());
+ PrintF(out, "%6d %6d %6d %6d",
+ i,
+ AstId(i)->value(),
+ ArgumentsStackHeight(i)->value(),
+ Pc(i)->value());
if (!FLAG_print_code_verbose) {
PrintF(out, "\n");
@@ -10542,7 +10545,7 @@ class TwoCharHashTableKey : public HashTableKey {
hash += hash << 3;
hash ^= hash >> 11;
hash += hash << 15;
- if ((hash & String::kHashBitMask) == 0) hash = 27;
+ if ((hash & String::kHashBitMask) == 0) hash = String::kZeroHash;
#ifdef DEBUG
StringHasher hasher(2, seed);
hasher.AddCharacter(c1);
View
9 deps/v8/src/objects.h
@@ -3535,7 +3535,8 @@ class DeoptimizationInputData: public FixedArray {
static const int kAstIdOffset = 0;
static const int kTranslationIndexOffset = 1;
static const int kArgumentsStackHeightOffset = 2;
- static const int kDeoptEntrySize = 3;
+ static const int kPcOffset = 3;
+ static const int kDeoptEntrySize = 4;
// Simple element accessors.
#define DEFINE_ELEMENT_ACCESSORS(name, type) \
@@ -3571,6 +3572,7 @@ class DeoptimizationInputData: public FixedArray {
DEFINE_ENTRY_ACCESSORS(AstId, Smi)
DEFINE_ENTRY_ACCESSORS(TranslationIndex, Smi)
DEFINE_ENTRY_ACCESSORS(ArgumentsStackHeight, Smi)
+ DEFINE_ENTRY_ACCESSORS(Pc, Smi)
#undef DEFINE_ENTRY_ACCESSORS
@@ -5832,6 +5834,11 @@ class StringHasher {
// value is represented decimal value.
static uint32_t MakeArrayIndexHash(uint32_t value, int length);
+ // No string is allowed to have a hash of zero. That value is reserved
+ // for internal properties. If the hash calculation yields zero then we
+ // use 27 instead.
+ static const int kZeroHash = 27;
+
private:
uint32_t array_index() {
ASSERT(is_array_index());
View
60 deps/v8/src/safepoint-table.cc
@@ -122,17 +122,20 @@ void Safepoint::DefinePointerRegister(Register reg) {
Safepoint SafepointTableBuilder::DefineSafepoint(
- Assembler* assembler, Safepoint::Kind kind, int arguments,
- int deoptimization_index) {
- ASSERT(deoptimization_index != -1);
+ Assembler* assembler,
+ Safepoint::Kind kind,
+ int arguments,
+ Safepoint::DeoptMode deopt_mode) {
ASSERT(arguments >= 0);
- DeoptimizationInfo pc_and_deoptimization_index;
- pc_and_deoptimization_index.pc = assembler->pc_offset();
- pc_and_deoptimization_index.deoptimization_index = deoptimization_index;
- pc_and_deoptimization_index.pc_after_gap = assembler->pc_offset();
- pc_and_deoptimization_index.arguments = arguments;
- pc_and_deoptimization_index.has_doubles = (kind & Safepoint::kWithDoubles);
- deoptimization_info_.Add(pc_and_deoptimization_index);
+ DeoptimizationInfo info;
+ info.pc = assembler->pc_offset();
+ info.arguments = arguments;
+ info.has_doubles = (kind & Safepoint::kWithDoubles);
+ deoptimization_info_.Add(info);
+ deopt_index_list_.Add(Safepoint::kNoDeoptimizationIndex);
+ if (deopt_mode == Safepoint::kNoLazyDeopt) {
+ last_lazy_safepoint_ = deopt_index_list_.length();
+ }
indexes_.Add(new ZoneList<int>(8));
registers_.Add((kind & Safepoint::kWithRegisters)
? new ZoneList<int>(4)
@@ -141,6 +144,12 @@ Safepoint SafepointTableBuilder::DefineSafepoint(
}
+void SafepointTableBuilder::RecordLazyDeoptimizationIndex(int index) {
+ while (last_lazy_safepoint_ < deopt_index_list_.length()) {
+ deopt_index_list_[last_lazy_safepoint_++] = index;
+ }
+}
+
unsigned SafepointTableBuilder::GetCodeOffset() const {
ASSERT(emitted_);
return offset_;
@@ -173,11 +182,11 @@ void SafepointTableBuilder::Emit(Assembler* assembler, int bits_per_entry) {
assembler->dd(length);
assembler->dd(bytes_per_entry);
- // Emit sorted table of pc offsets together with deoptimization indexes and
- // pc after gap information.
+ // Emit sorted table of pc offsets together with deoptimization indexes.
for (int i = 0; i < length; i++) {
assembler->dd(deoptimization_info_[i].pc);
- assembler->dd(EncodeExceptPC(deoptimization_info_[i]));
+ assembler->dd(EncodeExceptPC(deoptimization_info_[i],
+ deopt_index_list_[i]));
}
// Emit table of bitmaps.
@@ -222,35 +231,14 @@ void SafepointTableBuilder::Emit(Assembler* assembler, int bits_per_entry) {
}
-uint32_t SafepointTableBuilder::EncodeExceptPC(const DeoptimizationInfo& info) {
- unsigned index = info.deoptimization_index;
- unsigned gap_size = info.pc_after_gap - info.pc;
+uint32_t SafepointTableBuilder::EncodeExceptPC(const DeoptimizationInfo& info,
+ unsigned index) {
uint32_t encoding = SafepointEntry::DeoptimizationIndexField::encode(index);
- encoding |= SafepointEntry::GapCodeSizeField::encode(gap_size);
encoding |= SafepointEntry::ArgumentsField::encode(info.arguments);
encoding |= SafepointEntry::SaveDoublesField::encode(info.has_doubles);
return encoding;
}
-int SafepointTableBuilder::CountShortDeoptimizationIntervals(unsigned limit) {
- int result = 0;
- if (!deoptimization_info_.is_empty()) {
- unsigned previous_gap_end = deoptimization_info_[0].pc_after_gap;
- for (int i = 1, n = deoptimization_info_.length(); i < n; i++) {
- DeoptimizationInfo info = deoptimization_info_[i];
- if (static_cast<int>(info.deoptimization_index) !=
- Safepoint::kNoDeoptimizationIndex) {
- if (previous_gap_end + limit > info.pc) {
- result++;
- }
- previous_gap_end = info.pc_after_gap;
- }
- }
- }
- return result;
-}
-
-
} } // namespace v8::internal
View
78 deps/v8/src/safepoint-table.h
@@ -62,10 +62,20 @@ class SafepointEntry BASE_EMBEDDED {
return DeoptimizationIndexField::decode(info_);
}
- int gap_code_size() const {
- ASSERT(is_valid());
- return GapCodeSizeField::decode(info_);
- }
+ static const int kArgumentsFieldBits = 3;
+ static const int kSaveDoublesFieldBits = 1;
+ static const int kDeoptIndexBits =
+ 32 - kArgumentsFieldBits - kSaveDoublesFieldBits;
+ class DeoptimizationIndexField:
+ public BitField<int, 0, kDeoptIndexBits> {}; // NOLINT
+ class ArgumentsField:
+ public BitField<unsigned,
+ kDeoptIndexBits,
+ kArgumentsFieldBits> {}; // NOLINT
+ class SaveDoublesField:
+ public BitField<bool,
+ kDeoptIndexBits + kArgumentsFieldBits,
+ kSaveDoublesFieldBits> { }; // NOLINT
int argument_count() const {
ASSERT(is_valid());
@@ -85,27 +95,6 @@ class SafepointEntry BASE_EMBEDDED {
bool HasRegisters() const;
bool HasRegisterAt(int reg_index) const;
- // Reserve 13 bits for the gap code size. On ARM a constant pool can be
- // emitted when generating the gap code. The size of the const pool is less
- // than what can be represented in 12 bits, so 13 bits gives room for having
- // instructions before potentially emitting a constant pool.
- static const int kGapCodeSizeBits = 13;
- static const int kArgumentsFieldBits = 3;
- static const int kSaveDoublesFieldBits = 1;
- static const int kDeoptIndexBits =
- 32 - kGapCodeSizeBits - kArgumentsFieldBits - kSaveDoublesFieldBits;
- class GapCodeSizeField: public BitField<unsigned, 0, kGapCodeSizeBits> {};
- class DeoptimizationIndexField: public BitField<int,
- kGapCodeSizeBits,
- kDeoptIndexBits> {}; // NOLINT
- class ArgumentsField: public BitField<unsigned,
- kGapCodeSizeBits + kDeoptIndexBits,
- kArgumentsFieldBits> {}; // NOLINT
- class SaveDoublesField: public BitField<bool,
- kGapCodeSizeBits + kDeoptIndexBits +
- kArgumentsFieldBits,
- kSaveDoublesFieldBits> { }; // NOLINT
-
private:
unsigned info_;
uint8_t* bits_;
@@ -186,6 +175,11 @@ class Safepoint BASE_EMBEDDED {
kWithRegistersAndDoubles = kWithRegisters | kWithDoubles
} Kind;
+ enum DeoptMode {
+ kNoLazyDeopt,
+ kLazyDeopt
+ };
+
static const int kNoDeoptimizationIndex =
(1 << (SafepointEntry::kDeoptIndexBits)) - 1;
@@ -206,9 +200,11 @@ class SafepointTableBuilder BASE_EMBEDDED {
public:
SafepointTableBuilder()
: deoptimization_info_(32),
+ deopt_index_list_(32),
indexes_(32),
registers_(32),
- emitted_(false) { }
+ emitted_(false),
+ last_lazy_safepoint_(0) { }
// Get the offset of the emitted safepoint table in the code.
unsigned GetCodeOffset() const;
@@ -217,50 +213,34 @@ class SafepointTableBuilder BASE_EMBEDDED {
Safepoint DefineSafepoint(Assembler* assembler,
Safepoint::Kind kind,
int arguments,
- int deoptimization_index);
-
- // Update the last safepoint with the size of the code generated until the
- // end of the gap following it.
- void SetPcAfterGap(int pc) {
- ASSERT(!deoptimization_info_.is_empty());
- int index = deoptimization_info_.length() - 1;
- deoptimization_info_[index].pc_after_gap = pc;
- }
+ Safepoint::DeoptMode mode);
- // Get the end pc offset of the last safepoint, including the code generated
- // until the end of the gap following it.
- unsigned GetPcAfterGap() {
- int index = deoptimization_info_.length();
- if (index == 0) return 0;
- return deoptimization_info_[index - 1].pc_after_gap;
- }
+ // Record deoptimization index for lazy deoptimization for the last
+ // outstanding safepoints.
+ void RecordLazyDeoptimizationIndex(int index);
// Emit the safepoint table after the body. The number of bits per
// entry must be enough to hold all the pointer indexes.
void Emit(Assembler* assembler, int bits_per_entry);
- // Count the number of deoptimization points where the next
- // following deoptimization point comes less than limit bytes
- // after the end of this point's gap.
- int CountShortDeoptimizationIntervals(unsigned limit);
private:
struct DeoptimizationInfo {
unsigned pc;
- unsigned deoptimization_index;
- unsigned pc_after_gap;
unsigned arguments;
bool has_doubles;
};
- uint32_t EncodeExceptPC(const DeoptimizationInfo& info);
+ uint32_t EncodeExceptPC(const DeoptimizationInfo& info, unsigned index);
ZoneList<DeoptimizationInfo> deoptimization_info_;
+ ZoneList<unsigned> deopt_index_list_;
ZoneList<ZoneList<int>*> indexes_;
ZoneList<ZoneList<int>*> registers_;
unsigned offset_;
bool emitted_;
+ int last_lazy_safepoint_;
DISALLOW_COPY_AND_ASSIGN(SafepointTableBuilder);
};
View
4 deps/v8/src/version.cc
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 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:
@@ -35,7 +35,7 @@
#define MAJOR_VERSION 3
#define MINOR_VERSION 6
#define BUILD_NUMBER 6
-#define PATCH_LEVEL 15
+#define PATCH_LEVEL 19
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 0
View
5 deps/v8/src/x64/code-stubs-x64.cc
@@ -4654,13 +4654,12 @@ void StringHelper::GenerateHashGetHash(MacroAssembler* masm,
__ shll(scratch, Immediate(15));
__ addl(hash, scratch);
- uint32_t kHashShiftCutOffMask = (1 << (32 - String::kHashShift)) - 1;
- __ andl(hash, Immediate(kHashShiftCutOffMask));
+ __ andl(hash, Immediate(String::kHashBitMask));
// if (hash == 0) hash = 27;
Label hash_not_zero;
__ j(not_zero, &hash_not_zero);
- __ Set(hash, 27);
+ __ Set(hash, StringHasher::kZeroHash);
__ bind(&hash_not_zero);
}
View
147 deps/v8/src/x64/deoptimizer-x64.cc
@@ -42,67 +42,7 @@ const int Deoptimizer::table_entry_size_ = 10;
int Deoptimizer::patch_size() {
- return MacroAssembler::kCallInstructionLength;
-}
-
-
-#ifdef DEBUG
-// Overwrites code with int3 instructions.
-static void ZapCodeRange(Address from, Address to) {
- CHECK(from <= to);
- int length = static_cast<int>(to - from);
- CodePatcher destroyer(from, length);
- while (length-- > 0) {
- destroyer.masm()->int3();
- }
-}
-#endif
-
-
-// Iterate through the entries of a SafepointTable that corresponds to
-// deoptimization points.
-class SafepointTableDeoptimiztionEntryIterator {
- public:
- explicit SafepointTableDeoptimiztionEntryIterator(Code* code)
- : code_(code), table_(code), index_(-1), limit_(table_.length()) {
- FindNextIndex();
- }
-
- SafepointEntry Next(Address* pc) {
- if (index_ >= limit_) {
- *pc = NULL;
- return SafepointEntry(); // Invalid entry.
- }
- *pc = code_->instruction_start() + table_.GetPcOffset(index_);
- SafepointEntry entry = table_.GetEntry(index_);
- FindNextIndex();
- return entry;
- }
-
- private:
- void FindNextIndex() {
- ASSERT(index_ < limit_);
- while (++index_ < limit_) {
- if (table_.GetEntry(index_).deoptimization_index() !=
- Safepoint::kNoDeoptimizationIndex) {
- return;
- }
- }
- }
-
- Code* code_;
- SafepointTable table_;
- // Index of next deoptimization entry. If negative after calling
- // FindNextIndex, there are no more, and Next will return an invalid
- // SafepointEntry.
- int index_;
- // Table length.
- int limit_;
-};
-
-
-void Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code) {
- // TODO(1276): Implement.
+ return Assembler::kCallInstructionLength;
}
@@ -119,84 +59,34 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
// code patching below, and is not needed any more.
code->InvalidateRelocation();
- // For each return after a safepoint insert a absolute call to the
+ // For each LLazyBailout instruction insert a absolute call to the
// corresponding deoptimization entry, or a short call to an absolute
// jump if space is short. The absolute jumps are put in a table just
// before the safepoint table (space was allocated there when the Code
// object was created, if necessary).
Address instruction_start = function->code()->instruction_start();
- Address jump_table_address =
- instruction_start + function->code()->safepoint_table_offset();
#ifdef DEBUG
- Address previous_pc = instruction_start;
-#endif
-
- SafepointTableDeoptimiztionEntryIterator deoptimizations(function->code());
- Address entry_pc = NULL;
-
- SafepointEntry current_entry = deoptimizations.Next(&entry_pc);
- while (current_entry.is_valid()) {
- int gap_code_size = current_entry.gap_code_size();
- unsigned deoptimization_index = current_entry.deoptimization_index();
-
-#ifdef DEBUG
- // Destroy the code which is not supposed to run again.
- ZapCodeRange(previous_pc, entry_pc);
+ Address prev_call_address = NULL;
#endif
+ DeoptimizationInputData* deopt_data =
+ DeoptimizationInputData::cast(code->deoptimization_data());
+ for (int i = 0; i < deopt_data->DeoptCount(); i++) {
+ if (deopt_data->Pc(i)->value() == -1) continue;
// Position where Call will be patched in.
- Address call_address = entry_pc + gap_code_size;
- // End of call instruction, if using a direct call to a 64-bit address.
- Address call_end_address =
- call_address + MacroAssembler::kCallInstructionLength;
-
- // Find next deoptimization entry, if any.
- Address next_pc = NULL;
- SafepointEntry next_entry = deoptimizations.Next(&next_pc);
-
- if (!next_entry.is_valid() || next_pc >= call_end_address) {
- // Room enough to write a long call instruction.
- CodePatcher patcher(call_address, Assembler::kCallInstructionLength);
- patcher.masm()->Call(GetDeoptimizationEntry(deoptimization_index, LAZY),
- RelocInfo::NONE);
-#ifdef DEBUG
- previous_pc = call_end_address;
-#endif
- } else {
- // Not room enough for a long Call instruction. Write a short call
- // instruction to a long jump placed elsewhere in the code.
+ Address call_address = instruction_start + deopt_data->Pc(i)->value();
+ // There is room enough to write a long call instruction because we pad
+ // LLazyBailout instructions with nops if necessary.
+ CodePatcher patcher(call_address, Assembler::kCallInstructionLength);
+ patcher.masm()->Call(GetDeoptimizationEntry(i, LAZY), RelocInfo::NONE);
+ ASSERT(prev_call_address == NULL ||
+ call_address >= prev_call_address + patch_size());
+ ASSERT(call_address + patch_size() <= code->instruction_end());
#ifdef DEBUG
- Address short_call_end_address =
- call_address + MacroAssembler::kShortCallInstructionLength;
+ prev_call_address = call_address;
#endif
- ASSERT(next_pc >= short_call_end_address);
-
- // Write jump in jump-table.
- jump_table_address -= MacroAssembler::kJumpInstructionLength;
- CodePatcher jump_patcher(jump_table_address,
- MacroAssembler::kJumpInstructionLength);
- jump_patcher.masm()->Jump(
- GetDeoptimizationEntry(deoptimization_index, LAZY),
- RelocInfo::NONE);
-
- // Write call to jump at call_offset.
- CodePatcher call_patcher(call_address,
- MacroAssembler::kShortCallInstructionLength);
- call_patcher.masm()->call(jump_table_address);
-#ifdef DEBUG
- previous_pc = short_call_end_address;
-#endif
- }
-
- // Continue with next deoptimization entry.
- current_entry = next_entry;
- entry_pc = next_pc;
}
-#ifdef DEBUG
- // Destroy the code which is not supposed to run again.
- ZapCodeRange(previous_pc, jump_table_address);
-#endif
// Add the deoptimizing code to the list.