From: kmillikin@chromium.org Date: Fri, 27 Feb 2009 13:00:32 +0000 (+0000) Subject: Merge from experimental code generator branch to bleeding edge. X-Git-Tag: upstream/4.7.83~24606 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f4735247cfd74cefe2d57b83072baf58f1c53a27;p=platform%2Fupstream%2Fv8.git Merge from experimental code generator branch to bleeding edge. git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1389 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/SConscript b/src/SConscript index 34d2a4438..2f5f24476 100644 --- a/src/SConscript +++ b/src/SConscript @@ -39,25 +39,32 @@ SOURCES = { 'bootstrapper.cc', 'builtins.cc', 'checks.cc', 'code-stubs.cc', 'codegen.cc', 'compilation-cache.cc', 'compiler.cc', 'contexts.cc', 'conversions.cc', 'counters.cc', 'dateparser.cc', 'debug.cc', - 'disassembler.cc', 'execution.cc', 'factory.cc', 'flags.cc', 'frames.cc', - 'global-handles.cc', 'handles.cc', 'hashmap.cc', 'heap.cc', 'ic.cc', - 'interpreter-irregexp.cc', 'jsregexp.cc', 'log.cc', 'mark-compact.cc', - 'messages.cc', 'objects.cc', 'parser.cc', 'property.cc', - 'regexp-macro-assembler.cc', 'regexp-macro-assembler-irregexp.cc', - 'regexp-stack.cc', 'rewriter.cc', 'runtime.cc', 'scanner.cc', + 'disassembler.cc', 'execution.cc', 'factory.cc', 'flags.cc', + 'frames.cc', 'global-handles.cc', 'handles.cc', 'hashmap.cc', 'heap.cc', + 'ic.cc', 'interpreter-irregexp.cc', 'jsregexp.cc', 'jump-target.cc', + 'log.cc', 'mark-compact.cc', 'messages.cc', 'objects.cc', 'parser.cc', + 'property.cc', 'regexp-macro-assembler.cc', + 'regexp-macro-assembler-irregexp.cc', 'regexp-stack.cc', + 'register-allocator.cc', 'rewriter.cc', 'runtime.cc', 'scanner.cc', 'scopeinfo.cc', 'scopes.cc', 'serialize.cc', 'snapshot-common.cc', 'spaces.cc', 'string-stream.cc', 'stub-cache.cc', 'token.cc', 'top.cc', - 'unicode.cc', 'usage-analyzer.cc', 'utils.cc', 'v8-counters.cc', 'v8.cc', - 'v8threads.cc', 'variables.cc', 'zone.cc' + 'unicode.cc', 'usage-analyzer.cc', 'utils.cc', 'v8-counters.cc', + 'v8.cc', 'v8threads.cc', 'variables.cc', 'virtual-frame.cc', 'zone.cc' + ], + 'arch:arm': [ + 'assembler-arm.cc', 'builtins-arm.cc', 'codegen-arm.cc', 'cpu-arm.cc', + 'disasm-arm.cc', 'debug-arm.cc', 'frames-arm.cc', 'ic-arm.cc', + 'jump-target-arm.cc', 'macro-assembler-arm.cc', + 'regexp-macro-assembler-arm.cc', 'register-allocator-arm.cc', + 'stub-cache-arm.cc', 'virtual-frame-arm.cc' + ], + 'arch:ia32': [ + 'assembler-ia32.cc', 'builtins-ia32.cc', 'codegen-ia32.cc', + 'cpu-ia32.cc', 'disasm-ia32.cc', 'debug-ia32.cc', 'frames-ia32.cc', + 'ic-ia32.cc', 'jump-target-ia32.cc', 'macro-assembler-ia32.cc', + 'regexp-macro-assembler-ia32.cc', 'register-allocator-ia32.cc', + 'stub-cache-ia32.cc', 'virtual-frame-ia32.cc' ], - 'arch:arm': ['assembler-arm.cc', 'builtins-arm.cc', 'codegen-arm.cc', - 'cpu-arm.cc', 'debug-arm.cc', 'disasm-arm.cc', 'frames-arm.cc', - 'ic-arm.cc', 'macro-assembler-arm.cc', 'regexp-macro-assembler-arm.cc', - 'stub-cache-arm.cc'], - 'arch:ia32': ['assembler-ia32.cc', 'builtins-ia32.cc', 'codegen-ia32.cc', - 'cpu-ia32.cc', 'debug-ia32.cc', 'disasm-ia32.cc', 'frames-ia32.cc', - 'ic-ia32.cc', 'macro-assembler-ia32.cc', 'regexp-macro-assembler-ia32.cc', - 'stub-cache-ia32.cc'], 'simulator:arm': ['simulator-arm.cc'], 'os:freebsd': ['platform-freebsd.cc'], 'os:linux': ['platform-linux.cc'], diff --git a/src/assembler-arm.h b/src/assembler-arm.h index d8aa0681b..310a3a45a 100644 --- a/src/assembler-arm.h +++ b/src/assembler-arm.h @@ -83,6 +83,8 @@ struct Register { }; +const int kNumRegisters = 16; + extern Register no_reg; extern Register r0; extern Register r1; @@ -211,6 +213,12 @@ inline Condition ReverseCondition(Condition cc) { } +// Branch hints are not used on the ARM. They are defined so that they can +// appear in shared function signatures, but will be ignored in ARM +// implementations. +enum Hint { no_hint }; + + // The pc store offset may be 8 or 12 depending on the processor implementation. int PcStoreOffset(); diff --git a/src/assembler-ia32.cc b/src/assembler-ia32.cc index f57229f2f..ee51cb416 100644 --- a/src/assembler-ia32.cc +++ b/src/assembler-ia32.cc @@ -751,6 +751,18 @@ void Assembler::cmov(Condition cc, Register dst, const Operand& src) { } +void Assembler::xchg(Register dst, Register src) { + EnsureSpace ensure_space(this); + last_pc_ = pc_; + if (src.is(eax) || dst.is(eax)) { // Single-byte encoding + EMIT(0x90 | (src.is(eax) ? dst.code() : src.code())); + } else { + EMIT(0x87); + EMIT(0xC0 | src.code() << 3 | dst.code()); + } +} + + void Assembler::adc(Register dst, int32_t imm32) { EnsureSpace ensure_space(this); last_pc_ = pc_; @@ -1847,6 +1859,16 @@ void Assembler::sahf() { } +void Assembler::setcc(Condition cc, Register reg) { + ASSERT(reg.is_byte_register()); + EnsureSpace ensure_space(this); + last_pc_ = pc_; + EMIT(0x0F); + EMIT(0x90 | cc); + EMIT(0xC0 | reg.code()); +} + + void Assembler::cvttss2si(Register dst, const Operand& src) { ASSERT(CpuFeatures::IsEnabled(CpuFeatures::SSE2)); EnsureSpace ensure_space(this); diff --git a/src/assembler-ia32.h b/src/assembler-ia32.h index 4a88b9db9..eaf558dc6 100644 --- a/src/assembler-ia32.h +++ b/src/assembler-ia32.h @@ -63,6 +63,8 @@ namespace v8 { namespace internal { struct Register { bool is_valid() const { return 0 <= code_ && code_ < 8; } bool is(Register reg) const { return code_ == reg.code_; } + // eax, ebx, ecx and edx are byte registers, the rest are not. + bool is_byte_register() const { return code_ <= 3; } int code() const { ASSERT(is_valid()); return code_; @@ -76,6 +78,8 @@ struct Register { int code_; }; +const int kNumRegisters = 8; + extern Register eax; extern Register ecx; extern Register edx; @@ -174,6 +178,15 @@ enum Hint { }; +// The result of negating a hint is as if the corresponding condition +// were negated by NegateCondition. That is, no_hint is mapped to +// itself and not_taken and taken are mapped to each other. +inline Hint NegateHint(Hint hint) { + return (hint == no_hint) + ? no_hint + : ((hint == not_taken) ? taken : not_taken); +} + // ----------------------------------------------------------------------------- // Machine instruction Immediates @@ -494,6 +507,9 @@ class Assembler : public Malloced { void cmov(Condition cc, Register dst, Handle handle); void cmov(Condition cc, Register dst, const Operand& src); + // Exchange two registers + void xchg(Register dst, Register src); + // Arithmetics void adc(Register dst, int32_t imm32); void adc(Register dst, const Operand& src); @@ -674,6 +690,7 @@ class Assembler : public Malloced { void frndint(); void sahf(); + void setcc(Condition cc, Register reg); void cpuid(); diff --git a/src/assembler.h b/src/assembler.h index 8d2188916..49c9b90f0 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -48,7 +48,7 @@ namespace v8 { namespace internal { // unknown pc location. Assembler::bind() is used to bind a label to the // current pc. A label can be bound only once. -class Label : public ZoneObject { // LabelShadows are dynamically allocated. +class Label BASE_EMBEDDED { public: INLINE(Label()) { Unuse(); } INLINE(~Label()) { ASSERT(!is_linked()); } @@ -84,58 +84,11 @@ class Label : public ZoneObject { // LabelShadows are dynamically allocated. friend class Assembler; friend class RegexpAssembler; friend class Displacement; - friend class LabelShadow; + friend class ShadowTarget; friend class RegExpMacroAssemblerIrregexp; }; -// A LabelShadow represents a label that is temporarily shadowed by another -// label (represented by the original label during shadowing). They are used -// to catch jumps to labels in certain contexts, e.g. try blocks. After -// shadowing ends, the formerly shadowed label is again represented by the -// original label and the LabelShadow can be used as a label in its own -// right, representing the formerly shadowing label. -class LabelShadow : public Label { - public: - explicit LabelShadow(Label* original) { - ASSERT(original != NULL); - original_label_ = original; - original_pos_ = original->pos_; - original->Unuse(); -#ifdef DEBUG - is_shadowing_ = true; -#endif - } - - ~LabelShadow() { - ASSERT(!is_shadowing_); - } - - void StopShadowing() { - ASSERT(is_shadowing_ && is_unused()); - pos_ = original_label_->pos_; - original_label_->pos_ = original_pos_; -#ifdef DEBUG - is_shadowing_ = false; -#endif - } - - Label* original_label() const { return original_label_; } - - private: - // During shadowing, the currently shadowing label. After shadowing, the - // label that was shadowed. - Label* original_label_; - - // During shadowing, the saved state of the original label. - int original_pos_; - -#ifdef DEBUG - bool is_shadowing_; -#endif -}; - - // ----------------------------------------------------------------------------- // Relocation information diff --git a/src/ast.cc b/src/ast.cc index 3197aa90e..a577d383d 100644 --- a/src/ast.cc +++ b/src/ast.cc @@ -148,13 +148,13 @@ ObjectLiteral::Property::Property(bool is_getter, FunctionLiteral* value) { } -void LabelCollector::AddLabel(Label* label) { +void TargetCollector::AddTarget(JumpTarget* target) { // Add the label to the collector, but discard duplicates. - int length = labels_->length(); + int length = targets_->length(); for (int i = 0; i < length; i++) { - if (labels_->at(i) == label) return; + if (targets_->at(i) == target) return; } - labels_->Add(label); + targets_->Add(target); } diff --git a/src/ast.h b/src/ast.h index c0fa4146a..a57a87882 100644 --- a/src/ast.h +++ b/src/ast.h @@ -35,6 +35,7 @@ #include "variables.h" #include "macro-assembler.h" #include "jsregexp.h" +#include "jump-target.h" namespace v8 { namespace internal { @@ -92,6 +93,9 @@ namespace v8 { namespace internal { V(ThisFunction) +// Forward declarations +class TargetCollector; + #define DEF_FORWARD_DECLARATION(type) class type; NODE_LIST(DEF_FORWARD_DECLARATION) #undef DEF_FORWARD_DECLARATION @@ -118,7 +122,7 @@ class Node: public ZoneObject { virtual VariableProxy* AsVariableProxy() { return NULL; } virtual Property* AsProperty() { return NULL; } virtual Call* AsCall() { return NULL; } - virtual LabelCollector* AsLabelCollector() { return NULL; } + virtual TargetCollector* AsTargetCollector() { return NULL; } virtual BreakableStatement* AsBreakableStatement() { return NULL; } virtual IterationStatement* AsIterationStatement() { return NULL; } virtual UnaryOperation* AsUnaryOperation() { return NULL; } @@ -192,7 +196,7 @@ class BreakableStatement: public Statement { virtual BreakableStatement* AsBreakableStatement() { return this; } // Code generation - Label* break_target() { return &break_target_; } + JumpTarget* break_target() { return &break_target_; } // Used during code generation for restoring the stack when a // break/continue crosses a statement that keeps stuff on the stack. @@ -211,7 +215,7 @@ class BreakableStatement: public Statement { private: ZoneStringList* labels_; Type type_; - Label break_target_; + JumpTarget break_target_; int break_stack_height_; }; @@ -268,7 +272,7 @@ class IterationStatement: public BreakableStatement { Statement* body() const { return body_; } // Code generation - Label* continue_target() { return &continue_target_; } + JumpTarget* continue_target() { return &continue_target_; } protected: explicit IterationStatement(ZoneStringList* labels) @@ -280,7 +284,7 @@ class IterationStatement: public BreakableStatement { private: Statement* body_; - Label continue_target_; + JumpTarget continue_target_; }; @@ -503,43 +507,45 @@ class IfStatement: public Statement { }; -// NOTE: LabelCollectors are represented as nodes to fit in the target +// NOTE: TargetCollectors are represented as nodes to fit in the target // stack in the compiler; this should probably be reworked. -class LabelCollector: public Node { +class TargetCollector: public Node { public: - explicit LabelCollector(ZoneList* labels) : labels_(labels) { } + explicit TargetCollector(ZoneList* targets) + : targets_(targets) { + } - // Adds a label to the collector. The collector stores a pointer not - // a copy of the label to make binding work, so make sure not to - // pass in references to something on the stack. - void AddLabel(Label* label); + // Adds a jump target to the collector. The collector stores a pointer not + // a copy of the target to make binding work, so make sure not to pass in + // references to something on the stack. + void AddTarget(JumpTarget* target); - // Virtual behaviour. LabelCollectors are never part of the AST. + // Virtual behaviour. TargetCollectors are never part of the AST. virtual void Accept(AstVisitor* v) { UNREACHABLE(); } - virtual LabelCollector* AsLabelCollector() { return this; } + virtual TargetCollector* AsTargetCollector() { return this; } - ZoneList* labels() { return labels_; } + ZoneList* targets() { return targets_; } private: - ZoneList* labels_; + ZoneList* targets_; }; class TryStatement: public Statement { public: explicit TryStatement(Block* try_block) - : try_block_(try_block), escaping_labels_(NULL) { } + : try_block_(try_block), escaping_targets_(NULL) { } - void set_escaping_labels(ZoneList* labels) { - escaping_labels_ = labels; + void set_escaping_targets(ZoneList* targets) { + escaping_targets_ = targets; } Block* try_block() const { return try_block_; } - ZoneList* escaping_labels() const { return escaping_labels_; } + ZoneList* escaping_targets() const { return escaping_targets_; } private: Block* try_block_; - ZoneList* escaping_labels_; + ZoneList* escaping_targets_; }; diff --git a/src/codegen-arm.cc b/src/codegen-arm.cc index 8a47f8c23..e1f388254 100644 --- a/src/codegen-arm.cc +++ b/src/codegen-arm.cc @@ -37,82 +37,6 @@ namespace v8 { namespace internal { #define __ masm_-> -// ------------------------------------------------------------------------- -// VirtualFrame implementation. - -VirtualFrame::VirtualFrame(CodeGenerator* cgen) { - ASSERT(cgen->scope() != NULL); - - masm_ = cgen->masm(); - frame_local_count_ = cgen->scope()->num_stack_slots(); - parameter_count_ = cgen->scope()->num_parameters(); -} - - -void VirtualFrame::Enter() { - Comment cmnt(masm_, "[ Enter JS frame"); -#ifdef DEBUG - { Label done, fail; - __ tst(r1, Operand(kSmiTagMask)); - __ b(eq, &fail); - __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); - __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); - __ cmp(r2, Operand(JS_FUNCTION_TYPE)); - __ b(eq, &done); - __ bind(&fail); - __ stop("CodeGenerator::EnterJSFrame - r1 not a function"); - __ bind(&done); - } -#endif // DEBUG - - __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); - // Adjust FP to point to saved FP. - __ add(fp, sp, Operand(2 * kPointerSize)); -} - - -void VirtualFrame::Exit() { - Comment cmnt(masm_, "[ Exit JS frame"); - // Drop the execution stack down to the frame pointer and restore the caller - // frame pointer and return address. - __ mov(sp, fp); - __ ldm(ia_w, sp, fp.bit() | lr.bit()); -} - - -void VirtualFrame::AllocateLocals() { - if (frame_local_count_ > 0) { - Comment cmnt(masm_, "[ Allocate space for locals"); - // Initialize stack slots with 'undefined' value. - __ mov(ip, Operand(Factory::undefined_value())); - for (int i = 0; i < frame_local_count_; i++) { - __ push(ip); - } - } -} - - -void VirtualFrame::Drop(int count) { - ASSERT(count >= 0); - if (count > 0) { - __ add(sp, sp, Operand(count * kPointerSize)); - } -} - - -void VirtualFrame::Pop() { Drop(1); } - - -void VirtualFrame::Pop(Register reg) { - __ pop(reg); -} - - -void VirtualFrame::Push(Register reg) { - __ push(reg); -} - - // ------------------------------------------------------------------------- // CodeGenState implementation. @@ -128,8 +52,8 @@ CodeGenState::CodeGenState(CodeGenerator* owner) CodeGenState::CodeGenState(CodeGenerator* owner, TypeofState typeof_state, - Label* true_target, - Label* false_target) + JumpTarget* true_target, + JumpTarget* false_target) : owner_(owner), typeof_state_(typeof_state), true_target_(true_target), @@ -156,17 +80,19 @@ CodeGenerator::CodeGenerator(int buffer_size, Handle