mirror of https://github.com/lukechilds/node.git
Ryan Dahl
15 years ago
176 changed files with 8628 additions and 6128 deletions
@ -1,263 +0,0 @@ |
|||
// Copyright (c) 1994-2006 Sun Microsystems Inc.
|
|||
// All Rights Reserved.
|
|||
//
|
|||
// Redistribution and use in source and binary forms, with or without
|
|||
// modification, are permitted provided that the following conditions
|
|||
// are met:
|
|||
//
|
|||
// - Redistributions of source code must retain the above copyright notice,
|
|||
// this list of conditions and the following disclaimer.
|
|||
//
|
|||
// - Redistribution in binary form must reproduce the above copyright
|
|||
// notice, this list of conditions and the following disclaimer in the
|
|||
// documentation and/or other materials provided with the
|
|||
// distribution.
|
|||
//
|
|||
// - Neither the name of Sun Microsystems or the names of contributors may
|
|||
// be used to endorse or promote products derived from this software without
|
|||
// specific prior written permission.
|
|||
//
|
|||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|||
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|||
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|||
// OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
|||
// 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.
|
|||
|
|||
#ifndef V8_ARM_ASSEMBLER_THUMB2_INL_H_ |
|||
#define V8_ARM_ASSEMBLER_THUMB2_INL_H_ |
|||
|
|||
#include "arm/assembler-thumb2.h" |
|||
#include "cpu.h" |
|||
|
|||
|
|||
namespace v8 { |
|||
namespace internal { |
|||
|
|||
Condition NegateCondition(Condition cc) { |
|||
ASSERT(cc != al); |
|||
return static_cast<Condition>(cc ^ ne); |
|||
} |
|||
|
|||
|
|||
void RelocInfo::apply(intptr_t delta) { |
|||
if (RelocInfo::IsInternalReference(rmode_)) { |
|||
// absolute code pointer inside code object moves with the code object.
|
|||
int32_t* p = reinterpret_cast<int32_t*>(pc_); |
|||
*p += delta; // relocate entry
|
|||
} |
|||
// We do not use pc relative addressing on ARM, so there is
|
|||
// nothing else to do.
|
|||
} |
|||
|
|||
|
|||
Address RelocInfo::target_address() { |
|||
ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); |
|||
return Assembler::target_address_at(pc_); |
|||
} |
|||
|
|||
|
|||
Address RelocInfo::target_address_address() { |
|||
ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); |
|||
return reinterpret_cast<Address>(Assembler::target_address_address_at(pc_)); |
|||
} |
|||
|
|||
|
|||
void RelocInfo::set_target_address(Address target) { |
|||
ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); |
|||
Assembler::set_target_address_at(pc_, target); |
|||
} |
|||
|
|||
|
|||
Object* RelocInfo::target_object() { |
|||
ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
|||
return Memory::Object_at(Assembler::target_address_address_at(pc_)); |
|||
} |
|||
|
|||
|
|||
Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { |
|||
ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
|||
return Memory::Object_Handle_at(Assembler::target_address_address_at(pc_)); |
|||
} |
|||
|
|||
|
|||
Object** RelocInfo::target_object_address() { |
|||
ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
|||
return reinterpret_cast<Object**>(Assembler::target_address_address_at(pc_)); |
|||
} |
|||
|
|||
|
|||
void RelocInfo::set_target_object(Object* target) { |
|||
ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
|||
Assembler::set_target_address_at(pc_, reinterpret_cast<Address>(target)); |
|||
} |
|||
|
|||
|
|||
Address* RelocInfo::target_reference_address() { |
|||
ASSERT(rmode_ == EXTERNAL_REFERENCE); |
|||
return reinterpret_cast<Address*>(Assembler::target_address_address_at(pc_)); |
|||
} |
|||
|
|||
|
|||
Address RelocInfo::call_address() { |
|||
ASSERT(IsPatchedReturnSequence()); |
|||
// 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(IsPatchedReturnSequence()); |
|||
// The 2 instructions offset assumes patched return sequence.
|
|||
ASSERT(IsJSReturn(rmode())); |
|||
Memory::Address_at(pc_ + 2 * Assembler::kInstrSize) = target; |
|||
} |
|||
|
|||
|
|||
Object* RelocInfo::call_object() { |
|||
return *call_object_address(); |
|||
} |
|||
|
|||
|
|||
Object** RelocInfo::call_object_address() { |
|||
ASSERT(IsPatchedReturnSequence()); |
|||
// The 2 instructions offset assumes patched return sequence.
|
|||
ASSERT(IsJSReturn(rmode())); |
|||
return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize); |
|||
} |
|||
|
|||
|
|||
void RelocInfo::set_call_object(Object* target) { |
|||
*call_object_address() = target; |
|||
} |
|||
|
|||
|
|||
bool RelocInfo::IsPatchedReturnSequence() { |
|||
// 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); |
|||
} |
|||
|
|||
|
|||
Operand::Operand(int32_t immediate, RelocInfo::Mode rmode) { |
|||
rm_ = no_reg; |
|||
imm32_ = immediate; |
|||
rmode_ = rmode; |
|||
} |
|||
|
|||
|
|||
Operand::Operand(const char* s) { |
|||
rm_ = no_reg; |
|||
imm32_ = reinterpret_cast<int32_t>(s); |
|||
rmode_ = RelocInfo::EMBEDDED_STRING; |
|||
} |
|||
|
|||
|
|||
Operand::Operand(const ExternalReference& f) { |
|||
rm_ = no_reg; |
|||
imm32_ = reinterpret_cast<int32_t>(f.address()); |
|||
rmode_ = RelocInfo::EXTERNAL_REFERENCE; |
|||
} |
|||
|
|||
|
|||
Operand::Operand(Smi* value) { |
|||
rm_ = no_reg; |
|||
imm32_ = reinterpret_cast<intptr_t>(value); |
|||
rmode_ = RelocInfo::NONE; |
|||
} |
|||
|
|||
|
|||
Operand::Operand(Register rm) { |
|||
rm_ = rm; |
|||
rs_ = no_reg; |
|||
shift_op_ = LSL; |
|||
shift_imm_ = 0; |
|||
} |
|||
|
|||
|
|||
bool Operand::is_reg() const { |
|||
return rm_.is_valid() && |
|||
rs_.is(no_reg) && |
|||
shift_op_ == LSL && |
|||
shift_imm_ == 0; |
|||
} |
|||
|
|||
|
|||
void Assembler::CheckBuffer() { |
|||
if (buffer_space() <= kGap) { |
|||
GrowBuffer(); |
|||
} |
|||
if (pc_offset() >= next_buffer_check_) { |
|||
CheckConstPool(false, true); |
|||
} |
|||
} |
|||
|
|||
|
|||
void Assembler::emit(Instr x) { |
|||
CheckBuffer(); |
|||
*reinterpret_cast<Instr*>(pc_) = x; |
|||
pc_ += kInstrSize; |
|||
} |
|||
|
|||
|
|||
Address Assembler::target_address_address_at(Address pc) { |
|||
Address target_pc = pc; |
|||
Instr instr = Memory::int32_at(target_pc); |
|||
// If we have a bx instruction, the instruction before the bx is
|
|||
// what we need to patch.
|
|||
static const int32_t kBxInstMask = 0x0ffffff0; |
|||
static const int32_t kBxInstPattern = 0x012fff10; |
|||
if ((instr & kBxInstMask) == kBxInstPattern) { |
|||
target_pc -= kInstrSize; |
|||
instr = Memory::int32_at(target_pc); |
|||
} |
|||
// Verify that the instruction to patch is a
|
|||
// ldr<cond> <Rd>, [pc +/- offset_12].
|
|||
ASSERT((instr & 0x0f7f0000) == 0x051f0000); |
|||
int offset = instr & 0xfff; // offset_12 is unsigned
|
|||
if ((instr & (1 << 23)) == 0) offset = -offset; // U bit defines offset sign
|
|||
// Verify that the constant pool comes after the instruction referencing it.
|
|||
ASSERT(offset >= -4); |
|||
return target_pc + offset + 8; |
|||
} |
|||
|
|||
|
|||
Address Assembler::target_address_at(Address pc) { |
|||
return Memory::Address_at(target_address_address_at(pc)); |
|||
} |
|||
|
|||
|
|||
void Assembler::set_target_at(Address constant_pool_entry, |
|||
Address target) { |
|||
Memory::Address_at(constant_pool_entry) = target; |
|||
} |
|||
|
|||
|
|||
void Assembler::set_target_address_at(Address pc, Address target) { |
|||
Memory::Address_at(target_address_address_at(pc)) = target; |
|||
// Intuitively, we would think it is necessary to flush the instruction cache
|
|||
// after patching a target address in the code as follows:
|
|||
// CPU::FlushICache(pc, sizeof(target));
|
|||
// However, on ARM, no instruction was actually patched by the assignment
|
|||
// above; the target address is not part of an instruction, it is patched in
|
|||
// the constant pool and is read via a data access; the instruction accessing
|
|||
// this address in the constant pool remains unchanged.
|
|||
} |
|||
|
|||
} } // namespace v8::internal
|
|||
|
|||
#endif // V8_ARM_ASSEMBLER_THUMB2_INL_H_
|
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -0,0 +1,53 @@ |
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
|||
// Redistribution and use in source and binary forms, with or without
|
|||
// modification, are permitted provided that the following conditions are
|
|||
// met:
|
|||
//
|
|||
// * Redistributions of source code must retain the above copyright
|
|||
// notice, this list of conditions and the following disclaimer.
|
|||
// * Redistributions in binary form must reproduce the above
|
|||
// copyright notice, this list of conditions and the following
|
|||
// disclaimer in the documentation and/or other materials provided
|
|||
// with the distribution.
|
|||
// * Neither the name of Google Inc. nor the names of its
|
|||
// contributors may be used to endorse or promote products derived
|
|||
// from this software without specific prior written permission.
|
|||
//
|
|||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
|||
#ifndef V8_VIRTUAL_FRAME_ARM_INL_H_ |
|||
#define V8_VIRTUAL_FRAME_ARM_INL_H_ |
|||
|
|||
#include "assembler-arm.h" |
|||
#include "virtual-frame-arm.h" |
|||
|
|||
namespace v8 { |
|||
namespace internal { |
|||
|
|||
// These VirtualFrame methods should actually be in a virtual-frame-arm-inl.h
|
|||
// file if such a thing existed.
|
|||
MemOperand VirtualFrame::ParameterAt(int index) { |
|||
// Index -1 corresponds to the receiver.
|
|||
ASSERT(-1 <= index); // -1 is the receiver.
|
|||
ASSERT(index <= parameter_count()); |
|||
return MemOperand(fp, (1 + parameter_count() - index) * kPointerSize); |
|||
} |
|||
|
|||
// The receiver frame slot.
|
|||
MemOperand VirtualFrame::Receiver() { |
|||
return ParameterAt(-1); |
|||
} |
|||
|
|||
} } // namespace v8::internal
|
|||
|
|||
#endif // V8_VIRTUAL_FRAME_ARM_INL_H_
|
@ -0,0 +1,79 @@ |
|||
// Copyright 2010 the V8 project authors. All rights reserved.
|
|||
// Redistribution and use in source and binary forms, with or without
|
|||
// modification, are permitted provided that the following conditions are
|
|||
// met:
|
|||
//
|
|||
// * Redistributions of source code must retain the above copyright
|
|||
// notice, this list of conditions and the following disclaimer.
|
|||
// * Redistributions in binary form must reproduce the above
|
|||
// copyright notice, this list of conditions and the following
|
|||
// disclaimer in the documentation and/or other materials provided
|
|||
// with the distribution.
|
|||
// * Neither the name of Google Inc. nor the names of its
|
|||
// contributors may be used to endorse or promote products derived
|
|||
// from this software without specific prior written permission.
|
|||
//
|
|||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
|||
#include "v8.h" |
|||
|
|||
#include "ast.h" |
|||
|
|||
namespace v8 { |
|||
namespace internal { |
|||
|
|||
BreakableStatement::BreakableStatement(ZoneStringList* labels, Type type) |
|||
: labels_(labels), type_(type) { |
|||
ASSERT(labels == NULL || labels->length() > 0); |
|||
} |
|||
|
|||
|
|||
SwitchStatement::SwitchStatement(ZoneStringList* labels) |
|||
: BreakableStatement(labels, TARGET_FOR_ANONYMOUS), |
|||
tag_(NULL), cases_(NULL) { |
|||
} |
|||
|
|||
|
|||
IterationStatement::IterationStatement(ZoneStringList* labels) |
|||
: BreakableStatement(labels, TARGET_FOR_ANONYMOUS), body_(NULL) { |
|||
} |
|||
|
|||
|
|||
Block::Block(ZoneStringList* labels, int capacity, bool is_initializer_block) |
|||
: BreakableStatement(labels, TARGET_FOR_NAMED_ONLY), |
|||
statements_(capacity), |
|||
is_initializer_block_(is_initializer_block) { |
|||
} |
|||
|
|||
|
|||
ForStatement::ForStatement(ZoneStringList* labels) |
|||
: IterationStatement(labels), |
|||
init_(NULL), |
|||
cond_(NULL), |
|||
next_(NULL), |
|||
may_have_function_literal_(true), |
|||
loop_variable_(NULL), |
|||
peel_this_loop_(false) { |
|||
} |
|||
|
|||
|
|||
ForInStatement::ForInStatement(ZoneStringList* labels) |
|||
: IterationStatement(labels), each_(NULL), enumerable_(NULL) { |
|||
} |
|||
|
|||
|
|||
DoWhileStatement::DoWhileStatement(ZoneStringList* labels) |
|||
: IterationStatement(labels), cond_(NULL), condition_position_(-1) { |
|||
} |
|||
|
|||
} } // namespace v8::internal
|
File diff suppressed because it is too large
@ -0,0 +1,242 @@ |
|||
// Copyright 2008 the V8 project authors. All rights reserved.
|
|||
// Redistribution and use in source and binary forms, with or without
|
|||
// modification, are permitted provided that the following conditions are
|
|||
// met:
|
|||
//
|
|||
// * Redistributions of source code must retain the above copyright
|
|||
// notice, this list of conditions and the following disclaimer.
|
|||
// * Redistributions in binary form must reproduce the above
|
|||
// copyright notice, this list of conditions and the following
|
|||
// disclaimer in the documentation and/or other materials provided
|
|||
// with the distribution.
|
|||
// * Neither the name of Google Inc. nor the names of its
|
|||
// contributors may be used to endorse or promote products derived
|
|||
// from this software without specific prior written permission.
|
|||
//
|
|||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
|||
#ifndef V8_JUMP_TARGET_HEAVY_H_ |
|||
#define V8_JUMP_TARGET_HEAVY_H_ |
|||
|
|||
#include "macro-assembler.h" |
|||
#include "zone-inl.h" |
|||
|
|||
namespace v8 { |
|||
namespace internal { |
|||
|
|||
// Forward declarations.
|
|||
class FrameElement; |
|||
class Result; |
|||
class VirtualFrame; |
|||
|
|||
// -------------------------------------------------------------------------
|
|||
// Jump targets
|
|||
//
|
|||
// A jump target is an abstraction of a basic-block entry in generated
|
|||
// code. It collects all the virtual frames reaching the block by
|
|||
// forward jumps and pairs them with labels for the merge code along
|
|||
// all forward-reaching paths. When bound, an expected frame for the
|
|||
// block is determined and code is generated to merge to the expected
|
|||
// frame. For backward jumps, the merge code is generated at the edge
|
|||
// leaving the predecessor block.
|
|||
//
|
|||
// A jump target must have been reached via control flow (either by
|
|||
// jumping, branching, or falling through) at the time it is bound.
|
|||
// In particular, this means that at least one of the control-flow
|
|||
// graph edges reaching the target must be a forward edge.
|
|||
|
|||
class JumpTarget : public ZoneObject { // Shadows are dynamically allocated.
|
|||
public: |
|||
// Forward-only jump targets can only be reached by forward CFG edges.
|
|||
enum Directionality { FORWARD_ONLY, BIDIRECTIONAL }; |
|||
|
|||
// Construct a jump target used to generate code and to provide
|
|||
// access to a current frame.
|
|||
explicit JumpTarget(Directionality direction) |
|||
: direction_(direction), |
|||
reaching_frames_(0), |
|||
merge_labels_(0), |
|||
entry_frame_(NULL) { |
|||
} |
|||
|
|||
// Construct a jump target.
|
|||
JumpTarget() |
|||
: direction_(FORWARD_ONLY), |
|||
reaching_frames_(0), |
|||
merge_labels_(0), |
|||
entry_frame_(NULL) { |
|||
} |
|||
|
|||
virtual ~JumpTarget() {} |
|||
|
|||
// Set the direction of the jump target.
|
|||
virtual void set_direction(Directionality direction) { |
|||
direction_ = direction; |
|||
} |
|||
|
|||
// Treat the jump target as a fresh one. The state is reset.
|
|||
void Unuse(); |
|||
|
|||
inline CodeGenerator* cgen(); |
|||
|
|||
Label* entry_label() { return &entry_label_; } |
|||
|
|||
VirtualFrame* entry_frame() const { return entry_frame_; } |
|||
void set_entry_frame(VirtualFrame* frame) { |
|||
entry_frame_ = frame; |
|||
} |
|||
|
|||
// Predicates testing the state of the encapsulated label.
|
|||
bool is_bound() const { return entry_label_.is_bound(); } |
|||
bool is_linked() const { |
|||
return !is_bound() && !reaching_frames_.is_empty(); |
|||
} |
|||
bool is_unused() const { |
|||
// This is !is_bound() && !is_linked().
|
|||
return !is_bound() && reaching_frames_.is_empty(); |
|||
} |
|||
|
|||
// Emit a jump to the target. There must be a current frame at the
|
|||
// jump and there will be no current frame after the jump.
|
|||
virtual void Jump(); |
|||
virtual void Jump(Result* arg); |
|||
|
|||
// Emit a conditional branch to the target. There must be a current
|
|||
// frame at the branch. The current frame will fall through to the
|
|||
// code after the branch. The arg is a result that is live both at
|
|||
// the target and the fall-through.
|
|||
virtual void Branch(Condition cc, Hint hint = no_hint); |
|||
virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint); |
|||
virtual void Branch(Condition cc, |
|||
Result* arg0, |
|||
Result* arg1, |
|||
Hint hint = no_hint); |
|||
|
|||
// Bind a jump target. If there is no current frame at the binding
|
|||
// site, there must be at least one frame reaching via a forward
|
|||
// jump.
|
|||
virtual void Bind(); |
|||
virtual void Bind(Result* arg); |
|||
virtual void Bind(Result* arg0, Result* arg1); |
|||
|
|||
// Emit a call to a jump target. There must be a current frame at
|
|||
// the call. The frame at the target is the same as the current
|
|||
// frame except for an extra return address on top of it. The frame
|
|||
// after the call is the same as the frame before the call.
|
|||
void Call(); |
|||
|
|||
static void set_compiling_deferred_code(bool flag) { |
|||
compiling_deferred_code_ = flag; |
|||
} |
|||
|
|||
protected: |
|||
// Directionality flag set at initialization time.
|
|||
Directionality direction_; |
|||
|
|||
// A list of frames reaching this block via forward jumps.
|
|||
ZoneList<VirtualFrame*> reaching_frames_; |
|||
|
|||
// A parallel list of labels for merge code.
|
|||
ZoneList<Label> merge_labels_; |
|||
|
|||
// The frame used on entry to the block and expected at backward
|
|||
// jumps to the block. Set when the jump target is bound, but may
|
|||
// or may not be set for forward-only blocks.
|
|||
VirtualFrame* entry_frame_; |
|||
|
|||
// The actual entry label of the block.
|
|||
Label entry_label_; |
|||
|
|||
// Implementations of Jump, Branch, and Bind with all arguments and
|
|||
// return values using the virtual frame.
|
|||
void DoJump(); |
|||
void DoBranch(Condition cc, Hint hint); |
|||
void DoBind(); |
|||
|
|||
private: |
|||
static bool compiling_deferred_code_; |
|||
|
|||
// Add a virtual frame reaching this labeled block via a forward jump,
|
|||
// and a corresponding merge code label.
|
|||
void AddReachingFrame(VirtualFrame* frame); |
|||
|
|||
// Perform initialization required during entry frame computation
|
|||
// after setting the virtual frame element at index in frame to be
|
|||
// target.
|
|||
inline void InitializeEntryElement(int index, FrameElement* target); |
|||
|
|||
// Compute a frame to use for entry to this block.
|
|||
void ComputeEntryFrame(); |
|||
|
|||
DISALLOW_COPY_AND_ASSIGN(JumpTarget); |
|||
}; |
|||
|
|||
|
|||
// -------------------------------------------------------------------------
|
|||
// Break targets
|
|||
//
|
|||
// A break target is a jump target that can be used to break out of a
|
|||
// statement that keeps extra state on the stack (eg, for/in or
|
|||
// try/finally). They know the expected stack height at the target
|
|||
// and will drop state from nested statements as part of merging.
|
|||
//
|
|||
// Break targets are used for return, break, and continue targets.
|
|||
|
|||
class BreakTarget : public JumpTarget { |
|||
public: |
|||
// Construct a break target.
|
|||
BreakTarget() {} |
|||
|
|||
virtual ~BreakTarget() {} |
|||
|
|||
// Set the direction of the break target.
|
|||
virtual void set_direction(Directionality direction); |
|||
|
|||
// Copy the state of this break target to the destination. The
|
|||
// lists of forward-reaching frames and merge-point labels are
|
|||
// copied. All virtual frame pointers are copied, not the
|
|||
// pointed-to frames. The previous state of the destination is
|
|||
// overwritten, without deallocating pointed-to virtual frames.
|
|||
void CopyTo(BreakTarget* destination); |
|||
|
|||
// Emit a jump to the target. There must be a current frame at the
|
|||
// jump and there will be no current frame after the jump.
|
|||
virtual void Jump(); |
|||
virtual void Jump(Result* arg); |
|||
|
|||
// Emit a conditional branch to the target. There must be a current
|
|||
// frame at the branch. The current frame will fall through to the
|
|||
// code after the branch.
|
|||
virtual void Branch(Condition cc, Hint hint = no_hint); |
|||
virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint); |
|||
|
|||
// Bind a break target. If there is no current frame at the binding
|
|||
// site, there must be at least one frame reaching via a forward
|
|||
// jump.
|
|||
virtual void Bind(); |
|||
virtual void Bind(Result* arg); |
|||
|
|||
// Setter for expected height.
|
|||
void set_expected_height(int expected) { expected_height_ = expected; } |
|||
|
|||
private: |
|||
// The expected height of the expression stack where the target will
|
|||
// be bound, statically known at initialization time.
|
|||
int expected_height_; |
|||
|
|||
DISALLOW_COPY_AND_ASSIGN(BreakTarget); |
|||
}; |
|||
|
|||
} } // namespace v8::internal
|
|||
|
|||
#endif // V8_JUMP_TARGET_HEAVY_H_
|
@ -0,0 +1,187 @@ |
|||
// Copyright 2008 the V8 project authors. All rights reserved.
|
|||
// Redistribution and use in source and binary forms, with or without
|
|||
// modification, are permitted provided that the following conditions are
|
|||
// met:
|
|||
//
|
|||
// * Redistributions of source code must retain the above copyright
|
|||
// notice, this list of conditions and the following disclaimer.
|
|||
// * Redistributions in binary form must reproduce the above
|
|||
// copyright notice, this list of conditions and the following
|
|||
// disclaimer in the documentation and/or other materials provided
|
|||
// with the distribution.
|
|||
// * Neither the name of Google Inc. nor the names of its
|
|||
// contributors may be used to endorse or promote products derived
|
|||
// from this software without specific prior written permission.
|
|||
//
|
|||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
|||
#ifndef V8_JUMP_TARGET_LIGHT_H_ |
|||
#define V8_JUMP_TARGET_LIGHT_H_ |
|||
|
|||
#include "macro-assembler.h" |
|||
#include "zone-inl.h" |
|||
#include "virtual-frame.h" |
|||
|
|||
namespace v8 { |
|||
namespace internal { |
|||
|
|||
// Forward declarations.
|
|||
class FrameElement; |
|||
class Result; |
|||
|
|||
// -------------------------------------------------------------------------
|
|||
// Jump targets
|
|||
//
|
|||
// A jump target is an abstraction of a basic-block entry in generated
|
|||
// code. It collects all the virtual frames reaching the block by
|
|||
// forward jumps and pairs them with labels for the merge code along
|
|||
// all forward-reaching paths. When bound, an expected frame for the
|
|||
// block is determined and code is generated to merge to the expected
|
|||
// frame. For backward jumps, the merge code is generated at the edge
|
|||
// leaving the predecessor block.
|
|||
//
|
|||
// A jump target must have been reached via control flow (either by
|
|||
// jumping, branching, or falling through) at the time it is bound.
|
|||
// In particular, this means that at least one of the control-flow
|
|||
// graph edges reaching the target must be a forward edge.
|
|||
|
|||
class JumpTarget : public ZoneObject { // Shadows are dynamically allocated.
|
|||
public: |
|||
// Forward-only jump targets can only be reached by forward CFG edges.
|
|||
enum Directionality { FORWARD_ONLY, BIDIRECTIONAL }; |
|||
|
|||
// Construct a jump target.
|
|||
explicit inline JumpTarget(Directionality direction); |
|||
|
|||
inline JumpTarget(); |
|||
|
|||
virtual ~JumpTarget() {} |
|||
|
|||
void Unuse() { |
|||
entry_frame_set_ = false; |
|||
entry_label_.Unuse(); |
|||
} |
|||
|
|||
inline CodeGenerator* cgen(); |
|||
|
|||
const VirtualFrame* entry_frame() const { |
|||
return entry_frame_set_ ? &entry_frame_ : NULL; |
|||
} |
|||
|
|||
void set_entry_frame(VirtualFrame* frame) { |
|||
entry_frame_ = *frame; |
|||
entry_frame_set_ = true; |
|||
} |
|||
|
|||
// Predicates testing the state of the encapsulated label.
|
|||
bool is_bound() const { return entry_label_.is_bound(); } |
|||
bool is_linked() const { return entry_label_.is_linked(); } |
|||
bool is_unused() const { return entry_label_.is_unused(); } |
|||
|
|||
// Copy the state of this jump target to the destination.
|
|||
inline void CopyTo(JumpTarget* destination) { |
|||
*destination = *this; |
|||
} |
|||
|
|||
// Emit a jump to the target. There must be a current frame at the
|
|||
// jump and there will be no current frame after the jump.
|
|||
virtual void Jump(); |
|||
|
|||
// Emit a conditional branch to the target. There must be a current
|
|||
// frame at the branch. The current frame will fall through to the
|
|||
// code after the branch. The arg is a result that is live both at
|
|||
// the target and the fall-through.
|
|||
virtual void Branch(Condition cc, Hint hint = no_hint); |
|||
|
|||
// Bind a jump target. If there is no current frame at the binding
|
|||
// site, there must be at least one frame reaching via a forward
|
|||
// jump.
|
|||
virtual void Bind(); |
|||
|
|||
// Emit a call to a jump target. There must be a current frame at
|
|||
// the call. The frame at the target is the same as the current
|
|||
// frame except for an extra return address on top of it. The frame
|
|||
// after the call is the same as the frame before the call.
|
|||
void Call(); |
|||
|
|||
protected: |
|||
// Has an entry frame been found?
|
|||
bool entry_frame_set_; |
|||
|
|||
// The frame used on entry to the block and expected at backward
|
|||
// jumps to the block. Set the first time something branches to this
|
|||
// jump target.
|
|||
VirtualFrame entry_frame_; |
|||
|
|||
// The actual entry label of the block.
|
|||
Label entry_label_; |
|||
|
|||
// Implementations of Jump, Branch, and Bind with all arguments and
|
|||
// return values using the virtual frame.
|
|||
void DoJump(); |
|||
void DoBranch(Condition cc, Hint hint); |
|||
void DoBind(); |
|||
}; |
|||
|
|||
|
|||
// -------------------------------------------------------------------------
|
|||
// Break targets
|
|||
//
|
|||
// A break target is a jump target that can be used to break out of a
|
|||
// statement that keeps extra state on the stack (eg, for/in or
|
|||
// try/finally). They know the expected stack height at the target
|
|||
// and will drop state from nested statements as part of merging.
|
|||
//
|
|||
// Break targets are used for return, break, and continue targets.
|
|||
|
|||
class BreakTarget : public JumpTarget { |
|||
public: |
|||
// Construct a break target.
|
|||
inline BreakTarget(); |
|||
|
|||
virtual ~BreakTarget() {} |
|||
|
|||
// Copy the state of this jump target to the destination.
|
|||
inline void CopyTo(BreakTarget* destination) { |
|||
*destination = *this; |
|||
} |
|||
|
|||
// Emit a jump to the target. There must be a current frame at the
|
|||
// jump and there will be no current frame after the jump.
|
|||
virtual void Jump(); |
|||
|
|||
// Emit a conditional branch to the target. There must be a current
|
|||
// frame at the branch. The current frame will fall through to the
|
|||
// code after the branch.
|
|||
virtual void Branch(Condition cc, Hint hint = no_hint); |
|||
|
|||
// Bind a break target. If there is no current frame at the binding
|
|||
// site, there must be at least one frame reaching via a forward
|
|||
// jump.
|
|||
virtual void Bind(); |
|||
|
|||
// Setter for expected height.
|
|||
void set_expected_height(int expected) { expected_height_ = expected; } |
|||
|
|||
// Uses the current frame to set the expected height.
|
|||
void SetExpectedHeight(); |
|||
|
|||
private: |
|||
// The expected height of the expression stack where the target will
|
|||
// be bound, statically known at initialization time.
|
|||
int expected_height_; |
|||
}; |
|||
|
|||
} } // namespace v8::internal
|
|||
|
|||
#endif // V8_JUMP_TARGET_LIGHT_H_
|
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue