"""),
'arch:arm': Split("""
fast-codegen.cc
+ jump-target-light.cc
+ virtual-frame-light.cc
arm/builtins-arm.cc
arm/codegen-arm.cc
arm/constants-arm.cc
mips/virtual-frame-mips.cc
"""),
'arch:ia32': Split("""
+ jump-target-heavy.cc
+ virtual-frame-heavy.cc
ia32/assembler-ia32.cc
ia32/builtins-ia32.cc
ia32/codegen-ia32.cc
"""),
'arch:x64': Split("""
fast-codegen.cc
+ jump-target-heavy.cc
+ virtual-frame-heavy.cc
x64/assembler-x64.cc
x64/builtins-x64.cc
x64/codegen-x64.cc
void BreakTarget::Jump(Result* arg) {
- // On ARM we do not currently emit merge code for jumps, so we need to do
- // it explicitly here. The only merging necessary is to drop extra
- // statement state from the stack.
- ASSERT(cgen()->has_valid_frame());
- int count = cgen()->frame()->height() - expected_height_;
- cgen()->frame()->Drop(count);
- cgen()->frame()->Push(arg);
- DoJump();
+ UNIMPLEMENTED();
}
void BreakTarget::Bind(Result* arg) {
-#ifdef DEBUG
- // All the forward-reaching frames should have been adjusted at the
- // jumps to this target.
- for (int i = 0; i < reaching_frames_.length(); i++) {
- ASSERT(reaching_frames_[i] == NULL ||
- reaching_frames_[i]->height() == expected_height_ + 1);
- }
-#endif
- // Drop leftover statement state from the frame before merging, even
- // on the fall through. This is so we can bind the return target
- // with state on the frame.
- if (cgen()->has_valid_frame()) {
- int count = cgen()->frame()->height() - expected_height_;
- // On ARM we do not currently emit merge code at binding sites, so we need
- // to do it explicitly here. The only merging necessary is to drop extra
- // statement state from the stack.
- cgen()->frame()->ForgetElements(count);
- cgen()->frame()->Push(arg);
- }
- DoBind();
- *arg = cgen()->frame()->Pop();
+ UNIMPLEMENTED();
}
}
-void VirtualFrame::SyncRange(int begin, int end) {
- // All elements are in memory on ARM (ie, synced).
-#ifdef DEBUG
- for (int i = begin; i <= end; i++) {
- ASSERT(elements_[i].is_synced());
- }
-#endif
-}
-
-
void VirtualFrame::MergeTo(VirtualFrame* expected) {
// ARM frames are currently always in memory.
ASSERT(Equals(expected));
}
// Discard elements from the virtual frame and free any registers.
- for (int i = 0; i < count; i++) {
- FrameElement dropped = elements_.RemoveLast();
- if (dropped.is_register()) {
- Unuse(dropped.reg());
- }
- }
+ element_count_ -= count;
}
void VirtualFrame::EmitPop(Register reg) {
ASSERT(stack_pointer_ == element_count() - 1);
stack_pointer_--;
- elements_.RemoveLast();
+ element_count_--;
__ pop(reg);
}
void VirtualFrame::EmitPush(Register reg) {
ASSERT(stack_pointer_ == element_count() - 1);
- elements_.Add(FrameElement::MemoryElement(TypeInfo::Unknown()));
+ element_count_++;
stack_pointer_++;
__ push(reg);
}
CodeGenerator* cgen() { return CodeGeneratorScope::Current(); }
MacroAssembler* masm() { return cgen()->masm(); }
- // Create a duplicate of an existing valid frame element.
- FrameElement CopyElementAt(int index,
- TypeInfo info = TypeInfo::Unknown());
-
// The number of elements on the virtual frame.
- int element_count() { return elements_.length(); }
+ int element_count() { return element_count_; }
// The height of the virtual expression stack.
int height() {
stack_pointer_ -= count;
// On ARM, all elements are in memory, so there is no extra bookkeeping
// (registers, copies, etc.) beyond dropping the elements.
- elements_.Rewind(stack_pointer_ + 1);
+ element_count_ -= count;
}
// Forget count elements from the top of the frame and adjust the stack
void ForgetElements(int count);
// Spill all values from the frame to memory.
- void SpillAll();
+ inline void SpillAll();
// Spill all occurrences of a specific register from the frame.
void Spill(Register reg) {
// dropping all non-locals elements in the virtual frame. This
// avoids generating unnecessary merge code when jumping to the
// shared return site. Emits code for spills.
- void PrepareForReturn();
+ inline void PrepareForReturn();
// Number of local variables after when we use a loop for allocating.
static const int kLocalVarBound = 5;
SetElementAt(index, &temp);
}
- void PushElementAt(int index) {
- PushFrameSlotAt(element_count() - index - 1);
- }
-
// A frame-allocated local as an assembly operand.
MemOperand LocalAt(int index) {
ASSERT(0 <= index);
return MemOperand(fp, kLocal0Offset - index * kPointerSize);
}
- // Push a copy of the value of a local frame slot on top of the frame.
- void PushLocalAt(int index) {
- PushFrameSlotAt(local0_index() + index);
- }
-
// Push the value of a local frame slot on top of the frame and invalidate
// the local slot. The slot should be written to before trying to read
// from it again.
TakeFrameSlotAt(local0_index() + index);
}
- // Store the top value on the virtual frame into a local frame slot. The
- // value is left in place on top of the frame.
- void StoreToLocalAt(int index) {
- StoreToFrameSlotAt(local0_index() + index);
- }
-
// Push the address of the receiver slot on the frame.
void PushReceiverSlotAddress();
// The function frame slot.
MemOperand Function() { return MemOperand(fp, kFunctionOffset); }
- // Push the function on top of the frame.
- void PushFunction() { PushFrameSlotAt(function_index()); }
-
// The context frame slot.
MemOperand Context() { return MemOperand(fp, kContextOffset); }
return MemOperand(fp, (1 + parameter_count() - index) * kPointerSize);
}
- // Push a copy of the value of a parameter frame slot on top of the frame.
- void PushParameterAt(int index) {
- PushFrameSlotAt(param0_index() + index);
- }
-
// Push the value of a paramter frame slot on top of the frame and
// invalidate the parameter slot. The slot should be written to before
// trying to read from it again.
// Drop one element.
void Drop() { Drop(1); }
- // Duplicate the top element of the frame.
- void Dup() { PushFrameSlotAt(element_count() - 1); }
-
// Pop an element from the top of the expression stack. Returns a
// Result, which may be a constant or a register.
Result Pop();
void EmitPushMultiple(int count, int src_regs);
// Push an element on the virtual frame.
- inline void Push(Register reg, TypeInfo info = TypeInfo::Unknown());
inline void Push(Handle<Object> value);
inline void Push(Smi* value);
- // Pushing a result invalidates it (its contents become owned by the frame).
- void Push(Result* result) {
- if (result->is_register()) {
- Push(result->reg());
- } else {
- ASSERT(result->is_constant());
- Push(result->handle());
- }
- result->Unuse();
- }
-
// Nip removes zero or more elements from immediately below the top
// of the frame, leaving the previous top-of-frame value on top of
// the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x).
static const int kHandlerSize = StackHandlerConstants::kSize / kPointerSize;
static const int kPreallocatedElements = 5 + 8; // 8 expression stack slots.
- ZoneList<FrameElement> elements_;
+ // The number of elements on the stack frame.
+ int element_count_;
// The index of the element that is at the processor's stack pointer
// (the sp register).
// Keep the element type as register or constant, and clear the dirty bit.
void SyncElementAt(int index);
- // Sync the range of elements in [begin, end] with memory.
- void SyncRange(int begin, int end);
-
// Sync a single unsynced element that lies beneath or at the stack pointer.
void SyncElementBelowStackPointer(int index);
// Sync a single unsynced element that lies just above the stack pointer.
void SyncElementByPushing(int index);
- // Push a copy of a frame slot (typically a local or parameter) on top of
- // the frame.
- inline void PushFrameSlotAt(int index);
-
// Push a the value of a frame slot (typically a local or parameter) on
// top of the frame and invalidate the slot.
void TakeFrameSlotAt(int index);
inline bool Equals(VirtualFrame* other);
- // Classes that need raw access to the elements_ array.
- friend class DeferredCode;
friend class JumpTarget;
+ friend class DeferredCode;
};
CodeGenerator* CodeGeneratorScope::top_ = NULL;
-DeferredCode::DeferredCode()
- : masm_(CodeGeneratorScope::Current()->masm()),
- statement_position_(masm_->current_statement_position()),
- position_(masm_->current_position()) {
- ASSERT(statement_position_ != RelocInfo::kNoPosition);
- ASSERT(position_ != RelocInfo::kNoPosition);
-
- CodeGeneratorScope::Current()->AddDeferred(this);
-#ifdef DEBUG
- comment_ = "";
-#endif
-
- // Copy the register locations from the code generator's frame.
- // These are the registers that will be spilled on entry to the
- // deferred code and restored on exit.
- VirtualFrame* frame = CodeGeneratorScope::Current()->frame();
- int sp_offset = frame->fp_relative(frame->stack_pointer_);
- for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
- int loc = frame->register_location(i);
- if (loc == VirtualFrame::kIllegalIndex) {
- registers_[i] = kIgnore;
- } else if (frame->elements_[loc].is_synced()) {
- // Needs to be restored on exit but not saved on entry.
- registers_[i] = frame->fp_relative(loc) | kSyncedFlag;
- } else {
- int offset = frame->fp_relative(loc);
- registers_[i] = (offset < sp_offset) ? kPush : offset;
- }
- }
-}
-
-
void CodeGenerator::ProcessDeferred() {
while (!deferred_.is_empty()) {
DeferredCode* code = deferred_.RemoveLast();
void ForgetElements(int count);
// Spill all values from the frame to memory.
- void SpillAll();
+ inline void SpillAll();
// Spill all occurrences of a specific register from the frame.
void Spill(Register reg) {
// Prepare for returning from the frame by spilling locals. This
// avoids generating unnecessary merge code when jumping to the
// shared return site. Emits code for spills.
- void PrepareForReturn();
+ inline void PrepareForReturn();
// Number of local variables after when we use a loop for allocating.
static const int kLocalVarBound = 10;
--- /dev/null
+// 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_JUMP_TARGET_HEAVY_INL_H_
+#define V8_JUMP_TARGET_HEAVY_INL_H_
+
+#include "virtual-frame-inl.h"
+
+namespace v8 {
+namespace internal {
+
+void JumpTarget::InitializeEntryElement(int index, FrameElement* target) {
+ FrameElement* element = &entry_frame_->elements_[index];
+ element->clear_copied();
+ if (target->is_register()) {
+ entry_frame_->set_register_location(target->reg(), index);
+ } else if (target->is_copy()) {
+ entry_frame_->elements_[target->index()].set_copied();
+ }
+ if (direction_ == BIDIRECTIONAL && !target->is_copy()) {
+ element->set_type_info(TypeInfo::Unknown());
+ }
+}
+
+} } // namespace v8::internal
+
+#endif // V8_JUMP_TARGET_HEAVY_INL_H_
--- /dev/null
+// 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 "codegen-inl.h"
+#include "jump-target-inl.h"
+#include "register-allocator-inl.h"
+
+namespace v8 {
+namespace internal {
+
+
+void JumpTarget::Jump(Result* arg) {
+ ASSERT(cgen()->has_valid_frame());
+
+ cgen()->frame()->Push(arg);
+ DoJump();
+}
+
+
+void JumpTarget::Branch(Condition cc, Result* arg, Hint hint) {
+ ASSERT(cgen()->has_valid_frame());
+
+ // We want to check that non-frame registers at the call site stay in
+ // the same registers on the fall-through branch.
+#ifdef DEBUG
+ Result::Type arg_type = arg->type();
+ Register arg_reg = arg->is_register() ? arg->reg() : no_reg;
+#endif
+
+ cgen()->frame()->Push(arg);
+ DoBranch(cc, hint);
+ *arg = cgen()->frame()->Pop();
+
+ ASSERT(arg->type() == arg_type);
+ ASSERT(!arg->is_register() || arg->reg().is(arg_reg));
+}
+
+
+void JumpTarget::Branch(Condition cc, Result* arg0, Result* arg1, Hint hint) {
+ ASSERT(cgen()->has_valid_frame());
+
+ // We want to check that non-frame registers at the call site stay in
+ // the same registers on the fall-through branch.
+#ifdef DEBUG
+ Result::Type arg0_type = arg0->type();
+ Register arg0_reg = arg0->is_register() ? arg0->reg() : no_reg;
+ Result::Type arg1_type = arg1->type();
+ Register arg1_reg = arg1->is_register() ? arg1->reg() : no_reg;
+#endif
+
+ cgen()->frame()->Push(arg0);
+ cgen()->frame()->Push(arg1);
+ DoBranch(cc, hint);
+ *arg1 = cgen()->frame()->Pop();
+ *arg0 = cgen()->frame()->Pop();
+
+ ASSERT(arg0->type() == arg0_type);
+ ASSERT(!arg0->is_register() || arg0->reg().is(arg0_reg));
+ ASSERT(arg1->type() == arg1_type);
+ ASSERT(!arg1->is_register() || arg1->reg().is(arg1_reg));
+}
+
+
+void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) {
+ ASSERT(cgen()->has_valid_frame());
+
+ int count = cgen()->frame()->height() - expected_height_;
+ if (count > 0) {
+ // We negate and branch here rather than using DoBranch's negate
+ // and branch. This gives us a hook to remove statement state
+ // from the frame.
+ JumpTarget fall_through;
+ // Branch to fall through will not negate, because it is a
+ // forward-only target.
+ fall_through.Branch(NegateCondition(cc), NegateHint(hint));
+ Jump(arg); // May emit merge code here.
+ fall_through.Bind();
+ } else {
+#ifdef DEBUG
+ Result::Type arg_type = arg->type();
+ Register arg_reg = arg->is_register() ? arg->reg() : no_reg;
+#endif
+ cgen()->frame()->Push(arg);
+ DoBranch(cc, hint);
+ *arg = cgen()->frame()->Pop();
+ ASSERT(arg->type() == arg_type);
+ ASSERT(!arg->is_register() || arg->reg().is(arg_reg));
+ }
+}
+
+
+void JumpTarget::Bind(Result* arg) {
+ if (cgen()->has_valid_frame()) {
+ cgen()->frame()->Push(arg);
+ }
+ DoBind();
+ *arg = cgen()->frame()->Pop();
+}
+
+
+void JumpTarget::Bind(Result* arg0, Result* arg1) {
+ if (cgen()->has_valid_frame()) {
+ cgen()->frame()->Push(arg0);
+ cgen()->frame()->Push(arg1);
+ }
+ DoBind();
+ *arg1 = cgen()->frame()->Pop();
+ *arg0 = cgen()->frame()->Pop();
+}
+
+
+void JumpTarget::ComputeEntryFrame() {
+ // Given: a collection of frames reaching by forward CFG edges and
+ // the directionality of the block. Compute: an entry frame for the
+ // block.
+
+ Counters::compute_entry_frame.Increment();
+#ifdef DEBUG
+ if (compiling_deferred_code_) {
+ ASSERT(reaching_frames_.length() > 1);
+ VirtualFrame* frame = reaching_frames_[0];
+ bool all_identical = true;
+ for (int i = 1; i < reaching_frames_.length(); i++) {
+ if (!frame->Equals(reaching_frames_[i])) {
+ all_identical = false;
+ break;
+ }
+ }
+ ASSERT(!all_identical || all_identical);
+ }
+#endif
+
+ // Choose an initial frame.
+ VirtualFrame* initial_frame = reaching_frames_[0];
+
+ // A list of pointers to frame elements in the entry frame. NULL
+ // indicates that the element has not yet been determined.
+ int length = initial_frame->element_count();
+ ZoneList<FrameElement*> elements(length);
+
+ // Initially populate the list of elements based on the initial
+ // frame.
+ for (int i = 0; i < length; i++) {
+ FrameElement element = initial_frame->elements_[i];
+ // We do not allow copies or constants in bidirectional frames.
+ if (direction_ == BIDIRECTIONAL) {
+ if (element.is_constant() || element.is_copy()) {
+ elements.Add(NULL);
+ continue;
+ }
+ }
+ elements.Add(&initial_frame->elements_[i]);
+ }
+
+ // Compute elements based on the other reaching frames.
+ if (reaching_frames_.length() > 1) {
+ for (int i = 0; i < length; i++) {
+ FrameElement* element = elements[i];
+ for (int j = 1; j < reaching_frames_.length(); j++) {
+ // Element computation is monotonic: new information will not
+ // change our decision about undetermined or invalid elements.
+ if (element == NULL || !element->is_valid()) break;
+
+ FrameElement* other = &reaching_frames_[j]->elements_[i];
+ element = element->Combine(other);
+ if (element != NULL && !element->is_copy()) {
+ ASSERT(other != NULL);
+ // We overwrite the number information of one of the incoming frames.
+ // This is safe because we only use the frame for emitting merge code.
+ // The number information of incoming frames is not used anymore.
+ element->set_type_info(TypeInfo::Combine(element->type_info(),
+ other->type_info()));
+ }
+ }
+ elements[i] = element;
+ }
+ }
+
+ // Build the new frame. A freshly allocated frame has memory elements
+ // for the parameters and some platform-dependent elements (e.g.,
+ // return address). Replace those first.
+ entry_frame_ = new VirtualFrame();
+ int index = 0;
+ for (; index < entry_frame_->element_count(); index++) {
+ FrameElement* target = elements[index];
+ // If the element is determined, set it now. Count registers. Mark
+ // elements as copied exactly when they have a copy. Undetermined
+ // elements are initially recorded as if in memory.
+ if (target != NULL) {
+ entry_frame_->elements_[index] = *target;
+ InitializeEntryElement(index, target);
+ }
+ }
+ // Then fill in the rest of the frame with new elements.
+ for (; index < length; index++) {
+ FrameElement* target = elements[index];
+ if (target == NULL) {
+ entry_frame_->elements_.Add(
+ FrameElement::MemoryElement(TypeInfo::Uninitialized()));
+ } else {
+ entry_frame_->elements_.Add(*target);
+ InitializeEntryElement(index, target);
+ }
+ }
+
+ // Allocate any still-undetermined frame elements to registers or
+ // memory, from the top down.
+ for (int i = length - 1; i >= 0; i--) {
+ if (elements[i] == NULL) {
+ // Loop over all the reaching frames to check whether the element
+ // is synced on all frames and to count the registers it occupies.
+ bool is_synced = true;
+ RegisterFile candidate_registers;
+ int best_count = kMinInt;
+ int best_reg_num = RegisterAllocator::kInvalidRegister;
+ TypeInfo info = TypeInfo::Uninitialized();
+
+ for (int j = 0; j < reaching_frames_.length(); j++) {
+ FrameElement element = reaching_frames_[j]->elements_[i];
+ if (direction_ == BIDIRECTIONAL) {
+ info = TypeInfo::Unknown();
+ } else if (!element.is_copy()) {
+ info = TypeInfo::Combine(info, element.type_info());
+ } else {
+ // New elements will not be copies, so get number information from
+ // backing element in the reaching frame.
+ info = TypeInfo::Combine(info,
+ reaching_frames_[j]->elements_[element.index()].type_info());
+ }
+ is_synced = is_synced && element.is_synced();
+ if (element.is_register() && !entry_frame_->is_used(element.reg())) {
+ // Count the register occurrence and remember it if better
+ // than the previous best.
+ int num = RegisterAllocator::ToNumber(element.reg());
+ candidate_registers.Use(num);
+ if (candidate_registers.count(num) > best_count) {
+ best_count = candidate_registers.count(num);
+ best_reg_num = num;
+ }
+ }
+ }
+
+ // We must have a number type information now (not for copied elements).
+ ASSERT(entry_frame_->elements_[i].is_copy()
+ || !info.IsUninitialized());
+
+ // If the value is synced on all frames, put it in memory. This
+ // costs nothing at the merge code but will incur a
+ // memory-to-register move when the value is needed later.
+ if (is_synced) {
+ // Already recorded as a memory element.
+ // Set combined number info.
+ entry_frame_->elements_[i].set_type_info(info);
+ continue;
+ }
+
+ // Try to put it in a register. If there was no best choice
+ // consider any free register.
+ if (best_reg_num == RegisterAllocator::kInvalidRegister) {
+ for (int j = 0; j < RegisterAllocator::kNumRegisters; j++) {
+ if (!entry_frame_->is_used(j)) {
+ best_reg_num = j;
+ break;
+ }
+ }
+ }
+
+ if (best_reg_num != RegisterAllocator::kInvalidRegister) {
+ // If there was a register choice, use it. Preserve the copied
+ // flag on the element.
+ bool is_copied = entry_frame_->elements_[i].is_copied();
+ Register reg = RegisterAllocator::ToRegister(best_reg_num);
+ entry_frame_->elements_[i] =
+ FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED,
+ TypeInfo::Uninitialized());
+ if (is_copied) entry_frame_->elements_[i].set_copied();
+ entry_frame_->set_register_location(reg, i);
+ }
+ // Set combined number info.
+ entry_frame_->elements_[i].set_type_info(info);
+ }
+ }
+
+ // If we have incoming backward edges assert we forget all number information.
+#ifdef DEBUG
+ if (direction_ == BIDIRECTIONAL) {
+ for (int i = 0; i < length; ++i) {
+ if (!entry_frame_->elements_[i].is_copy()) {
+ ASSERT(entry_frame_->elements_[i].type_info().IsUnknown());
+ }
+ }
+ }
+#endif
+
+ // The stack pointer is at the highest synced element or the base of
+ // the expression stack.
+ int stack_pointer = length - 1;
+ while (stack_pointer >= entry_frame_->expression_base_index() &&
+ !entry_frame_->elements_[stack_pointer].is_synced()) {
+ stack_pointer--;
+ }
+ entry_frame_->stack_pointer_ = stack_pointer;
+}
+
+
+DeferredCode::DeferredCode()
+ : masm_(CodeGeneratorScope::Current()->masm()),
+ statement_position_(masm_->current_statement_position()),
+ position_(masm_->current_position()) {
+ ASSERT(statement_position_ != RelocInfo::kNoPosition);
+ ASSERT(position_ != RelocInfo::kNoPosition);
+
+ CodeGeneratorScope::Current()->AddDeferred(this);
+#ifdef DEBUG
+ comment_ = "";
+#endif
+
+ // Copy the register locations from the code generator's frame.
+ // These are the registers that will be spilled on entry to the
+ // deferred code and restored on exit.
+ VirtualFrame* frame = CodeGeneratorScope::Current()->frame();
+ int sp_offset = frame->fp_relative(frame->stack_pointer_);
+ for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
+ int loc = frame->register_location(i);
+ if (loc == VirtualFrame::kIllegalIndex) {
+ registers_[i] = kIgnore;
+ } else if (frame->elements_[loc].is_synced()) {
+ // Needs to be restored on exit but not saved on entry.
+ registers_[i] = frame->fp_relative(loc) | kSyncedFlag;
+ } else {
+ int offset = frame->fp_relative(loc);
+ registers_[i] = (offset < sp_offset) ? kPush : offset;
+ }
+ }
+}
+
+} } // namespace v8::internal
#include "virtual-frame-inl.h"
+#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
+#include "jump-target-heavy-inl.h"
+#else
+#include "jump-target-light-inl.h"
+#endif
+
namespace v8 {
namespace internal {
return CodeGeneratorScope::Current();
}
-void JumpTarget::InitializeEntryElement(int index, FrameElement* target) {
- FrameElement* element = &entry_frame_->elements_[index];
- element->clear_copied();
- if (target->is_register()) {
- entry_frame_->set_register_location(target->reg(), index);
- } else if (target->is_copy()) {
- entry_frame_->elements_[target->index()].set_copied();
- }
- if (direction_ == BIDIRECTIONAL && !target->is_copy()) {
- element->set_type_info(TypeInfo::Unknown());
- }
-}
-
} } // namespace v8::internal
#endif // V8_JUMP_TARGET_INL_H_
--- /dev/null
+// 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_JUMP_TARGET_LIGHT_INL_H_
+#define V8_JUMP_TARGET_LIGHT_INL_H_
+
+#include "virtual-frame-inl.h"
+
+namespace v8 {
+namespace internal {
+
+void JumpTarget::InitializeEntryElement(int index, FrameElement* target) {
+ UNIMPLEMENTED();
+}
+
+} } // namespace v8::internal
+
+#endif // V8_JUMP_TARGET_LIGHT_INL_H_
--- /dev/null
+// 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 "codegen-inl.h"
+#include "jump-target-inl.h"
+
+namespace v8 {
+namespace internal {
+
+
+void JumpTarget::Jump(Result* arg) {
+ UNIMPLEMENTED();
+}
+
+
+void JumpTarget::Branch(Condition cc, Result* arg, Hint hint) {
+ UNIMPLEMENTED();
+}
+
+
+void JumpTarget::Branch(Condition cc, Result* arg0, Result* arg1, Hint hint) {
+ UNIMPLEMENTED();
+}
+
+
+void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) {
+ UNIMPLEMENTED();
+}
+
+
+void JumpTarget::Bind(Result* arg) {
+ UNIMPLEMENTED();
+}
+
+
+void JumpTarget::Bind(Result* arg0, Result* arg1) {
+ UNIMPLEMENTED();
+}
+
+
+void JumpTarget::ComputeEntryFrame() {
+ UNIMPLEMENTED();
+}
+
+
+DeferredCode::DeferredCode()
+ : masm_(CodeGeneratorScope::Current()->masm()),
+ statement_position_(masm_->current_statement_position()),
+ position_(masm_->current_position()) {
+ ASSERT(statement_position_ != RelocInfo::kNoPosition);
+ ASSERT(position_ != RelocInfo::kNoPosition);
+
+ CodeGeneratorScope::Current()->AddDeferred(this);
+#ifdef DEBUG
+ comment_ = "";
+#endif
+
+ // Copy the register locations from the code generator's frame.
+ // These are the registers that will be spilled on entry to the
+ // deferred code and restored on exit.
+ VirtualFrame* frame = CodeGeneratorScope::Current()->frame();
+ for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
+ int loc = frame->register_location(i);
+ if (loc == VirtualFrame::kIllegalIndex) {
+ registers_[i] = kIgnore;
+ } else {
+ // Needs to be restored on exit but not saved on entry.
+ registers_[i] = frame->fp_relative(loc) | kSyncedFlag;
+ }
+ }
+}
+
+} } // namespace v8::internal
}
-void JumpTarget::ComputeEntryFrame() {
- // Given: a collection of frames reaching by forward CFG edges and
- // the directionality of the block. Compute: an entry frame for the
- // block.
-
- Counters::compute_entry_frame.Increment();
-#ifdef DEBUG
- if (compiling_deferred_code_) {
- ASSERT(reaching_frames_.length() > 1);
- VirtualFrame* frame = reaching_frames_[0];
- bool all_identical = true;
- for (int i = 1; i < reaching_frames_.length(); i++) {
- if (!frame->Equals(reaching_frames_[i])) {
- all_identical = false;
- break;
- }
- }
- ASSERT(!all_identical || all_identical);
- }
-#endif
-
- // Choose an initial frame.
- VirtualFrame* initial_frame = reaching_frames_[0];
-
- // A list of pointers to frame elements in the entry frame. NULL
- // indicates that the element has not yet been determined.
- int length = initial_frame->element_count();
- ZoneList<FrameElement*> elements(length);
-
- // Initially populate the list of elements based on the initial
- // frame.
- for (int i = 0; i < length; i++) {
- FrameElement element = initial_frame->elements_[i];
- // We do not allow copies or constants in bidirectional frames.
- if (direction_ == BIDIRECTIONAL) {
- if (element.is_constant() || element.is_copy()) {
- elements.Add(NULL);
- continue;
- }
- }
- elements.Add(&initial_frame->elements_[i]);
- }
-
- // Compute elements based on the other reaching frames.
- if (reaching_frames_.length() > 1) {
- for (int i = 0; i < length; i++) {
- FrameElement* element = elements[i];
- for (int j = 1; j < reaching_frames_.length(); j++) {
- // Element computation is monotonic: new information will not
- // change our decision about undetermined or invalid elements.
- if (element == NULL || !element->is_valid()) break;
-
- FrameElement* other = &reaching_frames_[j]->elements_[i];
- element = element->Combine(other);
- if (element != NULL && !element->is_copy()) {
- ASSERT(other != NULL);
- // We overwrite the number information of one of the incoming frames.
- // This is safe because we only use the frame for emitting merge code.
- // The number information of incoming frames is not used anymore.
- element->set_type_info(TypeInfo::Combine(element->type_info(),
- other->type_info()));
- }
- }
- elements[i] = element;
- }
- }
-
- // Build the new frame. A freshly allocated frame has memory elements
- // for the parameters and some platform-dependent elements (e.g.,
- // return address). Replace those first.
- entry_frame_ = new VirtualFrame();
- int index = 0;
- for (; index < entry_frame_->element_count(); index++) {
- FrameElement* target = elements[index];
- // If the element is determined, set it now. Count registers. Mark
- // elements as copied exactly when they have a copy. Undetermined
- // elements are initially recorded as if in memory.
- if (target != NULL) {
- entry_frame_->elements_[index] = *target;
- InitializeEntryElement(index, target);
- }
- }
- // Then fill in the rest of the frame with new elements.
- for (; index < length; index++) {
- FrameElement* target = elements[index];
- if (target == NULL) {
- entry_frame_->elements_.Add(
- FrameElement::MemoryElement(TypeInfo::Uninitialized()));
- } else {
- entry_frame_->elements_.Add(*target);
- InitializeEntryElement(index, target);
- }
- }
-
- // Allocate any still-undetermined frame elements to registers or
- // memory, from the top down.
- for (int i = length - 1; i >= 0; i--) {
- if (elements[i] == NULL) {
- // Loop over all the reaching frames to check whether the element
- // is synced on all frames and to count the registers it occupies.
- bool is_synced = true;
- RegisterFile candidate_registers;
- int best_count = kMinInt;
- int best_reg_num = RegisterAllocator::kInvalidRegister;
- TypeInfo info = TypeInfo::Uninitialized();
-
- for (int j = 0; j < reaching_frames_.length(); j++) {
- FrameElement element = reaching_frames_[j]->elements_[i];
- if (direction_ == BIDIRECTIONAL) {
- info = TypeInfo::Unknown();
- } else if (!element.is_copy()) {
- info = TypeInfo::Combine(info, element.type_info());
- } else {
- // New elements will not be copies, so get number information from
- // backing element in the reaching frame.
- info = TypeInfo::Combine(info,
- reaching_frames_[j]->elements_[element.index()].type_info());
- }
- is_synced = is_synced && element.is_synced();
- if (element.is_register() && !entry_frame_->is_used(element.reg())) {
- // Count the register occurrence and remember it if better
- // than the previous best.
- int num = RegisterAllocator::ToNumber(element.reg());
- candidate_registers.Use(num);
- if (candidate_registers.count(num) > best_count) {
- best_count = candidate_registers.count(num);
- best_reg_num = num;
- }
- }
- }
-
- // We must have a number type information now (not for copied elements).
- ASSERT(entry_frame_->elements_[i].is_copy()
- || !info.IsUninitialized());
-
- // If the value is synced on all frames, put it in memory. This
- // costs nothing at the merge code but will incur a
- // memory-to-register move when the value is needed later.
- if (is_synced) {
- // Already recorded as a memory element.
- // Set combined number info.
- entry_frame_->elements_[i].set_type_info(info);
- continue;
- }
-
- // Try to put it in a register. If there was no best choice
- // consider any free register.
- if (best_reg_num == RegisterAllocator::kInvalidRegister) {
- for (int j = 0; j < RegisterAllocator::kNumRegisters; j++) {
- if (!entry_frame_->is_used(j)) {
- best_reg_num = j;
- break;
- }
- }
- }
-
- if (best_reg_num != RegisterAllocator::kInvalidRegister) {
- // If there was a register choice, use it. Preserve the copied
- // flag on the element.
- bool is_copied = entry_frame_->elements_[i].is_copied();
- Register reg = RegisterAllocator::ToRegister(best_reg_num);
- entry_frame_->elements_[i] =
- FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED,
- TypeInfo::Uninitialized());
- if (is_copied) entry_frame_->elements_[i].set_copied();
- entry_frame_->set_register_location(reg, i);
- }
- // Set combined number info.
- entry_frame_->elements_[i].set_type_info(info);
- }
- }
-
- // If we have incoming backward edges assert we forget all number information.
-#ifdef DEBUG
- if (direction_ == BIDIRECTIONAL) {
- for (int i = 0; i < length; ++i) {
- if (!entry_frame_->elements_[i].is_copy()) {
- ASSERT(entry_frame_->elements_[i].type_info().IsUnknown());
- }
- }
- }
-#endif
-
- // The stack pointer is at the highest synced element or the base of
- // the expression stack.
- int stack_pointer = length - 1;
- while (stack_pointer >= entry_frame_->expression_base_index() &&
- !entry_frame_->elements_[stack_pointer].is_synced()) {
- stack_pointer--;
- }
- entry_frame_->stack_pointer_ = stack_pointer;
-}
-
-
void JumpTarget::Jump() {
DoJump();
}
-void JumpTarget::Jump(Result* arg) {
- ASSERT(cgen()->has_valid_frame());
-
- cgen()->frame()->Push(arg);
- DoJump();
-}
-
-
void JumpTarget::Branch(Condition cc, Hint hint) {
DoBranch(cc, hint);
}
-#ifdef DEBUG
-#define DECLARE_ARGCHECK_VARS(name) \
- Result::Type name##_type = name->type(); \
- Register name##_reg = name->is_register() ? name->reg() : no_reg
-
-#define ASSERT_ARGCHECK(name) \
- ASSERT(name->type() == name##_type); \
- ASSERT(!name->is_register() || name->reg().is(name##_reg))
-
-#else
-#define DECLARE_ARGCHECK_VARS(name) do {} while (false)
-
-#define ASSERT_ARGCHECK(name) do {} while (false)
-#endif
-
-void JumpTarget::Branch(Condition cc, Result* arg, Hint hint) {
- ASSERT(cgen()->has_valid_frame());
-
- // We want to check that non-frame registers at the call site stay in
- // the same registers on the fall-through branch.
- DECLARE_ARGCHECK_VARS(arg);
-
- cgen()->frame()->Push(arg);
- DoBranch(cc, hint);
- *arg = cgen()->frame()->Pop();
-
- ASSERT_ARGCHECK(arg);
-}
-
-
-void JumpTarget::Branch(Condition cc, Result* arg0, Result* arg1, Hint hint) {
- ASSERT(cgen()->has_valid_frame());
-
- // We want to check that non-frame registers at the call site stay in
- // the same registers on the fall-through branch.
- DECLARE_ARGCHECK_VARS(arg0);
- DECLARE_ARGCHECK_VARS(arg1);
-
- cgen()->frame()->Push(arg0);
- cgen()->frame()->Push(arg1);
- DoBranch(cc, hint);
- *arg1 = cgen()->frame()->Pop();
- *arg0 = cgen()->frame()->Pop();
-
- ASSERT_ARGCHECK(arg0);
- ASSERT_ARGCHECK(arg1);
-}
-
-
-void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) {
- ASSERT(cgen()->has_valid_frame());
-
- int count = cgen()->frame()->height() - expected_height_;
- if (count > 0) {
- // We negate and branch here rather than using DoBranch's negate
- // and branch. This gives us a hook to remove statement state
- // from the frame.
- JumpTarget fall_through;
- // Branch to fall through will not negate, because it is a
- // forward-only target.
- fall_through.Branch(NegateCondition(cc), NegateHint(hint));
- Jump(arg); // May emit merge code here.
- fall_through.Bind();
- } else {
- DECLARE_ARGCHECK_VARS(arg);
- cgen()->frame()->Push(arg);
- DoBranch(cc, hint);
- *arg = cgen()->frame()->Pop();
- ASSERT_ARGCHECK(arg);
- }
-}
-
-#undef DECLARE_ARGCHECK_VARS
-#undef ASSERT_ARGCHECK
-
-
void JumpTarget::Bind() {
DoBind();
}
-void JumpTarget::Bind(Result* arg) {
- if (cgen()->has_valid_frame()) {
- cgen()->frame()->Push(arg);
- }
- DoBind();
- *arg = cgen()->frame()->Pop();
-}
-
-
-void JumpTarget::Bind(Result* arg0, Result* arg1) {
- if (cgen()->has_valid_frame()) {
- cgen()->frame()->Push(arg0);
- cgen()->frame()->Push(arg1);
- }
- DoBind();
- *arg1 = cgen()->frame()->Pop();
- *arg0 = cgen()->frame()->Pop();
-}
-
-
void JumpTarget::AddReachingFrame(VirtualFrame* frame) {
ASSERT(reaching_frames_.length() == merge_labels_.length());
ASSERT(entry_frame_ == NULL);
--- /dev/null
+// 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_HEAVY_INL_H_
+#define V8_VIRTUAL_FRAME_HEAVY_INL_H_
+
+#include "type-info.h"
+#include "register-allocator.h"
+#include "scopes.h"
+
+namespace v8 {
+namespace internal {
+
+// On entry to a function, the virtual frame already contains the receiver,
+// the parameters, and a return address. All frame elements are in memory.
+VirtualFrame::VirtualFrame()
+ : elements_(parameter_count() + local_count() + kPreallocatedElements),
+ stack_pointer_(parameter_count() + 1) { // 0-based index of TOS.
+ for (int i = 0; i <= stack_pointer_; i++) {
+ elements_.Add(FrameElement::MemoryElement(TypeInfo::Unknown()));
+ }
+ for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
+ register_locations_[i] = kIllegalIndex;
+ }
+}
+
+
+// When cloned, a frame is a deep copy of the original.
+VirtualFrame::VirtualFrame(VirtualFrame* original)
+ : elements_(original->element_count()),
+ stack_pointer_(original->stack_pointer_) {
+ elements_.AddAll(original->elements_);
+ // Copy register locations from original.
+ memcpy(®ister_locations_,
+ original->register_locations_,
+ sizeof(register_locations_));
+}
+
+
+void VirtualFrame::PushFrameSlotAt(int index) {
+ elements_.Add(CopyElementAt(index));
+}
+
+
+void VirtualFrame::Push(Register reg, TypeInfo info) {
+ if (is_used(reg)) {
+ int index = register_location(reg);
+ FrameElement element = CopyElementAt(index, info);
+ elements_.Add(element);
+ } else {
+ Use(reg, element_count());
+ FrameElement element =
+ FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED, info);
+ elements_.Add(element);
+ }
+}
+
+
+void VirtualFrame::Push(Handle<Object> value) {
+ FrameElement element =
+ FrameElement::ConstantElement(value, FrameElement::NOT_SYNCED);
+ elements_.Add(element);
+}
+
+
+bool VirtualFrame::Equals(VirtualFrame* other) {
+#ifdef DEBUG
+ for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
+ if (register_location(i) != other->register_location(i)) {
+ return false;
+ }
+ }
+ if (element_count() != other->element_count()) return false;
+#endif
+ if (stack_pointer_ != other->stack_pointer_) return false;
+ for (int i = 0; i < element_count(); i++) {
+ if (!elements_[i].Equals(other->elements_[i])) return false;
+ }
+
+ return true;
+}
+
+
+void VirtualFrame::SetTypeForLocalAt(int index, TypeInfo info) {
+ elements_[local0_index() + index].set_type_info(info);
+}
+
+
+// Make the type of all elements be MEMORY.
+void VirtualFrame::SpillAll() {
+ for (int i = 0; i < element_count(); i++) {
+ SpillElementAt(i);
+ }
+}
+
+
+void VirtualFrame::PrepareForReturn() {
+ // Spill all locals. This is necessary to make sure all locals have
+ // the right value when breaking at the return site in the debugger.
+ for (int i = 0; i < expression_base_index(); i++) {
+ SpillElementAt(i);
+ }
+}
+
+
+void VirtualFrame::SetTypeForParamAt(int index, TypeInfo info) {
+ elements_[param0_index() + index].set_type_info(info);
+}
+
+} } // namespace v8::internal
+
+#endif // V8_VIRTUAL_FRAME_HEAVY_INL_H_
--- /dev/null
+// 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 "codegen-inl.h"
+#include "register-allocator-inl.h"
+#include "virtual-frame-inl.h"
+
+namespace v8 {
+namespace internal {
+
+void VirtualFrame::SetElementAt(int index, Result* value) {
+ int frame_index = element_count() - index - 1;
+ ASSERT(frame_index >= 0);
+ ASSERT(frame_index < element_count());
+ ASSERT(value->is_valid());
+ FrameElement original = elements_[frame_index];
+
+ // Early exit if the element is the same as the one being set.
+ bool same_register = original.is_register()
+ && value->is_register()
+ && original.reg().is(value->reg());
+ bool same_constant = original.is_constant()
+ && value->is_constant()
+ && original.handle().is_identical_to(value->handle());
+ if (same_register || same_constant) {
+ value->Unuse();
+ return;
+ }
+
+ InvalidateFrameSlotAt(frame_index);
+
+ if (value->is_register()) {
+ if (is_used(value->reg())) {
+ // The register already appears on the frame. Either the existing
+ // register element, or the new element at frame_index, must be made
+ // a copy.
+ int i = register_location(value->reg());
+
+ if (i < frame_index) {
+ // The register FrameElement is lower in the frame than the new copy.
+ elements_[frame_index] = CopyElementAt(i);
+ } else {
+ // There was an early bailout for the case of setting a
+ // register element to itself.
+ ASSERT(i != frame_index);
+ elements_[frame_index] = elements_[i];
+ elements_[i] = CopyElementAt(frame_index);
+ if (elements_[frame_index].is_synced()) {
+ elements_[i].set_sync();
+ }
+ elements_[frame_index].clear_sync();
+ set_register_location(value->reg(), frame_index);
+ for (int j = i + 1; j < element_count(); j++) {
+ if (elements_[j].is_copy() && elements_[j].index() == i) {
+ elements_[j].set_index(frame_index);
+ }
+ }
+ }
+ } else {
+ // The register value->reg() was not already used on the frame.
+ Use(value->reg(), frame_index);
+ elements_[frame_index] =
+ FrameElement::RegisterElement(value->reg(),
+ FrameElement::NOT_SYNCED,
+ value->type_info());
+ }
+ } else {
+ ASSERT(value->is_constant());
+ elements_[frame_index] =
+ FrameElement::ConstantElement(value->handle(),
+ FrameElement::NOT_SYNCED);
+ }
+ value->Unuse();
+}
+
+
+// Create a duplicate of an existing valid frame element.
+// We can pass an optional number type information that will override the
+// existing information about the backing element. The new information must
+// not conflict with the existing type information and must be equally or
+// more precise. The default parameter value kUninitialized means that there
+// is no additional information.
+FrameElement VirtualFrame::CopyElementAt(int index, TypeInfo info) {
+ ASSERT(index >= 0);
+ ASSERT(index < element_count());
+
+ FrameElement target = elements_[index];
+ FrameElement result;
+
+ switch (target.type()) {
+ case FrameElement::CONSTANT:
+ // We do not copy constants and instead return a fresh unsynced
+ // constant.
+ result = FrameElement::ConstantElement(target.handle(),
+ FrameElement::NOT_SYNCED);
+ break;
+
+ case FrameElement::COPY:
+ // We do not allow copies of copies, so we follow one link to
+ // the actual backing store of a copy before making a copy.
+ index = target.index();
+ ASSERT(elements_[index].is_memory() || elements_[index].is_register());
+ // Fall through.
+
+ case FrameElement::MEMORY: // Fall through.
+ case FrameElement::REGISTER: {
+ // All copies are backed by memory or register locations.
+ result.set_type(FrameElement::COPY);
+ result.clear_copied();
+ result.clear_sync();
+ result.set_index(index);
+ elements_[index].set_copied();
+ // Update backing element's number information.
+ TypeInfo existing = elements_[index].type_info();
+ ASSERT(!existing.IsUninitialized());
+ // Assert that the new type information (a) does not conflict with the
+ // existing one and (b) is equally or more precise.
+ ASSERT((info.ToInt() & existing.ToInt()) == existing.ToInt());
+ ASSERT((info.ToInt() | existing.ToInt()) == info.ToInt());
+
+ elements_[index].set_type_info(!info.IsUninitialized()
+ ? info
+ : existing);
+ break;
+ }
+ case FrameElement::INVALID:
+ // We should not try to copy invalid elements.
+ UNREACHABLE();
+ break;
+ }
+ return result;
+}
+
+
+// Modify the state of the virtual frame to match the actual frame by adding
+// extra in-memory elements to the top of the virtual frame. The extra
+// elements will be externally materialized on the actual frame (eg, by
+// pushing an exception handler). No code is emitted.
+void VirtualFrame::Adjust(int count) {
+ ASSERT(count >= 0);
+ ASSERT(stack_pointer_ == element_count() - 1);
+
+ for (int i = 0; i < count; i++) {
+ elements_.Add(FrameElement::MemoryElement(TypeInfo::Unknown()));
+ }
+ stack_pointer_ += count;
+}
+
+
+void VirtualFrame::ForgetElements(int count) {
+ ASSERT(count >= 0);
+ ASSERT(element_count() >= count);
+
+ for (int i = 0; i < count; i++) {
+ FrameElement last = elements_.RemoveLast();
+ if (last.is_register()) {
+ // A hack to properly count register references for the code
+ // generator's current frame and also for other frames. The
+ // same code appears in PrepareMergeTo.
+ if (cgen()->frame() == this) {
+ Unuse(last.reg());
+ } else {
+ set_register_location(last.reg(), kIllegalIndex);
+ }
+ }
+ }
+}
+
+
+// Make the type of the element at a given index be MEMORY.
+void VirtualFrame::SpillElementAt(int index) {
+ if (!elements_[index].is_valid()) return;
+
+ SyncElementAt(index);
+ // Number type information is preserved.
+ // Copies get their number information from their backing element.
+ TypeInfo info;
+ if (!elements_[index].is_copy()) {
+ info = elements_[index].type_info();
+ } else {
+ info = elements_[elements_[index].index()].type_info();
+ }
+ // The element is now in memory. Its copied flag is preserved.
+ FrameElement new_element = FrameElement::MemoryElement(info);
+ if (elements_[index].is_copied()) {
+ new_element.set_copied();
+ }
+ if (elements_[index].is_untagged_int32()) {
+ new_element.set_untagged_int32(true);
+ }
+ if (elements_[index].is_register()) {
+ Unuse(elements_[index].reg());
+ }
+ elements_[index] = new_element;
+}
+
+
+// Clear the dirty bit for the element at a given index.
+void VirtualFrame::SyncElementAt(int index) {
+ if (index <= stack_pointer_) {
+ if (!elements_[index].is_synced()) SyncElementBelowStackPointer(index);
+ } else if (index == stack_pointer_ + 1) {
+ SyncElementByPushing(index);
+ } else {
+ SyncRange(stack_pointer_ + 1, index);
+ }
+}
+
+
+void VirtualFrame::PrepareMergeTo(VirtualFrame* expected) {
+ // Perform state changes on this frame that will make merge to the
+ // expected frame simpler or else increase the likelihood that his
+ // frame will match another.
+ for (int i = 0; i < element_count(); i++) {
+ FrameElement source = elements_[i];
+ FrameElement target = expected->elements_[i];
+
+ if (!target.is_valid() ||
+ (target.is_memory() && !source.is_memory() && source.is_synced())) {
+ // No code needs to be generated to invalidate valid elements.
+ // No code needs to be generated to move values to memory if
+ // they are already synced. We perform those moves here, before
+ // merging.
+ if (source.is_register()) {
+ // If the frame is the code generator's current frame, we have
+ // to decrement both the frame-internal and global register
+ // counts.
+ if (cgen()->frame() == this) {
+ Unuse(source.reg());
+ } else {
+ set_register_location(source.reg(), kIllegalIndex);
+ }
+ }
+ elements_[i] = target;
+ } else if (target.is_register() && !target.is_synced() &&
+ !source.is_memory()) {
+ // If an element's target is a register that doesn't need to be
+ // synced, and the element is not in memory, then the sync state
+ // of the element is irrelevant. We clear the sync bit.
+ ASSERT(source.is_valid());
+ elements_[i].clear_sync();
+ }
+ }
+}
+
+
+void VirtualFrame::PrepareForCall(int spilled_args, int dropped_args) {
+ ASSERT(height() >= dropped_args);
+ ASSERT(height() >= spilled_args);
+ ASSERT(dropped_args <= spilled_args);
+
+ SyncRange(0, element_count() - 1);
+ // Spill registers.
+ for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
+ if (is_used(i)) {
+ SpillElementAt(register_location(i));
+ }
+ }
+
+ // Spill the arguments.
+ for (int i = element_count() - spilled_args; i < element_count(); i++) {
+ if (!elements_[i].is_memory()) {
+ SpillElementAt(i);
+ }
+ }
+
+ // Forget the frame elements that will be popped by the call.
+ Forget(dropped_args);
+}
+
+
+} } // namespace v8::internal
#include "virtual-frame.h"
-namespace v8 {
-namespace internal {
-
-
-// On entry to a function, the virtual frame already contains the receiver,
-// the parameters, and a return address. All frame elements are in memory.
-VirtualFrame::VirtualFrame()
- : elements_(parameter_count() + local_count() + kPreallocatedElements),
- stack_pointer_(parameter_count() + 1) { // 0-based index of TOS.
- for (int i = 0; i <= stack_pointer_; i++) {
- elements_.Add(FrameElement::MemoryElement(TypeInfo::Unknown()));
- }
- for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
- register_locations_[i] = kIllegalIndex;
- }
-}
-
-
-// When cloned, a frame is a deep copy of the original.
-VirtualFrame::VirtualFrame(VirtualFrame* original)
- : elements_(original->element_count()),
- stack_pointer_(original->stack_pointer_) {
- elements_.AddAll(original->elements_);
- // Copy register locations from original.
- memcpy(®ister_locations_,
- original->register_locations_,
- sizeof(register_locations_));
-}
-
-
-void VirtualFrame::PushFrameSlotAt(int index) {
- elements_.Add(CopyElementAt(index));
-}
-
-
-void VirtualFrame::Push(Register reg, TypeInfo info) {
- if (is_used(reg)) {
- int index = register_location(reg);
- FrameElement element = CopyElementAt(index, info);
- elements_.Add(element);
- } else {
- Use(reg, element_count());
- FrameElement element =
- FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED, info);
- elements_.Add(element);
- }
-}
-
+#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
+#include "virtual-frame-heavy-inl.h"
+#else
+#include "virtual-frame-light-inl.h"
+#endif
-void VirtualFrame::Push(Handle<Object> value) {
- FrameElement element =
- FrameElement::ConstantElement(value, FrameElement::NOT_SYNCED);
- elements_.Add(element);
-}
+namespace v8 {
+namespace internal {
void VirtualFrame::Push(Smi* value) {
Push(Handle<Object> (value));
SetElementAt(0, &tos);
}
-
-bool VirtualFrame::Equals(VirtualFrame* other) {
-#ifdef DEBUG
- for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
- if (register_location(i) != other->register_location(i)) {
- return false;
- }
- }
- if (element_count() != other->element_count()) return false;
-#endif
- if (stack_pointer_ != other->stack_pointer_) return false;
- for (int i = 0; i < element_count(); i++) {
- if (!elements_[i].Equals(other->elements_[i])) return false;
- }
-
- return true;
-}
-
-
-void VirtualFrame::SetTypeForLocalAt(int index, TypeInfo info) {
- elements_[local0_index() + index].set_type_info(info);
-}
-
-
-void VirtualFrame::SetTypeForParamAt(int index, TypeInfo info) {
- elements_[param0_index() + index].set_type_info(info);
-}
-
-
} } // namespace v8::internal
#endif // V8_VIRTUAL_FRAME_INL_H_
--- /dev/null
+// 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_LIGHT_INL_H_
+#define V8_VIRTUAL_FRAME_LIGHT_INL_H_
+
+#include "type-info.h"
+#include "register-allocator.h"
+#include "scopes.h"
+
+namespace v8 {
+namespace internal {
+
+// On entry to a function, the virtual frame already contains the receiver,
+// the parameters, and a return address. All frame elements are in memory.
+VirtualFrame::VirtualFrame()
+ : element_count_(parameter_count() + 2),
+ stack_pointer_(parameter_count() + 1) {
+ for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
+ register_locations_[i] = kIllegalIndex;
+ }
+}
+
+
+// When cloned, a frame is a deep copy of the original.
+VirtualFrame::VirtualFrame(VirtualFrame* original)
+ : element_count_(original->element_count()),
+ stack_pointer_(original->stack_pointer_) {
+ memcpy(®ister_locations_,
+ original->register_locations_,
+ sizeof(register_locations_));
+}
+
+
+void VirtualFrame::Push(Handle<Object> value) {
+ UNIMPLEMENTED();
+}
+
+
+bool VirtualFrame::Equals(VirtualFrame* other) {
+#ifdef DEBUG
+ for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
+ if (register_location(i) != other->register_location(i)) {
+ return false;
+ }
+ }
+ if (element_count() != other->element_count()) return false;
+#endif
+ if (stack_pointer_ != other->stack_pointer_) return false;
+
+ return true;
+}
+
+
+void VirtualFrame::SetTypeForLocalAt(int index, TypeInfo info) {
+ UNIMPLEMENTED();
+}
+
+
+// Everything is always spilled anyway.
+void VirtualFrame::SpillAll() {
+}
+
+
+void VirtualFrame::PrepareForReturn() {
+}
+
+
+} } // namespace v8::internal
+
+#endif // V8_VIRTUAL_FRAME_LIGHT_INL_H_
--- /dev/null
+// 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 "codegen-inl.h"
+#include "register-allocator-inl.h"
+#include "virtual-frame-inl.h"
+
+namespace v8 {
+namespace internal {
+
+void VirtualFrame::Adjust(int count) {
+ ASSERT(count >= 0);
+ ASSERT(stack_pointer_ == element_count() - 1);
+
+ element_count_ += count;
+ stack_pointer_ += count;
+}
+
+
+// Make the type of the element at a given index be MEMORY.
+void VirtualFrame::SpillElementAt(int index) {
+ UNIMPLEMENTED();
+}
+
+
+} } // namespace v8::internal
// -------------------------------------------------------------------------
// VirtualFrame implementation.
-// Create a duplicate of an existing valid frame element.
-// We can pass an optional number type information that will override the
-// existing information about the backing element. The new information must
-// not conflict with the existing type information and must be equally or
-// more precise. The default parameter value kUninitialized means that there
-// is no additional information.
-FrameElement VirtualFrame::CopyElementAt(int index, TypeInfo info) {
- ASSERT(index >= 0);
- ASSERT(index < element_count());
-
- FrameElement target = elements_[index];
- FrameElement result;
-
- switch (target.type()) {
- case FrameElement::CONSTANT:
- // We do not copy constants and instead return a fresh unsynced
- // constant.
- result = FrameElement::ConstantElement(target.handle(),
- FrameElement::NOT_SYNCED);
- break;
-
- case FrameElement::COPY:
- // We do not allow copies of copies, so we follow one link to
- // the actual backing store of a copy before making a copy.
- index = target.index();
- ASSERT(elements_[index].is_memory() || elements_[index].is_register());
- // Fall through.
-
- case FrameElement::MEMORY: // Fall through.
- case FrameElement::REGISTER: {
- // All copies are backed by memory or register locations.
- result.set_type(FrameElement::COPY);
- result.clear_copied();
- result.clear_sync();
- result.set_index(index);
- elements_[index].set_copied();
- // Update backing element's number information.
- TypeInfo existing = elements_[index].type_info();
- ASSERT(!existing.IsUninitialized());
- // Assert that the new type information (a) does not conflict with the
- // existing one and (b) is equally or more precise.
- ASSERT((info.ToInt() & existing.ToInt()) == existing.ToInt());
- ASSERT((info.ToInt() | existing.ToInt()) == info.ToInt());
-
- elements_[index].set_type_info(!info.IsUninitialized()
- ? info
- : existing);
- break;
- }
- case FrameElement::INVALID:
- // We should not try to copy invalid elements.
- UNREACHABLE();
- break;
- }
- return result;
-}
-
-
-// Modify the state of the virtual frame to match the actual frame by adding
-// extra in-memory elements to the top of the virtual frame. The extra
-// elements will be externally materialized on the actual frame (eg, by
-// pushing an exception handler). No code is emitted.
-void VirtualFrame::Adjust(int count) {
- ASSERT(count >= 0);
- ASSERT(stack_pointer_ == element_count() - 1);
-
- for (int i = 0; i < count; i++) {
- elements_.Add(FrameElement::MemoryElement(TypeInfo::Unknown()));
- }
- stack_pointer_ += count;
-}
-
-
-void VirtualFrame::ForgetElements(int count) {
- ASSERT(count >= 0);
- ASSERT(element_count() >= count);
-
- for (int i = 0; i < count; i++) {
- FrameElement last = elements_.RemoveLast();
- if (last.is_register()) {
- // A hack to properly count register references for the code
- // generator's current frame and also for other frames. The
- // same code appears in PrepareMergeTo.
- if (cgen()->frame() == this) {
- Unuse(last.reg());
- } else {
- set_register_location(last.reg(), kIllegalIndex);
- }
- }
- }
-}
-
-
// If there are any registers referenced only by the frame, spill one.
Register VirtualFrame::SpillAnyRegister() {
// Find the leftmost (ordered by register number) register whose only
}
-// Make the type of the element at a given index be MEMORY.
-void VirtualFrame::SpillElementAt(int index) {
- if (!elements_[index].is_valid()) return;
-
- SyncElementAt(index);
- // Number type information is preserved.
- // Copies get their number information from their backing element.
- TypeInfo info;
- if (!elements_[index].is_copy()) {
- info = elements_[index].type_info();
- } else {
- info = elements_[elements_[index].index()].type_info();
- }
- // The element is now in memory. Its copied flag is preserved.
- FrameElement new_element = FrameElement::MemoryElement(info);
- if (elements_[index].is_copied()) {
- new_element.set_copied();
- }
- if (elements_[index].is_untagged_int32()) {
- new_element.set_untagged_int32(true);
- }
- if (elements_[index].is_register()) {
- Unuse(elements_[index].reg());
- }
- elements_[index] = new_element;
-}
-
-
-// Clear the dirty bit for the element at a given index.
-void VirtualFrame::SyncElementAt(int index) {
- if (index <= stack_pointer_) {
- if (!elements_[index].is_synced()) SyncElementBelowStackPointer(index);
- } else if (index == stack_pointer_ + 1) {
- SyncElementByPushing(index);
- } else {
- SyncRange(stack_pointer_ + 1, index);
- }
-}
-
-
-// Make the type of all elements be MEMORY.
-void VirtualFrame::SpillAll() {
- for (int i = 0; i < element_count(); i++) {
- SpillElementAt(i);
- }
-}
-
-
-void VirtualFrame::PrepareMergeTo(VirtualFrame* expected) {
- // Perform state changes on this frame that will make merge to the
- // expected frame simpler or else increase the likelihood that his
- // frame will match another.
- for (int i = 0; i < element_count(); i++) {
- FrameElement source = elements_[i];
- FrameElement target = expected->elements_[i];
-
- if (!target.is_valid() ||
- (target.is_memory() && !source.is_memory() && source.is_synced())) {
- // No code needs to be generated to invalidate valid elements.
- // No code needs to be generated to move values to memory if
- // they are already synced. We perform those moves here, before
- // merging.
- if (source.is_register()) {
- // If the frame is the code generator's current frame, we have
- // to decrement both the frame-internal and global register
- // counts.
- if (cgen()->frame() == this) {
- Unuse(source.reg());
- } else {
- set_register_location(source.reg(), kIllegalIndex);
- }
- }
- elements_[i] = target;
- } else if (target.is_register() && !target.is_synced() &&
- !source.is_memory()) {
- // If an element's target is a register that doesn't need to be
- // synced, and the element is not in memory, then the sync state
- // of the element is irrelevant. We clear the sync bit.
- ASSERT(source.is_valid());
- elements_[i].clear_sync();
- }
- }
-}
-
-
-void VirtualFrame::PrepareForCall(int spilled_args, int dropped_args) {
- ASSERT(height() >= dropped_args);
- ASSERT(height() >= spilled_args);
- ASSERT(dropped_args <= spilled_args);
-
- SyncRange(0, element_count() - 1);
- // Spill registers.
- for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
- if (is_used(i)) {
- SpillElementAt(register_location(i));
- }
- }
-
- // Spill the arguments.
- for (int i = element_count() - spilled_args; i < element_count(); i++) {
- if (!elements_[i].is_memory()) {
- SpillElementAt(i);
- }
- }
-
- // Forget the frame elements that will be popped by the call.
- Forget(dropped_args);
-}
-
-
-void VirtualFrame::PrepareForReturn() {
- // Spill all locals. This is necessary to make sure all locals have
- // the right value when breaking at the return site in the debugger.
- for (int i = 0; i < expression_base_index(); i++) {
- SpillElementAt(i);
- }
-}
-
-
-void VirtualFrame::SetElementAt(int index, Result* value) {
- int frame_index = element_count() - index - 1;
- ASSERT(frame_index >= 0);
- ASSERT(frame_index < element_count());
- ASSERT(value->is_valid());
- FrameElement original = elements_[frame_index];
-
- // Early exit if the element is the same as the one being set.
- bool same_register = original.is_register()
- && value->is_register()
- && original.reg().is(value->reg());
- bool same_constant = original.is_constant()
- && value->is_constant()
- && original.handle().is_identical_to(value->handle());
- if (same_register || same_constant) {
- value->Unuse();
- return;
- }
-
- InvalidateFrameSlotAt(frame_index);
-
- if (value->is_register()) {
- if (is_used(value->reg())) {
- // The register already appears on the frame. Either the existing
- // register element, or the new element at frame_index, must be made
- // a copy.
- int i = register_location(value->reg());
-
- if (i < frame_index) {
- // The register FrameElement is lower in the frame than the new copy.
- elements_[frame_index] = CopyElementAt(i);
- } else {
- // There was an early bailout for the case of setting a
- // register element to itself.
- ASSERT(i != frame_index);
- elements_[frame_index] = elements_[i];
- elements_[i] = CopyElementAt(frame_index);
- if (elements_[frame_index].is_synced()) {
- elements_[i].set_sync();
- }
- elements_[frame_index].clear_sync();
- set_register_location(value->reg(), frame_index);
- for (int j = i + 1; j < element_count(); j++) {
- if (elements_[j].is_copy() && elements_[j].index() == i) {
- elements_[j].set_index(frame_index);
- }
- }
- }
- } else {
- // The register value->reg() was not already used on the frame.
- Use(value->reg(), frame_index);
- elements_[frame_index] =
- FrameElement::RegisterElement(value->reg(),
- FrameElement::NOT_SYNCED,
- value->type_info());
- }
- } else {
- ASSERT(value->is_constant());
- elements_[frame_index] =
- FrameElement::ConstantElement(value->handle(),
- FrameElement::NOT_SYNCED);
- }
- value->Unuse();
-}
-
-
// Specialization of List::ResizeAdd to non-inlined version for FrameElements.
// The function ResizeAdd becomes a real function, whose implementation is the
// inlined ResizeAddInternal.
void ForgetElements(int count);
// Spill all values from the frame to memory.
- void SpillAll();
+ inline void SpillAll();
// Spill all occurrences of a specific register from the frame.
void Spill(Register reg) {
// Prepare for returning from the frame by spilling locals. This
// avoids generating unnecessary merge code when jumping to the
// shared return site. Emits code for spills.
- void PrepareForReturn();
+ inline void PrepareForReturn();
// Number of local variables after when we use a loop for allocating.
static const int kLocalVarBound = 7;
'../../src/execution.h',
'../../src/factory.cc',
'../../src/factory.h',
+ '../../src/fast-codegen.cc',
'../../src/fast-codegen.h',
'../../src/fast-dtoa.cc',
'../../src/fast-dtoa.h',
'../../src/ic.h',
'../../src/interpreter-irregexp.cc',
'../../src/interpreter-irregexp.h',
+ '../../src/jump-target-heavy-inl.h',
+ '../../src/jump-target-heavy.cc',
+ '../../src/jump-target-inl.h',
+ '../../src/jump-target-light-inl.h',
+ '../../src/jump-target-light.cc',
'../../src/jump-target.cc',
'../../src/jump-target.h',
- '../../src/jump-target-inl.h',
'../../src/jsregexp.cc',
'../../src/jsregexp.h',
'../../src/list-inl.h',
'../../src/variables.h',
'../../src/version.cc',
'../../src/version.h',
+ '../../src/virtual-frame-heavy-inl.h',
+ '../../src/virtual-frame-heavy.cc',
'../../src/virtual-frame-inl.h',
+ '../../src/virtual-frame-light-inl.h',
+ '../../src/virtual-frame-light.cc',
'../../src/virtual-frame.cc',
'../../src/virtual-frame.h',
'../../src/zone-inl.h',
'../../src/arm',
],
'sources': [
- '../../src/fast-codegen.cc',
+ '../../src/jump-target-light-inl.h',
+ '../../src/jump-target-light.cc',
+ '../../src/virtual-frame-light-inl.h',
+ '../../src/virtual-frame-light.cc',
'../../src/arm/assembler-arm-inl.h',
'../../src/arm/assembler-arm.cc',
'../../src/arm/assembler-arm.h',
'../../src/ia32',
],
'sources': [
+ '../../src/jump-target-heavy-inl.h',
+ '../../src/jump-target-heavy.cc',
+ '../../src/virtual-frame-heavy-inl.h',
+ '../../src/virtual-frame-heavy.cc',
'../../src/ia32/assembler-ia32-inl.h',
'../../src/ia32/assembler-ia32.cc',
'../../src/ia32/assembler-ia32.h',
'../../src/x64',
],
'sources': [
- '../../src/fast-codegen.cc',
+ '../../src/jump-target-heavy-inl.h',
+ '../../src/jump-target-heavy.cc',
+ '../../src/virtual-frame-heavy-inl.h',
+ '../../src/virtual-frame-heavy.cc',
'../../src/x64/assembler-x64-inl.h',
'../../src/x64/assembler-x64.cc',
'../../src/x64/assembler-x64.h',
/* Begin PBXBuildFile section */
58950D5E0F55519800F3E8BA /* jump-target.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D500F55514900F3E8BA /* jump-target.cc */; };
58950D5F0F55519D00F3E8BA /* jump-target-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D4F0F55514900F3E8BA /* jump-target-ia32.cc */; };
+ 58950D5F0F55519D00F3E8BA /* jump-target-heavy.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D4F0F55514900F3E8BA /* jump-target-heavy.cc */; };
58950D600F5551A300F3E8BA /* jump-target.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D500F55514900F3E8BA /* jump-target.cc */; };
58950D610F5551A400F3E8BA /* jump-target-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D4E0F55514900F3E8BA /* jump-target-arm.cc */; };
+ 58950D610F5551A400F3E8BA /* jump-target-light.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D4E0F55514900F3E8BA /* jump-target-light.cc */; };
58950D620F5551AF00F3E8BA /* register-allocator-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D530F55514900F3E8BA /* register-allocator-ia32.cc */; };
58950D630F5551AF00F3E8BA /* register-allocator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D540F55514900F3E8BA /* register-allocator.cc */; };
58950D640F5551B500F3E8BA /* register-allocator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D540F55514900F3E8BA /* register-allocator.cc */; };
58950D650F5551B600F3E8BA /* register-allocator-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D520F55514900F3E8BA /* register-allocator-arm.cc */; };
58950D660F5551C200F3E8BA /* virtual-frame.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D5A0F55514900F3E8BA /* virtual-frame.cc */; };
58950D670F5551C400F3E8BA /* virtual-frame-ia32.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D580F55514900F3E8BA /* virtual-frame-ia32.cc */; };
+ 58950D670F5551C400F3E8BA /* virtual-frame-heavy.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D580F55514900F3E8BA /* virtual-frame-heavy.cc */; };
58950D680F5551CB00F3E8BA /* virtual-frame.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D5A0F55514900F3E8BA /* virtual-frame.cc */; };
58950D690F5551CE00F3E8BA /* virtual-frame-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D560F55514900F3E8BA /* virtual-frame-arm.cc */; };
+ 58950D690F5551CE00F3E8BA /* virtual-frame-light.cc in Sources */ = {isa = PBXBuildFile; fileRef = 58950D560F55514900F3E8BA /* virtual-frame-light.cc */; };
8900116C0E71CA2300F91F35 /* libraries.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8900116B0E71CA2300F91F35 /* libraries.cc */; };
890A13FE0EE9C47F00E49346 /* interpreter-irregexp.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89A15C660EE4665300B48DEB /* interpreter-irregexp.cc */; };
890A14010EE9C4B000E49346 /* regexp-macro-assembler-arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = 89A15C700EE466D000B48DEB /* regexp-macro-assembler-arm.cc */; };
22A76C900FF259E600FDC694 /* log-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "log-inl.h"; sourceTree = "<group>"; };
58242A1E0FA1F14D00BD6F59 /* json-delay.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = "json-delay.js"; sourceTree = "<group>"; };
58950D4E0F55514900F3E8BA /* jump-target-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "jump-target-arm.cc"; path = "arm/jump-target-arm.cc"; sourceTree = "<group>"; };
+ 58950D4E0F55514900F3E8BA /* jump-target-light.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "jump-target-light.cc"; path = "jump-target-light.cc"; sourceTree = "<group>"; };
58950D4F0F55514900F3E8BA /* jump-target-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "jump-target-ia32.cc"; path = "ia32/jump-target-ia32.cc"; sourceTree = "<group>"; };
+ 58950D4F0F55514900F3E8BA /* jump-target-heavy.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "jump-target-heavy.cc"; path = "jump-target-heavy.cc"; sourceTree = "<group>"; };
58950D500F55514900F3E8BA /* jump-target.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "jump-target.cc"; sourceTree = "<group>"; };
58950D510F55514900F3E8BA /* jump-target.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "jump-target.h"; sourceTree = "<group>"; };
58950D520F55514900F3E8BA /* register-allocator-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "register-allocator-arm.cc"; path = "arm/register-allocator-arm.cc"; sourceTree = "<group>"; };
58950D540F55514900F3E8BA /* register-allocator.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "register-allocator.cc"; sourceTree = "<group>"; };
58950D550F55514900F3E8BA /* register-allocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "register-allocator.h"; sourceTree = "<group>"; };
58950D560F55514900F3E8BA /* virtual-frame-arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "virtual-frame-arm.cc"; path = "arm/virtual-frame-arm.cc"; sourceTree = "<group>"; };
+ 58950D560F55514900F3E8BA /* virtual-frame-light.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "virtual-frame-light.cc"; path = "virtual-frame-light.cc"; sourceTree = "<group>"; };
58950D570F55514900F3E8BA /* virtual-frame-arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "virtual-frame-arm.h"; path = "arm/virtual-frame-arm.h"; sourceTree = "<group>"; };
58950D580F55514900F3E8BA /* virtual-frame-ia32.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "virtual-frame-ia32.cc"; path = "ia32/virtual-frame-ia32.cc"; sourceTree = "<group>"; };
+ 58950D580F55514900F3E8BA /* virtual-frame-heavy.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "virtual-frame-heavy.cc"; path = "virtual-frame-heavy.cc"; sourceTree = "<group>"; };
58950D590F55514900F3E8BA /* virtual-frame-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "virtual-frame-ia32.h"; path = "ia32/virtual-frame-ia32.h"; sourceTree = "<group>"; };
58950D5A0F55514900F3E8BA /* virtual-frame.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "virtual-frame.cc"; sourceTree = "<group>"; };
58950D5B0F55514900F3E8BA /* virtual-frame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "virtual-frame.h"; sourceTree = "<group>"; };
8956B6CD0F5D86570033B5A2 /* debug-agent.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "debug-agent.cc"; sourceTree = "<group>"; };
8956B6CE0F5D86570033B5A2 /* debug-agent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "debug-agent.h"; sourceTree = "<group>"; };
895FA720107FFB15006F39D4 /* jump-target-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "jump-target-inl.h"; sourceTree = "<group>"; };
+ 895FA720107FFB15006F39D4 /* jump-target-light-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "jump-target-light-inl.h"; sourceTree = "<group>"; };
+ 895FA720107FFB15006F39D4 /* jump-target-heavy-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "jump-target-heavy-inl.h"; sourceTree = "<group>"; };
895FA725107FFB57006F39D4 /* codegen-ia32-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "codegen-ia32-inl.h"; path = "ia32/codegen-ia32-inl.h"; sourceTree = "<group>"; };
895FA72A107FFB85006F39D4 /* register-allocator-ia32-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "register-allocator-ia32-inl.h"; path = "ia32/register-allocator-ia32-inl.h"; sourceTree = "<group>"; };
895FA72B107FFB85006F39D4 /* register-allocator-ia32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "register-allocator-ia32.h"; path = "ia32/register-allocator-ia32.h"; sourceTree = "<group>"; };
897FF14E0E719B8F00D62E90 /* jsregexp.cc */,
897FF14F0E719B8F00D62E90 /* jsregexp.h */,
895FA720107FFB15006F39D4 /* jump-target-inl.h */,
+ 895FA720107FFB15006F39D4 /* jump-target-heavy-inl.h */,
+ 895FA720107FFB15006F39D4 /* jump-target-light-inl.h */,
58950D4E0F55514900F3E8BA /* jump-target-arm.cc */,
+ 58950D4E0F55514900F3E8BA /* jump-target-light.cc */,
58950D4F0F55514900F3E8BA /* jump-target-ia32.cc */,
+ 58950D4F0F55514900F3E8BA /* jump-target-heavy.cc */,
58950D500F55514900F3E8BA /* jump-target.cc */,
58950D510F55514900F3E8BA /* jump-target.h */,
897FF1500E719B8F00D62E90 /* list-inl.h */,
897FF32F0FAA0ED200136CF6 /* version.cc */,
897FF3300FAA0ED200136CF6 /* version.h */,
58950D560F55514900F3E8BA /* virtual-frame-arm.cc */,
+ 58950D560F55514900F3E8BA /* virtual-frame-light.cc */,
58950D570F55514900F3E8BA /* virtual-frame-arm.h */,
58950D580F55514900F3E8BA /* virtual-frame-ia32.cc */,
+ 58950D580F55514900F3E8BA /* virtual-frame-heavy.cc */,
58950D590F55514900F3E8BA /* virtual-frame-ia32.h */,
58950D5A0F55514900F3E8BA /* virtual-frame.cc */,
58950D5B0F55514900F3E8BA /* virtual-frame.h */,
89A88E0E0E71A66F0043BA31 /* jsregexp.cc in Sources */,
58950D5E0F55519800F3E8BA /* jump-target.cc in Sources */,
58950D5F0F55519D00F3E8BA /* jump-target-ia32.cc in Sources */,
+ 58950D5F0F55519D00F3E8BA /* jump-target-heavy.cc in Sources */,
8900116C0E71CA2300F91F35 /* libraries.cc in Sources */,
89A88E0F0E71A6740043BA31 /* log.cc in Sources */,
89A88E100E71A6770043BA31 /* macro-assembler-ia32.cc in Sources */,
89A88E2D0E71A6D50043BA31 /* variables.cc in Sources */,
89B933AF0FAA0F9600201304 /* version.cc in Sources */,
58950D660F5551C200F3E8BA /* virtual-frame.cc in Sources */,
+ 58950D660F5551C200F3E8BA /* virtual-frame-heavy.cc in Sources */,
58950D670F5551C400F3E8BA /* virtual-frame-ia32.cc in Sources */,
89A88E2E0E71A6D60043BA31 /* zone.cc in Sources */,
9F4B7B890FCC877A00DC4117 /* log-utils.cc in Sources */,
89F23C610E78D5B2006B2466 /* jsregexp.cc in Sources */,
58950D600F5551A300F3E8BA /* jump-target.cc in Sources */,
58950D610F5551A400F3E8BA /* jump-target-arm.cc in Sources */,
+ 58950D610F5551A400F3E8BA /* jump-target-light.cc in Sources */,
89F23C620E78D5B2006B2466 /* libraries.cc in Sources */,
89F23C630E78D5B2006B2466 /* log.cc in Sources */,
89F23C9E0E78D5FD006B2466 /* macro-assembler-arm.cc in Sources */,
89F23C810E78D5B2006B2466 /* variables.cc in Sources */,
89B933B00FAA0F9D00201304 /* version.cc in Sources */,
58950D680F5551CB00F3E8BA /* virtual-frame.cc in Sources */,
+ 58950D680F5551CB00F3E8BA /* virtual-frame-light.cc in Sources */,
58950D690F5551CE00F3E8BA /* virtual-frame-arm.cc in Sources */,
89F23C820E78D5B2006B2466 /* zone.cc in Sources */,
9F4B7B8A0FCC877A00DC4117 /* log-utils.cc in Sources */,
>
</File>
<File
+ RelativePath="..\..\src\jump-target-heavy-inl.h"
+ >
+ </File>
+ <File
RelativePath="..\..\src\jump-target.cc"
>
</File>
>
</File>
<File
+ RelativePath="..\..\src\jump-target-heavy.cc"
+ >
+ </File>
+ <File
RelativePath="..\..\src\jsregexp.cc"
>
</File>
>
</File>
<File
+ RelativePath="..\..\src\virtual-frame-heavy-inl.h"
+ >
+ </File>
+ <File
RelativePath="..\..\src\virtual-frame.h"
>
</File>
>
</File>
<File
+ RelativePath="..\..\src\virtual-frame-heavy.cc"
+ >
+ </File>
+ <File
RelativePath="..\..\src\zone-inl.h"
>
</File>
>
</File>
<File
+ RelativePath="..\..\src\jump-target-inl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\jump-target-light-inl.h"
+ >
+ </File>
+ <File
RelativePath="..\..\src\jump-target.cc"
>
</File>
>
</File>
<File
+ RelativePath="..\..\src\jump-target-light.cc"
+ >
+ </File>
+ <File
RelativePath="..\..\src\jsregexp.cc"
>
</File>
>
</File>
<File
+ RelativePath="..\..\src\virtual-frame-light-inl.h"
+ >
+ </File>
+ <File
RelativePath="..\..\src\virtual-frame.h"
>
</File>
>
</File>
<File
+ RelativePath="..\..\src\virtual-frame-light.cc"
+ >
+ </File>
+ <File
RelativePath="..\..\src\zone-inl.h"
>
</File>
>
</File>
<File
+ RelativePath="..\..\src\jump-target-heavy-inl.h"
+ >
+ </File>
+ <File
RelativePath="..\..\src\jump-target.cc"
>
</File>
>
</File>
<File
+ RelativePath="..\..\src\jump-target-heavy.cc"
+ >
+ </File>
+ <File
RelativePath="..\..\src\jsregexp.cc"
>
</File>
>
</File>
<File
+ RelativePath="..\..\src\virtual-frame-heavy-inl.h"
+ >
+ </File>
+ <File
RelativePath="..\..\src\virtual-frame.h"
>
</File>
>
</File>
<File
+ RelativePath="..\..\src\virtual-frame-heavy.cc"
+ >
+ </File>
+ <File
RelativePath="..\..\src\zone-inl.h"
>
</File>