diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog index a78755b63a..009296cb44 100644 --- a/deps/v8/ChangeLog +++ b/deps/v8/ChangeLog @@ -1,3 +1,16 @@ +2009-09-15: Version 1.3.11 + + Fixed crash in error reporting during bootstrapping. + + Optimized generated IA32 math code by using SSE2 instructions when + available. + + Implemented missing pieces of debugger infrastructure on ARM. The + debugger is now fully functional on ARM. + + Make 'hidden' the default visibility for gcc. + + 2009-09-09: Version 1.3.10 Fixed profiler on Mac in 64-bit mode. diff --git a/deps/v8/SConstruct b/deps/v8/SConstruct index ddd0190af7..b5aa7abadb 100644 --- a/deps/v8/SConstruct +++ b/deps/v8/SConstruct @@ -96,13 +96,18 @@ ANDROID_LINKFLAGS = ['-nostdlib', LIBRARY_FLAGS = { 'all': { - 'CPPDEFINES': ['ENABLE_LOGGING_AND_PROFILING'], 'CPPPATH': [join(root_dir, 'src')], 'regexp:native': { 'CPPDEFINES': ['V8_NATIVE_REGEXP'] }, 'mode:debug': { 'CPPDEFINES': ['V8_ENABLE_CHECKS'] + }, + 'profilingsupport:on': { + 'CPPDEFINES': ['ENABLE_LOGGING_AND_PROFILING'], + }, + 'debuggersupport:on': { + 'CPPDEFINES': ['ENABLE_DEBUGGER_SUPPORT'], } }, 'gcc': { @@ -110,11 +115,14 @@ LIBRARY_FLAGS = { 'CCFLAGS': ['$DIALECTFLAGS', '$WARNINGFLAGS'], 'CXXFLAGS': ['$CCFLAGS', '-fno-rtti', '-fno-exceptions'], }, + 'visibility:hidden': { + # Use visibility=default to disable this. + 'CXXFLAGS': ['-fvisibility=hidden'] + }, 'mode:debug': { 'CCFLAGS': ['-g', '-O0'], 'CPPDEFINES': ['ENABLE_DISASSEMBLER', 'DEBUG'], 'os:android': { - 'CPPDEFINES': ['ENABLE_DEBUGGER_SUPPORT'], 'CCFLAGS': ['-mthumb'] } }, @@ -123,7 +131,7 @@ LIBRARY_FLAGS = { '-ffunction-sections'], 'os:android': { 'CCFLAGS': ['-mthumb', '-Os'], - 'CPPDEFINES': ['SK_RELEASE', 'NDEBUG', 'ENABLE_DEBUGGER_SUPPORT'] + 'CPPDEFINES': ['SK_RELEASE', 'NDEBUG'] } }, 'os:linux': { @@ -229,7 +237,6 @@ LIBRARY_FLAGS = { V8_EXTRA_FLAGS = { 'gcc': { 'all': { - 'CXXFLAGS': [], #['-fvisibility=hidden'], 'WARNINGFLAGS': ['-Wall', '-Werror', '-W', @@ -576,6 +583,16 @@ SIMPLE_OPTIONS = { 'default': 'static', 'help': 'the type of library to produce' }, + 'profilingsupport': { + 'values': ['on', 'off'], + 'default': 'on', + 'help': 'enable profiling of JavaScript code' + }, + 'debuggersupport': { + 'values': ['on', 'off'], + 'default': 'on', + 'help': 'enable debugging of JavaScript code' + }, 'soname': { 'values': ['on', 'off'], 'default': 'off', @@ -615,6 +632,11 @@ SIMPLE_OPTIONS = { 'values': ['on', 'off'], 'default': 'off', 'help': 'more output from compiler and linker' + }, + 'visibility': { + 'values': ['default', 'hidden'], + 'default': 'hidden', + 'help': 'shared library symbol visibility' } } @@ -794,6 +816,10 @@ def PostprocessOptions(options): # Print a warning if arch has explicitly been set print "Warning: forcing architecture to match simulator (%s)" % options['simulator'] options['arch'] = options['simulator'] + if (options['prof'] != 'off') and (options['profilingsupport'] == 'off'): + # Print a warning if profiling is enabled without profiling support + print "Warning: forcing profilingsupport on when prof is on" + options['profilingsupport'] = 'on' def ParseEnvOverrides(arg, imports): diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index 2789bad216..24dc6d13f7 100644 --- a/deps/v8/include/v8.h +++ b/deps/v8/include/v8.h @@ -2725,9 +2725,9 @@ class Internals { // These constants are compiler dependent so their values must be // defined within the implementation. - static int kJSObjectType; - static int kFirstNonstringType; - static int kProxyType; + V8EXPORT static int kJSObjectType; + V8EXPORT static int kFirstNonstringType; + V8EXPORT static int kProxyType; static inline bool HasHeapObjectTag(internal::Object* value) { return ((reinterpret_cast(value) & kHeapObjectTagMask) == diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index 1128d3e022..052e875169 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -2672,9 +2672,7 @@ Persistent v8::Context::New( } // Leave V8. - if (!ApiCheck(!env.is_null(), - "v8::Context::New()", - "Could not initialize environment")) + if (env.is_null()) return Persistent(); return Persistent(Utils::ToLocal(env)); } diff --git a/deps/v8/src/arm/assembler-arm-inl.h b/deps/v8/src/arm/assembler-arm-inl.h index cb5faa2347..cd5a1bbfd7 100644 --- a/deps/v8/src/arm/assembler-arm-inl.h +++ b/deps/v8/src/arm/assembler-arm-inl.h @@ -105,40 +105,45 @@ Address* RelocInfo::target_reference_address() { Address RelocInfo::call_address() { ASSERT(IsCallInstruction()); - UNIMPLEMENTED(); - return NULL; + // The 2 instructions offset assumes patched return sequence. + ASSERT(IsJSReturn(rmode())); + return Memory::Address_at(pc_ + 2 * Assembler::kInstrSize); } void RelocInfo::set_call_address(Address target) { ASSERT(IsCallInstruction()); - UNIMPLEMENTED(); + // The 2 instructions offset assumes patched return sequence. + ASSERT(IsJSReturn(rmode())); + Memory::Address_at(pc_ + 2 * Assembler::kInstrSize) = target; } Object* RelocInfo::call_object() { - ASSERT(IsCallInstruction()); - UNIMPLEMENTED(); - return NULL; + return *call_object_address(); } Object** RelocInfo::call_object_address() { ASSERT(IsCallInstruction()); - UNIMPLEMENTED(); - return NULL; + // The 2 instructions offset assumes patched return sequence. + ASSERT(IsJSReturn(rmode())); + return reinterpret_cast(pc_ + 2 * Assembler::kInstrSize); } void RelocInfo::set_call_object(Object* target) { - ASSERT(IsCallInstruction()); - UNIMPLEMENTED(); + *call_object_address() = target; } bool RelocInfo::IsCallInstruction() { - UNIMPLEMENTED(); - return false; + // On ARM a "call instruction" is actually two instructions. + // mov lr, pc + // ldr pc, [pc, #XXX] + return (Assembler::instr_at(pc_) == kMovLrPc) + && ((Assembler::instr_at(pc_ + Assembler::kInstrSize) & kLdrPCPattern) + == kLdrPCPattern); } diff --git a/deps/v8/src/arm/assembler-arm.cc b/deps/v8/src/arm/assembler-arm.cc index 8bd06dbfed..bc3b8e6447 100644 --- a/deps/v8/src/arm/assembler-arm.cc +++ b/deps/v8/src/arm/assembler-arm.cc @@ -93,7 +93,14 @@ const int RelocInfo::kApplyMask = 0; void RelocInfo::PatchCode(byte* instructions, int instruction_count) { // Patch the code at the current address with the supplied instructions. - UNIMPLEMENTED(); + Instr* pc = reinterpret_cast(pc_); + Instr* instr = reinterpret_cast(instructions); + for (int i = 0; i < instruction_count; i++) { + *(pc + i) = *(instr + i); + } + + // Indicate that code has changed. + CPU::FlushICache(pc_, instruction_count * Assembler::kInstrSize); } @@ -232,6 +239,10 @@ static const Instr kPushRegPattern = // register r is not encoded. static const Instr kPopRegPattern = al | B26 | L | 4 | PostIndex | sp.code() * B16; +// mov lr, pc +const Instr kMovLrPc = al | 13*B21 | pc.code() | lr.code() * B12; +// ldr pc, [pc, #XXX] +const Instr kLdrPCPattern = al | B26 | L | pc.code() * B16; // spare_buffer_ static const int kMinimalBufferSize = 4*KB; @@ -1301,6 +1312,13 @@ void Assembler::lea(Register dst, // Debugging +void Assembler::RecordJSReturn() { + WriteRecordedPositions(); + CheckBuffer(); + RecordRelocInfo(RelocInfo::JS_RETURN); +} + + void Assembler::RecordComment(const char* msg) { if (FLAG_debug_code) { CheckBuffer(); @@ -1387,16 +1405,20 @@ void Assembler::GrowBuffer() { RelocInfo& rinfo = prinfo_[i]; ASSERT(rinfo.rmode() != RelocInfo::COMMENT && rinfo.rmode() != RelocInfo::POSITION); - rinfo.set_pc(rinfo.pc() + pc_delta); + if (rinfo.rmode() != RelocInfo::JS_RETURN) { + rinfo.set_pc(rinfo.pc() + pc_delta); + } } } void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { RelocInfo rinfo(pc_, rmode, data); // we do not try to reuse pool constants - if (rmode >= RelocInfo::COMMENT && rmode <= RelocInfo::STATEMENT_POSITION) { - // adjust code for new modes - ASSERT(RelocInfo::IsComment(rmode) || RelocInfo::IsPosition(rmode)); + if (rmode >= RelocInfo::JS_RETURN && rmode <= RelocInfo::STATEMENT_POSITION) { + // Adjust code for new modes + ASSERT(RelocInfo::IsJSReturn(rmode) + || RelocInfo::IsComment(rmode) + || RelocInfo::IsPosition(rmode)); // these modes do not need an entry in the constant pool } else { ASSERT(num_prinfo_ < kMaxNumPRInfo); @@ -1490,6 +1512,7 @@ void Assembler::CheckConstPool(bool force_emit, bool require_jump) { rinfo.rmode() != RelocInfo::POSITION && rinfo.rmode() != RelocInfo::STATEMENT_POSITION); Instr instr = instr_at(rinfo.pc()); + // Instruction to patch must be a ldr/str [pc, #offset] // P and U set, B and W clear, Rn == pc, offset12 still 0 ASSERT((instr & (7*B25 | P | U | B | W | 15*B16 | Off12Mask)) == diff --git a/deps/v8/src/arm/assembler-arm.h b/deps/v8/src/arm/assembler-arm.h index 63f04473e1..7e43f2e5da 100644 --- a/deps/v8/src/arm/assembler-arm.h +++ b/deps/v8/src/arm/assembler-arm.h @@ -376,6 +376,10 @@ class MemOperand BASE_EMBEDDED { typedef int32_t Instr; +extern const Instr kMovLrPc; +extern const Instr kLdrPCPattern; + + class Assembler : public Malloced { public: // Create an assembler. Instructions and relocation information are emitted @@ -433,12 +437,16 @@ class Assembler : public Malloced { INLINE(static Address target_address_at(Address pc)); INLINE(static void set_target_address_at(Address pc, Address target)); + // Size of an instruction. + static const int kInstrSize = sizeof(Instr); + // Distance between the instruction referring to the address of the call // target (ldr pc, [target addr in const pool]) and the return address - static const int kPatchReturnSequenceLength = sizeof(Instr); + static const int kCallTargetAddressOffset = kInstrSize; + // Distance between start of patched return sequence and the emitted address // to jump to. - static const int kPatchReturnSequenceAddressOffset = 1; + static const int kPatchReturnSequenceAddressOffset = kInstrSize; // Difference between address of current opcode and value read from pc // register. @@ -652,9 +660,16 @@ class Assembler : public Malloced { // Jump unconditionally to given label. void jmp(Label* L) { b(L, al); } + // Check the code size generated from label to here. + int InstructionsGeneratedSince(Label* l) { + return (pc_offset() - l->pos()) / kInstrSize; + } // Debugging + // Mark address of the ExitJSFrame code. + void RecordJSReturn(); + // Record a comment relocation entry that can be used by a disassembler. // Use --debug_code to enable. void RecordComment(const char* msg); @@ -671,7 +686,7 @@ class Assembler : public Malloced { int buffer_space() const { return reloc_info_writer.pos() - pc_; } // Read/patch instructions - Instr instr_at(byte* pc) { return *reinterpret_cast(pc); } + static Instr instr_at(byte* pc) { return *reinterpret_cast(pc); } void instr_at_put(byte* pc, Instr instr) { *reinterpret_cast(pc) = instr; } @@ -708,7 +723,6 @@ class Assembler : public Malloced { int next_buffer_check_; // pc offset of next buffer check // Code generation - static const int kInstrSize = sizeof(Instr); // signed size // The relocation writer's position is at least kGap bytes below the end of // the generated instructions. This is so that multi-instruction sequences do // not have to check for overflow. The same is true for writes of large @@ -795,6 +809,8 @@ class Assembler : public Malloced { void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); friend class RegExpMacroAssemblerARM; + friend class RelocInfo; + friend class CodePatcher; }; } } // namespace v8::internal diff --git a/deps/v8/src/arm/codegen-arm.cc b/deps/v8/src/arm/codegen-arm.cc index 7b3662d4fc..9ef879a5f5 100644 --- a/deps/v8/src/arm/codegen-arm.cc +++ b/deps/v8/src/arm/codegen-arm.cc @@ -299,7 +299,10 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) { } // Generate the return sequence if necessary. - if (frame_ != NULL || function_return_.is_linked()) { + if (has_valid_frame() || function_return_.is_linked()) { + if (!function_return_.is_linked()) { + CodeForReturnPosition(fun); + } // exit // r0: result // sp: stack pointer @@ -315,12 +318,23 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) { frame_->CallRuntime(Runtime::kTraceExit, 1); } + // Add a label for checking the size of the code used for returning. + Label check_exit_codesize; + masm_->bind(&check_exit_codesize); + // Tear down the frame which will restore the caller's frame pointer and // the link register. frame_->Exit(); - __ add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize)); - __ Jump(lr); + // Here we use masm_-> instead of the __ macro to avoid the code coverage + // tool from instrumenting as we rely on the code size here. + masm_->add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize)); + masm_->Jump(lr); + + // Check that the size of the code used for returning matches what is + // expected by the debugger. + ASSERT_EQ(kJSReturnSequenceLength, + masm_->InstructionsGeneratedSince(&check_exit_codesize)); } // Code generation state must be reset. @@ -1111,10 +1125,10 @@ void CodeGenerator::CheckStack() { if (FLAG_check_stack) { Comment cmnt(masm_, "[ check stack"); __ LoadRoot(ip, Heap::kStackLimitRootIndex); - // Put the lr setup instruction in the delay slot. The 'sizeof(Instr)' is - // added to the implicit 8 byte offset that always applies to operations - // with pc and gives a return address 12 bytes down. - masm_->add(lr, pc, Operand(sizeof(Instr))); + // Put the lr setup instruction in the delay slot. kInstrSize is added to + // the implicit 8 byte offset that always applies to operations with pc and + // gives a return address 12 bytes down. + masm_->add(lr, pc, Operand(Assembler::kInstrSize)); masm_->cmp(sp, Operand(ip)); StackCheckStub stub; // Call the stub if lower. @@ -1380,16 +1394,12 @@ void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { VirtualFrame::SpilledScope spilled_scope; Comment cmnt(masm_, "[ ReturnStatement"); + CodeForStatementPosition(node); + LoadAndSpill(node->expression()); if (function_return_is_shadowed_) { - CodeForStatementPosition(node); - LoadAndSpill(node->expression()); frame_->EmitPop(r0); function_return_.Jump(); } else { - // Load the returned value. - CodeForStatementPosition(node); - LoadAndSpill(node->expression()); - // Pop the result from the frame and prepare the frame for // returning thus making it easier to merge. frame_->EmitPop(r0); diff --git a/deps/v8/src/arm/codegen-arm.h b/deps/v8/src/arm/codegen-arm.h index 70a7b27765..b28e96594f 100644 --- a/deps/v8/src/arm/codegen-arm.h +++ b/deps/v8/src/arm/codegen-arm.h @@ -180,6 +180,10 @@ class CodeGenerator: public AstVisitor { static const int kUnknownIntValue = -1; + // Number of instructions used for the JS return sequence. The constant is + // used by the debugger to patch the JS return sequence. + static const int kJSReturnSequenceLength = 4; + private: // Construction/Destruction CodeGenerator(int buffer_size, Handle