+2008-08-13: Version 0.2.2 (130807)
+
+ Improved performance of garbage collection by changing the way
+ we use the marking stack in the event of stack overflow during
+ full garbage collection and by changing the way we mark roots.
+
+ Cleaned up ARM version by removing top of stack caching and by
+ introducing push/pop elimination.
+
+ Cleaned up the way runtime functions are called to allow
+ runtime calls with no arguments.
+
+ Changed Windows build options to make sure that exceptions are
+ disabled and that optimization flags are enabled.
+
+ Added first version of Visual Studio project files.
+
+
2008-08-06: Version 0.2.1 (130029)
Improved performance of unary addition by avoiding runtime calls.
Added platform-nullos.cc to serve as the basis for new platform
implementations.
-
+
2008-07-30: Version 0.2.0 (129146)
Changed all text files to have native svn:eol-style.
'ARFLAGS': '/NOLOGO',
'CCFLAGS': '$DIALECTFLAGS $WARNINGFLAGS /Od /Gm /MTd',
'CCPDBFLAGS': '/Zi',
- 'CPPDEFINES': ['WIN32', '_CRT_SECURE_NO_DEPRECATE', '_CRT_NONSTDC_NO_DEPRECATE', '_USE_32BIT_TIME_T', 'PCRE_STATIC', 'ENABLE_LOGGING_AND_PROFILING', 'DEBUG', '_DEBUG', 'ENABLE_DISASSEMBLER'],
- 'CXXFLAGS': '$CCFLAGS /EHsc /GS- /GR-',
+ 'CPPDEFINES': ['WIN32', '_CRT_SECURE_NO_DEPRECATE', '_CRT_NONSTDC_NO_DEPRECATE', '_USE_32BIT_TIME_T', '_HAS_EXCEPTIONS=0', 'PCRE_STATIC', 'ENABLE_LOGGING_AND_PROFILING', 'DEBUG', '_DEBUG', 'ENABLE_DISASSEMBLER'],
+ 'CXXFLAGS': '$CCFLAGS /GS- /GR- /Gy',
'DIALECTFLAGS': '/nologo',
- 'LIBS': 'WS2_32',
- 'LINKFLAGS': '/NOLOGO /SUBSYSTEM:CONSOLE /MACHINE:X86 /INCREMENTAL:NO /DEBUG',
+ 'LINKFLAGS': '/NOLOGO /MACHINE:X86 /INCREMENTAL:NO /NXCOMPAT /IGNORE:4221 /DEBUG',
'PDB': '${TARGET}.pdb',
'WARNINGFLAGS': '/W3 /WX /wd4355 /wd4800'
},
'ARFLAGS': '/NOLOGO',
'CCFLAGS': '$DIALECTFLAGS $WARNINGFLAGS /Od /Gm /MTd',
'CCPDBFLAGS': '/Zi',
- 'CPPDEFINES': ['WIN32', '_CRT_SECURE_NO_DEPRECATE', '_CRT_NONSTDC_NO_DEPRECATE', '_USE_32BIT_TIME_T', 'PCRE_STATIC', 'ENABLE_LOGGING_AND_PROFILING', 'DEBUG', '_DEBUG', 'ENABLE_DISASSEMBLER'],
- 'CXXFLAGS': '$CCFLAGS /EHsc /GS- /GR-',
+ 'CPPDEFINES': ['WIN32', '_CRT_SECURE_NO_DEPRECATE', '_CRT_NONSTDC_NO_DEPRECATE', '_USE_32BIT_TIME_T', '_HAS_EXCEPTIONS=0', 'PCRE_STATIC', 'ENABLE_LOGGING_AND_PROFILING', 'DEBUG', '_DEBUG', 'ENABLE_DISASSEMBLER'],
+ 'CXXFLAGS': '$CCFLAGS /GS- /GR- /Gy',
'DIALECTFLAGS': '/nologo',
- 'LIBS': 'WS2_32',
- 'LINKFLAGS': '/NOLOGO /SUBSYSTEM:CONSOLE /MACHINE:X86 /INCREMENTAL:NO /DEBUG',
+ 'LINKFLAGS': '/NOLOGO /MACHINE:X86 /INCREMENTAL:NO /NXCOMPAT /IGNORE:4221 /DEBUG',
'PDB': '${TARGET}.pdb',
'WARNINGFLAGS': '/WX /wd4018 /wd4244'
},
'ARFLAGS': '/NOLOGO',
'CCFLAGS': '$DIALECTFLAGS $WARNINGFLAGS /Od /Gm /MTd',
'CCPDBFLAGS': '/Zi',
- 'CPPDEFINES': ['WIN32', '_CRT_SECURE_NO_DEPRECATE', '_CRT_NONSTDC_NO_DEPRECATE', '_USE_32BIT_TIME_T', 'PCRE_STATIC', 'ENABLE_LOGGING_AND_PROFILING', 'DEBUG', '_DEBUG', 'ENABLE_DISASSEMBLER', 'SUPPORT_UTF8', 'NO_RECURSE', 'SUPPORT_UCP'],
- 'CXXFLAGS': '$CCFLAGS /EHsc /GS- /GR-',
+ 'CPPDEFINES': ['WIN32', '_CRT_SECURE_NO_DEPRECATE', '_CRT_NONSTDC_NO_DEPRECATE', '_USE_32BIT_TIME_T', '_HAS_EXCEPTIONS=0', 'PCRE_STATIC', 'ENABLE_LOGGING_AND_PROFILING', 'DEBUG', '_DEBUG', 'ENABLE_DISASSEMBLER', 'SUPPORT_UTF8', 'NO_RECURSE', 'SUPPORT_UCP'],
+ 'CXXFLAGS': '$CCFLAGS /GS- /GR- /Gy',
'DIALECTFLAGS': '/nologo',
- 'LIBS': 'WS2_32',
- 'LINKFLAGS': '/NOLOGO /SUBSYSTEM:CONSOLE /MACHINE:X86 /INCREMENTAL:NO /DEBUG',
+ 'LINKFLAGS': '/NOLOGO /MACHINE:X86 /INCREMENTAL:NO /NXCOMPAT /IGNORE:4221 /DEBUG',
'PDB': '${TARGET}.pdb',
- 'WARNINGFLAGS': '/WX /wd4003 /wd4005 /wd4018 /wd4133'
+ 'WARNINGFLAGS': '/W3 /WX /wd4355 /wd4800'
}
},
'release': {
'default': {
'ARFLAGS': '/NOLOGO',
- 'CCFLAGS': '$DIALECTFLAGS $WARNINGFLAGS /O2 /MT',
+ 'CCFLAGS': '$DIALECTFLAGS $WARNINGFLAGS /Ox /MT /Ob2 /Oi /Oy',
'CCPDBFLAGS': '/Zi',
- 'CPPDEFINES': ['WIN32', '_CRT_SECURE_NO_DEPRECATE', '_CRT_NONSTDC_NO_DEPRECATE', '_USE_32BIT_TIME_T', 'PCRE_STATIC', 'ENABLE_LOGGING_AND_PROFILING'],
- 'CXXFLAGS': '$CCFLAGS /EHsc /GS- /GR-',
+ 'CPPDEFINES': ['WIN32', '_CRT_SECURE_NO_DEPRECATE', '_CRT_NONSTDC_NO_DEPRECATE', '_USE_32BIT_TIME_T', '_HAS_EXCEPTIONS=0', 'PCRE_STATIC', 'ENABLE_LOGGING_AND_PROFILING'],
+ 'CXXFLAGS': '$CCFLAGS /GS- /GR- /Gy',
'DIALECTFLAGS': '/nologo',
- 'LIBS': 'WS2_32',
- 'LINKFLAGS': '/NOLOGO /SUBSYSTEM:CONSOLE /MACHINE:X86 /INCREMENTAL:NO /OPT:REF /OPT:ICF /SUBSYSTEM:CONSOLE',
+ 'LINKFLAGS': '/NOLOGO /MACHINE:X86 /INCREMENTAL:NO /NXCOMPAT /IGNORE:4221 /OPT:REF',
'PDB': '${TARGET}.pdb',
'WARNINGFLAGS': '/W3 /WX /wd4355 /wd4800'
},
'dtoa': {
'ARFLAGS': '/NOLOGO',
- 'CCFLAGS': '$DIALECTFLAGS $WARNINGFLAGS /O2 /MT',
+ 'CCFLAGS': '$DIALECTFLAGS $WARNINGFLAGS /Ox /MT /Ob2 /Oi /Oy',
'CCPDBFLAGS': '/Zi',
- 'CPPDEFINES': ['WIN32', '_CRT_SECURE_NO_DEPRECATE', '_CRT_NONSTDC_NO_DEPRECATE', '_USE_32BIT_TIME_T', 'PCRE_STATIC', 'ENABLE_LOGGING_AND_PROFILING'],
- 'CXXFLAGS': '$CCFLAGS /EHsc /GS- /GR-',
+ 'CPPDEFINES': ['WIN32', '_CRT_SECURE_NO_DEPRECATE', '_CRT_NONSTDC_NO_DEPRECATE', '_USE_32BIT_TIME_T', '_HAS_EXCEPTIONS=0', 'PCRE_STATIC', 'ENABLE_LOGGING_AND_PROFILING'],
+ 'CXXFLAGS': '$CCFLAGS /GS- /GR- /Gy',
'DIALECTFLAGS': '/nologo',
- 'LIBS': 'WS2_32',
- 'LINKFLAGS': '/NOLOGO /SUBSYSTEM:CONSOLE /MACHINE:X86 /INCREMENTAL:NO /OPT:REF /OPT:ICF /SUBSYSTEM:CONSOLE',
+ 'LINKFLAGS': '/NOLOGO /MACHINE:X86 /INCREMENTAL:NO /NXCOMPAT /IGNORE:4221 /OPT:REF',
'PDB': '${TARGET}.pdb',
'WARNINGFLAGS': '/WX /wd4018 /wd4244'
},
'jscre': {
'ARFLAGS': '/NOLOGO',
- 'CCFLAGS': '$DIALECTFLAGS $WARNINGFLAGS /O2 /MT',
+ 'CCFLAGS': '$DIALECTFLAGS $WARNINGFLAGS /Ox /MT /Ob2 /Oi /Oy',
'CCPDBFLAGS': '/Zi',
- 'CPPDEFINES': ['WIN32', '_CRT_SECURE_NO_DEPRECATE', '_CRT_NONSTDC_NO_DEPRECATE', '_USE_32BIT_TIME_T', 'PCRE_STATIC', 'ENABLE_LOGGING_AND_PROFILING', 'SUPPORT_UTF8', 'NO_RECURSE', 'SUPPORT_UCP'],
- 'CXXFLAGS': '$CCFLAGS /EHsc /GS- /GR-',
+ 'CPPDEFINES': ['WIN32', '_CRT_SECURE_NO_DEPRECATE', '_CRT_NONSTDC_NO_DEPRECATE', '_USE_32BIT_TIME_T', '_HAS_EXCEPTIONS=0', 'PCRE_STATIC', 'ENABLE_LOGGING_AND_PROFILING', 'SUPPORT_UTF8', 'NO_RECURSE', 'SUPPORT_UCP'],
+ 'CXXFLAGS': '$CCFLAGS /GS- /GR- /Gy',
'DIALECTFLAGS': '/nologo',
- 'LIBS': 'WS2_32',
- 'LINKFLAGS': '/NOLOGO /SUBSYSTEM:CONSOLE /MACHINE:X86 /INCREMENTAL:NO /OPT:REF /OPT:ICF /SUBSYSTEM:CONSOLE',
+ 'LINKFLAGS': '/NOLOGO /MACHINE:X86 /INCREMENTAL:NO /NXCOMPAT /IGNORE:4221 /OPT:REF',
'PDB': '${TARGET}.pdb',
- 'WARNINGFLAGS': '/WX /wd4003 /wd4005 /wd4018 /wd4133'
+ 'WARNINGFLAGS': '/W3 /WX /wd4355 /wd4800'
}
}
}
const char* v8::V8::GetVersion() {
- return "0.2.1 (130029)";
+ return "0.2.2 (130807)";
}
class Arguments BASE_EMBEDDED {
public:
Object*& operator[] (int index) {
- ASSERT(0 <= index && index <= length_);
+ ASSERT(0 <= index && index < length_);
return arguments_[-index];
}
}
// Get the total number of arguments including the receiver.
- int length() const { return length_ + 1; }
+ int length() const { return length_; }
private:
int length_;
}
+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();
B27 = 1 << 27,
// Instruction bit masks
+ RdMask = 15 << 12, // in str instruction
CondMask = 15 << 28,
OpCodeMask = 15 << 21, // in data-processing instructions
Imm24Mask = (1 << 24) - 1,
};
+DEFINE_bool(push_pop_elimination, true,
+ "eliminate redundant push/pops in assembly code");
+DEFINE_bool(print_push_pop_elimination, false,
+ "print elimination of redundant push/pops in assembly code");
+
+// add(sp, sp, 4) instruction (aka Pop())
+static const Instr kPopInstruction =
+ al | 4 * B21 | 4 | LeaveCC | I | sp.code() * B16 | sp.code() * B12;
+// str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r))
+// register r is not encoded.
+static const Instr kPushRegPattern =
+ al | B26 | 4 | NegPreIndex | sp.code() * B16;
+// ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r))
+// register r is not encoded.
+static const Instr kPopRegPattern =
+ al | B26 | L | 4 | PostIndex | sp.code() * B16;
+
// spare_buffer_
static const int kMinimalBufferSize = 4*KB;
static byte* spare_buffer_ = NULL;
void Assembler::add(Register dst, Register src1, const Operand& src2,
SBit s, Condition cond) {
addrmod1(cond | 4*B21 | s, src1, dst, src2);
+
+ // Eliminate pattern: push(r), pop()
+ // str(src, MemOperand(sp, 4, NegPreIndex), al);
+ // add(sp, sp, Operand(kPointerSize));
+ // Both instructions can be eliminated.
+ int pattern_size = 2 * kInstrSize;
+ if (FLAG_push_pop_elimination &&
+ last_bound_pos_ <= (pc_offset() - pattern_size) &&
+ reloc_info_writer.last_pc() <= (pc_ - pattern_size) &&
+ // pattern
+ instr_at(pc_ - 1 * kInstrSize) == kPopInstruction &&
+ (instr_at(pc_ - 2 * kInstrSize) & ~RdMask) == kPushRegPattern) {
+ pc_ -= 2 * kInstrSize;
+ if (FLAG_print_push_pop_elimination) {
+ PrintF("%x push(reg)/pop() eliminated\n", pc_offset());
+ }
+ }
}
// Load/Store instructions
void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
addrmod2(cond | B26 | L, dst, src);
+
+ // Eliminate pattern: push(r), pop(r)
+ // str(r, MemOperand(sp, 4, NegPreIndex), al)
+ // ldr(r, MemOperand(sp, 4, PostIndex), al)
+ // Both instructions can be eliminated.
+ int pattern_size = 2 * kInstrSize;
+ if (FLAG_push_pop_elimination &&
+ last_bound_pos_ <= (pc_offset() - pattern_size) &&
+ reloc_info_writer.last_pc() <= (pc_ - pattern_size) &&
+ // pattern
+ instr_at(pc_ - 1 * kInstrSize) == (kPopRegPattern | dst.code() * B12) &&
+ instr_at(pc_ - 2 * kInstrSize) == (kPushRegPattern | dst.code() * B12)) {
+ pc_ -= 2 * kInstrSize;
+ if (FLAG_print_push_pop_elimination) {
+ PrintF("%x push/pop (same reg) eliminated\n", pc_offset());
+ }
+ }
}
void Assembler::str(Register src, const MemOperand& dst, Condition cond) {
addrmod2(cond | B26, src, dst);
+
+ // Eliminate pattern: pop(), push(r)
+ // add sp, sp, #4 LeaveCC, al; str r, [sp, #-4], al
+ // -> str r, [sp, 0], al
+ int pattern_size = 2 * kInstrSize;
+ if (FLAG_push_pop_elimination &&
+ last_bound_pos_ <= (pc_offset() - pattern_size) &&
+ reloc_info_writer.last_pc() <= (pc_ - pattern_size) &&
+ instr_at(pc_ - 1 * kInstrSize) == (kPushRegPattern | src.code() * B12) &&
+ instr_at(pc_ - 2 * kInstrSize) == kPopInstruction) {
+ pc_ -= 2 * kInstrSize;
+ emit(al | B26 | 0 | Offset | sp.code() * B16 | src.code() * B12);
+ if (FLAG_print_push_pop_elimination) {
+ PrintF("%x pop()/push(reg) eliminated\n", pc_offset());
+ }
+ }
}
// rm <shift_op> rs
explicit Operand(Register rm, ShiftOp shift_op, Register rs);
+ // Return true if this is a register operand.
+ INLINE(bool is_reg() const);
+
+ Register rm() const { return rm_; }
+
private:
Register rm_;
Register rs_;
// Pseudo instructions
void nop() { mov(r0, Operand(r0)); }
- void push(Register src, Condition cond = al) {
- str(src, MemOperand(sp, 4, NegPreIndex), cond);
+ void push(Register src) {
+ str(src, MemOperand(sp, 4, NegPreIndex), al);
+ }
+
+ void pop(Register dst) {
+ ldr(dst, MemOperand(sp, 4, PostIndex), al);
}
- void pop(Register dst, Condition cond = al) {
- ldr(dst, MemOperand(sp, 4, PostIndex), cond);
+ void pop() {
+ add(sp, sp, Operand(kPointerSize));
}
// Load effective address of memory operand x into register dst
}
return "unknown relocation type";
}
-#endif // ENABLE_DISASSEMBLER
-#ifdef DEBUG
void RelocInfo::Print() {
PrintF("%p %s", pc_, RelocModeName(rmode_));
if (rmode_ == comment) {
PrintF("\n");
}
+#endif // ENABLE_DISASSEMBLER
+#ifdef DEBUG
void RelocInfo::Verify() {
switch (rmode_) {
case embedded_object:
#ifdef ENABLE_DISASSEMBLER
// Printing
static const char* RelocModeName(RelocMode rmode);
+ void Print();
#endif // ENABLE_DISASSEMBLER
#ifdef DEBUG
// Debugging
- void Print();
void Verify();
#endif
void Builtins::Generate_Adaptor(MacroAssembler* masm,
int argc,
CFunctionId id) {
+ // r0 contains the number of arguments excluding the receiver.
+ // JumpToBuiltin expects r0 to contains the number of arguments
+ // including the receiver.
+ __ add(r0, r0, Operand(1));
__ JumpToBuiltin(ExternalReference(id));
}
__ EnterJSFrame(0);
// Allocate the new receiver object.
- __ push(r0);
__ ldr(r0, MemOperand(pp, JavaScriptFrameConstants::kFunctionOffset));
+ __ push(r0);
__ CallRuntime(Runtime::kNewObject, 1);
- __ push(r0); // empty TOS cache
+ __ push(r0); // save the receiver
// Push the function and the allocated receiver from the stack.
__ ldr(r1, MemOperand(pp, JavaScriptFrameConstants::kFunctionOffset));
// Restore context from the frame and discard the function.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
- __ add(sp, sp, Operand(kPointerSize));
+ __ pop();
// If the result is an object (in the ECMA sense), we should get rid
// of the receiver and use the result; see ECMA-262 section 13.2.2-7
__ add(fp, sp, Operand(-StandardFrameConstants::kContextOffset));
__ mov(pp, Operand(ip)); // setup new parameter pointer
// r0 is already set to 0 as spare slot to store caller code object during GC
+ __ push(r0); // code pointer
// Inlined EnterJSFrame ends here.
- // Empty top-of-stack cache (code pointer).
- __ push(r0);
-
// Store the registers containing object pointers on the expression stack to
// make sure that these are correctly updated during GC.
// Use sp as base to push.
__ CopyRegistersFromMemoryToStack(sp, pointer_regs);
- // Empty top-of-stack cache (fake receiver).
- __ push(r0);
-
#ifdef DEBUG
__ RecordComment("// Calling from debug break to runtime - come in - over");
#endif
__ mov(sp, Operand(fp)); // respect ABI stack constraint
__ ldm(ia, sp, pp.bit() | fp.bit() | sp.bit() | lr.bit());
- __ add(sp, sp, Operand(kPointerSize)); // discard fake function
+ __ pop(); // discard fake function
// Inlined ExitJSFrame ends here.
void Builtins::Generate_Adaptor(MacroAssembler* masm,
int argc,
CFunctionId id) {
- __ mov(eax, argc);
+ // argc is the number of arguments excluding the receiver.
+ // JumpToBuiltin expects eax to contain the number of arguments
+ // including the receiver.
+ __ mov(eax, argc + 1);
__ mov(Operand::StaticVariable(ExternalReference::builtin_passed_function()),
edi);
__ JumpToBuiltin(ExternalReference(id));
__ RecordComment("// Calling from debug break to runtime - come in - over");
#endif
__ Set(eax, Immediate(0)); // no arguments
- __ push(eax); // fake receiver - use NULL
__ mov(Operand(ebx), Immediate(ExternalReference::debug_break()));
CEntryDebugBreakStub ceb;
namespace v8 { namespace internal {
+#ifdef DEBUG
+ DECLARE_bool(print_builtin_code);
+#endif // DEBUG
+
+
// ----------------------------------------------------------------------------
// Support macros for defining builtins in C.
// ----------------------------------------------------------------------------
//
// and they evaluate to undefined values if too few arguments were
// passed to the builtin function invocation.
+//
+// __argc__ is the number of arguments including the receiver.
// ----------------------------------------------------------------------------
} else if (type == StackFrame::ARGUMENTS_ADAPTOR) { \
ArgumentsAdaptorFrame* frame = \
ArgumentsAdaptorFrame::cast(it.frame()); \
- __argc__ = frame->GetProvidedParametersCount(); \
+ /* __argc__ includes the receiver. */ \
+ __argc__ = frame->GetProvidedParametersCount() + 1; \
__argv__ = reinterpret_cast<Object**>(frame->pp()) - 1; \
it.Advance(); \
is_construct = \
Object* a2 = BUILTIN_ARG(3);
-#define BUILTIN_VARARG(name, aidx0, aidxN) \
- BUILTIN_0(name); \
- int aidx0 = 1; \
- int aidxN = __argc__; \
-
-
// Use an inline function to avoid evaluating the index (n) more than
// once in the BUILTIN_ARG macro.
static inline Object* __builtin_arg__(int n, int argc, Object** argv) {
ASSERT(n >= 0);
- return (argc >= n) ? argv[-n] : Heap::undefined_value();
+ return (argc > n) ? argv[-n] : Heap::undefined_value();
}
// Optimize the case where there is one argument and the argument is a
// small smi.
- if (__argc__ == 1) {
+ if (__argc__ == 2) {
Object* obj = BUILTIN_ARG(1);
if (obj->IsSmi()) {
int len = Smi::cast(obj)->value();
// Take the argument as the length.
obj = array->Initialize(0);
if (obj->IsFailure()) return obj;
- if (__argc__ == 1) return array->SetElementsLength(BUILTIN_ARG(1));
+ if (__argc__ == 2) return array->SetElementsLength(BUILTIN_ARG(1));
}
// Optimize the case where there are no paramaters passed.
- if (__argc__ == 0) return array->Initialize(4);
+ if (__argc__ == 1) return array->Initialize(4);
// Take the arguments as elements.
- int len = Smi::FromInt(__argc__)->value();
- Object* obj = Heap::AllocateFixedArrayWithHoles(len);
+ int number_of_elements = __argc__ - 1;
+ Smi* len = Smi::FromInt(number_of_elements);
+ Object* obj = Heap::AllocateFixedArrayWithHoles(len->value());
if (obj->IsFailure()) return obj;
FixedArray* elms = FixedArray::cast(obj);
FixedArray::WriteBarrierMode mode = elms->GetWriteBarrierMode();
// Fill in the content
- for (int index = 0; index < __argc__; index++) {
+ for (int index = 0; index < number_of_elements; index++) {
elms->set(index, BUILTIN_ARG(index+1), mode);
}
// Set length and elements on the array.
array->set_elements(FixedArray::cast(obj));
- array->set_length(Smi::FromInt(__argc__));
+ array->set_length(len);
return array;
}
int len = Smi::cast(array->length())->value();
// Set new length.
- int new_length = len + __argc__;
+ int new_length = len + __argc__ - 1;
FixedArray* elms = FixedArray::cast(array->elements());
if (new_length <= elms->length()) {
// Backing storage has extra space for the provided values.
- for (int index = 0; index < __argc__; index++) {
+ for (int index = 0; index < __argc__ - 1; index++) {
elms->set(index + len, BUILTIN_ARG(index+1));
}
} else {
// Fill out the new array with old elements.
for (int i = 0; i < len; i++) new_elms->set(i, elms->get(i), mode);
// Add the provided values.
- for (int index = 0; index < __argc__; index++) {
+ for (int index = 0; index < __argc__ - 1; index++) {
new_elms->set(index + len, BUILTIN_ARG(index+1), mode);
}
// Set the new backing storage.
if (args_obj->IsUndefined()) return holder;
FixedArray* args = FixedArray::cast(args_obj);
int length = args->length();
- if (argc < length) length = argc;
+ if (argc <= length) length = argc - 1;
for (int i = 0; i < length; i++) {
Object* argtype = args->get(i);
if (argtype->IsUndefined()) continue;
callee,
is_construct,
reinterpret_cast<void**>(__argv__ - 1),
- __argc__);
+ __argc__ - 1);
v8::Handle<v8::Value> value;
{
callee,
is_construct,
reinterpret_cast<void**>(__argv__ - 1),
- __argc__);
+ __argc__ - 1);
v8::Handle<v8::Value> value;
{
// Leaving JavaScript.
// Log the event and add the code to the builtins array.
LOG(CodeCreateEvent("Builtin", Code::cast(code), functions[i].s_name));
builtins_[i] = code;
+#ifdef DEBUG
+ if (FLAG_print_builtin_code) {
+ PrintF("Builtin: %s\n", functions[i].s_name);
+ code->Print();
+ PrintF("\n");
+ }
+#endif
} else {
// Deserializing. The values will be filled in during IterateBuiltins.
builtins_[i] = NULL;
virtual ~CodeStub() {}
+ protected:
+ static const int kMajorBits = 5;
+ static const int kMinorBits = kBitsPerPointer - kMajorBits - kSmiTagSize;
+
private:
// Generates the assembler code for the stub.
virtual void Generate(MacroAssembler* masm) = 0;
bool AllowsStubCalls() { return MajorKey() <= RecordWrite; }
- static const int kMajorBits = 5;
- static const int kMinorBits = kBitsPerPointer - kMajorBits - kSmiTagSize;
-
class MajorKeyBits: public BitField<uint32_t, 0, kMajorBits> {};
class MinorKeyBits: public BitField<uint32_t, kMajorBits, kMinorBits> {};
}
private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(ParameterCount);
-
const Register reg_;
const int immediate_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ParameterCount);
};
DECLARE_bool(debug_info);
DECLARE_bool(debug_code);
+#ifdef ENABLE_DISASSEMBLER
+DEFINE_bool(print_code, false, "print generated code");
+#endif
+
#ifdef DEBUG
DECLARE_bool(gc_greedy);
DEFINE_bool(trace_codegen, false,
"print name of functions for which code is generated");
-DEFINE_bool(print_code, false, "print generated code");
DEFINE_bool(print_builtin_code, false, "print generated code for builtins");
DEFINE_bool(print_source, false, "pretty print source code");
DEFINE_bool(print_builtin_source, false,
AccessReference(ref, CodeGenState::INIT_CONST);
}
- void ToBoolean(Register reg, Label* true_target, Label* false_target);
+ void ToBoolean(Label* true_target, Label* false_target);
// Access property from the reference (must be at the TOS).
Handle<Code> ArmCodeGenerator::MakeCode(FunctionLiteral* flit,
Handle<Script> script,
bool is_eval) {
+#ifdef ENABLE_DISASSEMBLER
+ bool print_code = FLAG_print_code && !Bootstrapper::IsActive();
+#endif // ENABLE_DISASSEMBLER
+
#ifdef DEBUG
bool print_source = false;
bool print_ast = false;
- bool print_code = false;
const char* ftype;
if (Bootstrapper::IsActive()) {
} else {
print_source = FLAG_print_source;
print_ast = FLAG_print_ast;
- print_code = FLAG_print_code;
ftype = "user-defined";
}
// Add unresolved entries in the code to the fixup list.
Bootstrapper::AddFixup(*code, cgen.masm());
-#ifdef DEBUG
+#ifdef ENABLE_DISASSEMBLER
if (print_code) {
// Print the source code if available.
if (!script->IsUndefined() && !script->source()->IsUndefined()) {
PrintF("\n\n");
}
PrintF("--- Code ---\n");
- code->Print();
+ code->Disassemble();
}
-#endif // DEBUG
+#endif // ENABLE_DISASSEMBLER
return code;
}
// Calling conventions:
-// r0: always contains top-of-stack (TOS), but in case of a call it's
-// the number of arguments
+// r0: the number of arguments
// fp: frame pointer
// sp: stack pointer
// pp: caller's parameter pointer
// Allocate space for locals and initialize them.
if (scope->num_stack_slots() > 0) {
Comment cmnt(masm_, "[ allocate space for locals");
- // Pushing the first local materializes the code slot on the stack
- // (formerly stored in tos register r0).
- __ Push(Operand(Factory::undefined_value()));
- // The remaining locals are pushed using the fact that r0 (tos)
- // already contains the undefined value.
- for (int i = 1; i < scope->num_stack_slots(); i++) {
- __ push(r0);
+ // Initialize stack slots with 'undefined' value.
+ __ mov(ip, Operand(Factory::undefined_value()));
+ for (int i = 0; i < scope->num_stack_slots(); i++) {
+ __ push(ip);
}
}
if (scope->num_heap_slots() > 0) {
// Allocate local context.
// Get outer context and create a new context based on it.
- __ Push(FunctionOperand());
+ __ ldr(r0, FunctionOperand());
+ __ push(r0);
__ CallRuntime(Runtime::kNewContext, 1); // r0 holds the result
if (kDebug) {
__ stop("NewContext: r0 is expected to be the same as cp");
__ bind(&verified_true);
}
- __ pop(r0); // restore TOS
// Update context local.
__ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
}
Comment cmnt(masm_, "[ allocate arguments object");
{
Reference target(this, scope->arguments());
- __ Push(FunctionOperand());
+ __ ldr(r0, FunctionOperand());
+ __ push(r0);
__ CallRuntime(Runtime::kNewArguments, 1);
+ __ push(r0);
SetValue(&target);
}
// The value of arguments must also be stored in .arguments.
scope->VisitIllegalRedeclaration(this);
} else {
Comment cmnt(masm_, "[ declarations");
+ // ProcessDeclarations calls DeclareGlobals indirectly
ProcessDeclarations(scope->declarations());
+
// Bail out if a stack-overflow exception occured when
// processing declarations.
if (HasStackOverflow()) return;
}
- if (FLAG_trace) __ CallRuntime(Runtime::kTraceEnter, 1);
+ if (FLAG_trace) {
+ // Push a valid value as the parameter. The runtime call only uses
+ // it as the return value to indicate non-failure.
+ __ mov(r0, Operand(Smi::FromInt(0)));
+ __ push(r0);
+ __ CallRuntime(Runtime::kTraceEnter, 1);
+ }
CheckStack();
// Compile the body of the function in a vanilla state. Don't
bool is_builtin = Bootstrapper::IsActive();
bool should_trace =
is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls;
- if (should_trace) __ CallRuntime(Runtime::kDebugTrace, 1);
+ if (should_trace) {
+ // Push a valid value as the parameter. The runtime call only uses
+ // it as the return value to indicate non-failure.
+ __ mov(r0, Operand(Smi::FromInt(0)));
+ __ push(r0);
+ __ CallRuntime(Runtime::kDebugTrace, 1);
+ }
#endif
VisitStatements(body);
}
// fp: frame pointer
// pp: parameter pointer
// cp: callee's context
- __ Push(Operand(Factory::undefined_value()));
+ __ mov(r0, Operand(Factory::undefined_value()));
+
__ bind(&function_return_);
- if (FLAG_trace) __ CallRuntime(Runtime::kTraceExit, 1);
+ if (FLAG_trace) {
+ // Push the return value on the stack as the parameter.
+ // Runtime::TraceExit returns the parameter as it is.
+ __ push(r0);
+ __ CallRuntime(Runtime::kTraceExit, 1);
+ }
+
ExitJSFrame();
// Code generation state must be reset.
}
-// Loads a value on TOS. If it is a boolean value, the result may have been
-// (partially) translated into branches, or it may have set the condition code
-// register. If force_cc is set, the value is forced to set the condition code
-// register and no value is pushed. If the condition code register was set,
+// Loads a value on the stack. If it is a boolean value, the result may have
+// been (partially) translated into branches, or it may have set the condition
+// code register. If force_cc is set, the value is forced to set the condition
+// code register and no value is pushed. If the condition code register was set,
// has_cc() is true and cc_reg_ contains the condition to test for 'true'.
void ArmCodeGenerator::LoadCondition(Expression* x,
CodeGenState::AccessType access,
Visit(x);
state_ = old_state;
if (force_cc && !has_cc()) {
- // Pop the TOS from the stack and convert it to a boolean in the
- // condition code register.
- __ mov(r1, Operand(r0));
- __ pop(r0);
- ToBoolean(r1, true_target, false_target);
+ // Convert the TOS value to a boolean in the condition code register.
+ ToBoolean(true_target, false_target);
}
ASSERT(has_cc() || !force_cc);
}
// convert cc_reg_ into a bool
Label loaded, materialize_true;
__ b(cc_reg_, &materialize_true);
- __ Push(Operand(Factory::false_value()));
+ __ mov(r0, Operand(Factory::false_value()));
+ __ push(r0);
__ b(&loaded);
__ bind(&materialize_true);
- __ Push(Operand(Factory::true_value()));
+ __ mov(r0, Operand(Factory::true_value()));
+ __ push(r0);
__ bind(&loaded);
cc_reg_ = al;
}
// reincarnate "true", if necessary
if (true_target.is_linked()) {
__ bind(&true_target);
- __ Push(Operand(Factory::true_value()));
+ __ mov(r0, Operand(Factory::true_value()));
+ __ push(r0);
}
// if both "true" and "false" need to be reincarnated,
// jump across code for "false"
// reincarnate "false", if necessary
if (false_target.is_linked()) {
__ bind(&false_target);
- __ Push(Operand(Factory::false_value()));
+ __ mov(r0, Operand(Factory::false_value()));
+ __ push(r0);
}
// everything is loaded at this point
__ bind(&loaded);
void ArmCodeGenerator::LoadGlobal() {
- __ Push(GlobalObject());
+ __ ldr(r0, GlobalObject());
+ __ push(r0);
}
} else {
Load(e);
__ CallRuntime(Runtime::kThrowReferenceError, 1);
+ __ push(r0);
}
}
if (size <= 0) {
// Do nothing. No popping is necessary.
} else {
+ __ pop(r0);
__ add(sp, sp, Operand(size * kPointerSize));
+ __ push(r0);
}
}
// ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given
// register to a boolean in the condition code register. The code
// may jump to 'false_target' in case the register converts to 'false'.
-void ArmCodeGenerator::ToBoolean(Register reg,
- Label* true_target,
+void ArmCodeGenerator::ToBoolean(Label* true_target,
Label* false_target) {
- // Note: The generated code snippet cannot change 'reg'.
+ // Note: The generated code snippet does not change stack variables.
// Only the condition code should be set.
+ __ pop(r0);
// Fast case checks
- // Check if reg is 'false'.
- __ cmp(reg, Operand(Factory::false_value()));
+ // Check if the value is 'false'.
+ __ cmp(r0, Operand(Factory::false_value()));
__ b(eq, false_target);
- // Check if reg is 'true'.
- __ cmp(reg, Operand(Factory::true_value()));
+ // Check if the value is 'true'.
+ __ cmp(r0, Operand(Factory::true_value()));
__ b(eq, true_target);
- // Check if reg is 'undefined'.
- __ cmp(reg, Operand(Factory::undefined_value()));
+ // Check if the value is 'undefined'.
+ __ cmp(r0, Operand(Factory::undefined_value()));
__ b(eq, false_target);
- // Check if reg is a smi.
- __ cmp(reg, Operand(Smi::FromInt(0)));
+ // Check if the value is a smi.
+ __ cmp(r0, Operand(Smi::FromInt(0)));
__ b(eq, false_target);
- __ tst(reg, Operand(kSmiTagMask));
+ __ tst(r0, Operand(kSmiTagMask));
__ b(eq, true_target);
// Slow case: call the runtime.
__ push(r0);
- if (r0.is(reg)) {
- __ CallRuntime(Runtime::kToBool, 1);
- } else {
- __ mov(r0, Operand(reg));
- __ CallRuntime(Runtime::kToBool, 1);
- }
+ __ CallRuntime(Runtime::kToBool, 1);
+
// Convert result (r0) to condition code
__ cmp(r0, Operand(Factory::false_value()));
- __ pop(r0);
cc_reg_ = ne;
}
void GetPropertyStub::Generate(MacroAssembler* masm) {
+ // sp[0]: key
+ // sp[1]: receiver
Label slow, fast;
- // Get the object from the stack.
- __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); // 1 ~ key
+ // Get the key and receiver object from the stack.
+ __ ldm(ia, sp, r0.bit() | r1.bit());
// Check that the key is a smi.
__ tst(r0, Operand(kSmiTagMask));
__ b(ne, &slow);
__ ldm(ia, sp, r0.bit() | r1.bit());
__ stm(db_w, sp, r0.bit() | r1.bit());
// Do tail-call to runtime routine.
- __ mov(r0, Operand(1)); // not counting receiver
- __ JumpToBuiltin(ExternalReference(Runtime::kGetProperty));
+ __ TailCallRuntime(ExternalReference(Runtime::kGetProperty), 2);
// Fast case: Do the load.
__ bind(&fast);
};
+
void SetPropertyStub::Generate(MacroAssembler* masm) {
+ // r0 : value
+ // sp[0] : key
+ // sp[1] : receiver
+
Label slow, fast, array, extra, exit;
// Get the key and the object from the stack.
- __ ldm(ia, sp, r1.bit() | r3.bit()); // r0 == value, r1 == key, r3 == object
+ __ ldm(ia, sp, r1.bit() | r3.bit()); // r1 = key, r3 = receiver
// Check that the key is a smi.
__ tst(r1, Operand(kSmiTagMask));
__ b(ne, &slow);
// Slow case: Push extra copies of the arguments (3).
- // r0 == value
__ bind(&slow);
__ ldm(ia, sp, r1.bit() | r3.bit()); // r0 == value, r1 == key, r3 == object
__ stm(db_w, sp, r0.bit() | r1.bit() | r3.bit());
// Do tail-call to runtime routine.
- __ mov(r0, Operand(2)); // not counting receiver
- __ JumpToBuiltin(ExternalReference(Runtime::kSetProperty));
+ __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3);
// Extra capacity case: Check if there is extra capacity to
void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
+ // r1 : x
+ // r0 : y
+ // result : r0
+
switch (op_) {
case Token::ADD: {
Label slow, exit;
// fast path
- // Get x (y is on TOS, i.e., r0).
- __ ldr(r1, MemOperand(sp, 0 * kPointerSize));
__ orr(r2, r1, Operand(r0)); // r2 = x | y;
__ add(r0, r1, Operand(r0), SetCC); // add y optimistically
// go slow-path in case of overflow
// slow path
__ bind(&slow);
__ sub(r0, r0, Operand(r1)); // revert optimistic add
+ __ push(r1);
__ push(r0);
__ mov(r0, Operand(1)); // set number of arguments
__ InvokeBuiltin("ADD", 1, JUMP_JS);
case Token::SUB: {
Label slow, exit;
// fast path
- __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); // get x
__ orr(r2, r1, Operand(r0)); // r2 = x | y;
__ sub(r3, r1, Operand(r0), SetCC); // subtract y optimistically
// go slow-path in case of overflow
__ b(eq, &exit);
// slow path
__ bind(&slow);
+ __ push(r1);
__ push(r0);
__ mov(r0, Operand(1)); // set number of arguments
__ InvokeBuiltin("SUB", 1, JUMP_JS);
case Token::MUL: {
Label slow, exit;
- __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); // get x
// tag check
__ orr(r2, r1, Operand(r0)); // r2 = x | y;
ASSERT(kSmiTag == 0); // adjust code below
__ b(ne, &exit);
// slow case
__ bind(&slow);
+ __ push(r1);
__ push(r0);
__ mov(r0, Operand(1)); // set number of arguments
__ InvokeBuiltin("MUL", 1, JUMP_JS);
}
default: UNREACHABLE();
}
- masm->StubReturn(2);
+ __ Ret();
}
__ b(hs, &within_limit);
// Do tail-call to runtime routine.
__ push(r0);
- __ mov(r0, Operand(0)); // not counting receiver (i.e. flushed TOS)
- __ JumpToBuiltin(ExternalReference(Runtime::kStackGuard));
+ __ TailCallRuntime(ExternalReference(Runtime::kStackGuard), 1);
__ bind(&within_limit);
masm->StubReturn(1);
__ mov(r2, Operand(external_caught));
__ str(r0, MemOperand(r2));
- // Set pending exception and TOS to out of memory exception.
+ // Set pending exception and r0 to out of memory exception.
Failure* out_of_memory = Failure::OutOfMemoryException();
__ mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory)));
__ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address)));
bool do_gc,
bool do_restore) {
// r0: result parameter for PerformGC, if any
- // r4: number of arguments (C callee-saved)
+ // r4: number of arguments including receiver (C callee-saved)
// r5: pointer to builtin function (C callee-saved)
if (do_gc) {
__ Call(FUNCTION_ADDR(Runtime::PerformGC), runtime_entry); // passing r0
}
- // call C built-in
- __ mov(r0, Operand(r4)); // a0 = argc
+ // Call C built-in.
+ // r0 = argc.
+ __ mov(r0, Operand(r4));
+ // r1 = argv.
__ add(r1, fp, Operand(r4, LSL, kPointerSizeLog2));
- __ add(r1, r1, Operand(ExitFrameConstants::kPPDisplacement)); // a1 = argv
+ __ add(r1, r1, Operand(ExitFrameConstants::kPPDisplacement - kPointerSize));
// TODO(1242173): To let the GC traverse the return address of the exit
// frames, we need to know where the return address is. Right now,
void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
// Called from JavaScript; parameters are on stack as if calling JS function
- // r0: number of arguments
+ // r0: number of arguments including receiver
// r1: pointer to builtin function
// fp: frame pointer (restored after C call)
// sp: stack pointer (restored as callee's pp after C call)
// Enter C frame
// Compute parameter pointer before making changes and save it as ip register
// so that it is restored as sp register on exit, thereby popping the args.
- // ip = sp + kPointerSize*(args_len+1); // +1 for receiver
+ // ip = sp + kPointerSize*args_len;
__ add(ip, sp, Operand(r0, LSL, kPointerSizeLog2));
- __ add(ip, ip, Operand(kPointerSize));
// all JS callee-saved are saved and traversed by GC; push in reverse order:
// JS callee-saved, caller_pp, caller_fp, sp_on_exit (ip==pp), caller_pc
__ str(r3, MemOperand(ip));
// Remove constructor mark.
- __ add(sp, sp, Operand(kPointerSize));
+ __ pop();
// Restore callee-saved registers, sp, and return.
#ifdef DEBUG
// by calling the runtime system.
__ bind(&slow);
__ push(r0);
- __ mov(r0, Operand(0)); // not counting receiver
- __ JumpToBuiltin(ExternalReference(Runtime::kGetArgumentsProperty));
+ __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1);
}
}
Literal* literal = key->AsLiteral();
Handle<String> name(String::cast(*literal->handle()));
- // Loading adds a value to the stack; push the TOS to prepare.
- if (is_load) __ push(r0);
-
- // Setup the name register.
- __ mov(r2, Operand(name));
-
// Call the appropriate IC code.
if (is_load) {
+ // Setup the name register.
+ __ mov(r2, Operand(name));
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
Variable* var = ref()->expression()->AsVariableProxy()->AsVariable();
if (var != NULL) {
} else {
__ Call(ic, code_target);
}
+
} else {
+ __ pop(r0); // value
+ // Setup the name register.
+ __ mov(r2, Operand(name));
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
__ Call(ic, code_target);
}
- return;
- }
- // Access keyed property.
- ASSERT(type == Reference::KEYED);
-
- if (is_load) {
- __ push(r0); // empty tos
- // TODO(1224671): Implement inline caching for keyed loads as on ia32.
- GetPropertyStub stub;
- __ CallStub(&stub);
} else {
- SetPropertyStub stub;
- __ CallStub(&stub);
+ // Access keyed property.
+ ASSERT(type == Reference::KEYED);
+
+ if (is_load) {
+ // TODO(1224671): Implement inline caching for keyed loads as on ia32.
+ GetPropertyStub stub;
+ __ CallStub(&stub);
+
+ } else {
+ __ pop(r0); // value
+ SetPropertyStub stub;
+ __ CallStub(&stub);
+ }
}
+ __ push(r0);
}
void ArmCodeGenerator::GenericBinaryOperation(Token::Value op) {
+ // sp[0] : y
+ // sp[1] : x
+ // result : r0
+
// Stub is entered with a call: 'return address' is in lr.
switch (op) {
case Token::ADD: // fall through.
case Token::SUB: // fall through.
case Token::MUL: {
+ __ pop(r0); // r0 : y
+ __ pop(r1); // r1 : x
GenericBinaryOpStub stub(op);
__ CallStub(&stub);
break;
}
case Token::DIV: {
- __ push(r0);
- __ mov(r0, Operand(1)); // set number of arguments
+ __ mov(r0, Operand(1));
__ InvokeBuiltin("DIV", 1, CALL_JS);
break;
}
case Token::MOD: {
- __ push(r0);
- __ mov(r0, Operand(1)); // set number of arguments
+ __ mov(r0, Operand(1));
__ InvokeBuiltin("MOD", 1, CALL_JS);
break;
}
case Token::BIT_AND:
case Token::BIT_XOR: {
Label slow, exit;
+ __ pop(r0); // get y
__ pop(r1); // get x
// tag check
__ orr(r2, r1, Operand(r0)); // r2 = x | y;
case Token::SHR:
case Token::SAR: {
Label slow, exit;
- __ mov(r1, Operand(r0)); // get y
+ __ pop(r1); // get y
__ pop(r0); // get x
// tag check
__ orr(r2, r1, Operand(r0)); // r2 = x | y;
default: UNREACHABLE();
}
- // tag result and store it in TOS (r0)
+ // tag result and store it in r0
ASSERT(kSmiTag == 0); // adjust code below
__ mov(r0, Operand(r3, LSL, kSmiTagSize));
__ b(&exit);
// slow case
__ bind(&slow);
__ push(r0); // restore stack
- __ mov(r0, Operand(r1));
- __ Push(Operand(1)); // 1 argument (not counting receiver).
+ __ push(r1);
+ __ mov(r0, Operand(1)); // 1 argument (not counting receiver).
switch (op) {
case Token::SAR: __ InvokeBuiltin("SAR", 1, CALL_JS); break;
case Token::SHR: __ InvokeBuiltin("SHR", 1, CALL_JS); break;
}
case Token::COMMA:
+ __ pop(r0);
// simply discard left value
- __ add(sp, sp, Operand(kPointerSize));
+ __ pop();
break;
default:
}
-
-
void ArmCodeGenerator::SmiOperation(Token::Value op,
Handle<Object> value,
bool reversed) {
// code size is increased by ~1% (measured on a combination of
// different benchmarks).
+ // sp[0] : operand
+
ASSERT(value->IsSmi());
Label exit;
+ __ pop(r0);
switch (op) {
case Token::ADD: {
default:
if (!reversed) {
- __ Push(Operand(value));
+ __ push(r0);
+ __ mov(r0, Operand(value));
+ __ push(r0);
} else {
__ mov(ip, Operand(value));
__ push(ip);
+ __ push(r0);
}
GenericBinaryOperation(op);
break;
void ArmCodeGenerator::Comparison(Condition cc, bool strict) {
+ // sp[0] : y
+ // sp[1] : x
+ // result : cc register
+
// Strict only makes sense for equality comparisons.
ASSERT(!strict || cc == eq);
// Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
if (cc == gt || cc == le) {
cc = ReverseCondition(cc);
- __ mov(r1, Operand(r0));
+ __ pop(r1);
__ pop(r0);
} else {
+ __ pop(r0);
__ pop(r1);
}
__ orr(r2, r0, Operand(r1));
ASSERT(cc == gt || cc == ge); // remaining cases
ncr = LESS;
}
- __ Push(Operand(Smi::FromInt(ncr)));
+ __ push(r0);
+ __ mov(r0, Operand(Smi::FromInt(ncr)));
argc = 2;
}
// Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
// tagged as a small integer.
- __ Push(Operand(argc));
+ __ push(r0);
+ __ mov(r0, Operand(argc));
__ InvokeBuiltin(native, argc, CALL_JS);
__ cmp(r0, Operand(0));
__ b(&exit);
__ cmp(r1, Operand(r0));
__ bind(&exit);
- __ pop(r0); // be careful not to destroy the cc register
cc_reg_ = cc;
}
void CallFunctionStub::Generate(MacroAssembler* masm) {
Label slow;
-
- // Flush the TOS cache
- masm->push(r0);
-
// Get the function to call from the stack.
// function, receiver [, arguments]
masm->ldr(r1, MemOperand(sp, (argc_ + 1) * kPointerSize));
}
-// Call the function just below TOS on the stack with the given
-// arguments. The receiver is the TOS.
+// Call the function on the stack with the given arguments.
void ArmCodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
int position) {
// Push the arguments ("left-to-right") on the stack.
- for (int i = 0; i < args->length(); i++) Load(args->at(i));
+ for (int i = 0; i < args->length(); i++) {
+ Load(args->at(i));
+ }
// Record the position for debugging purposes.
__ RecordPosition(position);
// Restore context and pop function from the stack.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
- __ add(sp, sp, Operand(kPointerSize)); // discard
+ __ pop(); // discard the TOS
}
void ArmCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
- __ Push(Operand(pairs));
- __ Push(Operand(cp));
- __ Push(Operand(Smi::FromInt(is_eval() ? 1 : 0)));
+ __ mov(r0, Operand(pairs));
+ __ push(r0);
+ __ push(cp);
+ __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
+ __ push(r0);
__ CallRuntime(Runtime::kDeclareGlobals, 3);
-
- // Get rid of return value.
- __ pop(r0);
+ // The result is discarded.
}
// during variable resolution and must have mode DYNAMIC.
ASSERT(var->mode() == Variable::DYNAMIC);
// For now, just do a runtime call.
- __ Push(Operand(cp));
- __ Push(Operand(var->name()));
+ __ push(cp);
+ __ mov(r0, Operand(var->name()));
+ __ push(r0);
// Declaration nodes are always declared in only two modes.
ASSERT(node->mode() == Variable::VAR || node->mode() == Variable::CONST);
PropertyAttributes attr = node->mode() == Variable::VAR ? NONE : READ_ONLY;
- __ Push(Operand(Smi::FromInt(attr)));
+ __ mov(r0, Operand(Smi::FromInt(attr)));
+ __ push(r0);
// Push initial value, if any.
// Note: For variables we must not push an initial value (such as
// 'undefined') because we may have a (legal) redeclaration and we
// must not destroy the current value.
if (node->mode() == Variable::CONST) {
- __ Push(Operand(Factory::the_hole_value()));
+ __ mov(r0, Operand(Factory::the_hole_value()));
+ __ push(r0);
} else if (node->fun() != NULL) {
Load(node->fun());
} else {
- __ Push(Operand(0)); // no initial value!
+ __ mov(r0, Operand(0)); // no initial value!
+ __ push(r0);
}
__ CallRuntime(Runtime::kDeclareContextSlot, 5);
- // DeclareContextSlot pops the assigned value by accepting an
- // extra argument and returning the TOS; no need to explicitly pop
- // here.
+ __ push(r0);
+
return;
}
Load(val);
SetValue(&target);
// Get rid of the assigned value (declarations are statements).
- __ pop(r0); // Pop(no_reg);
+ __ pop();
}
}
Expression* expression = node->expression();
expression->MarkAsStatement();
Load(expression);
- __ pop(r0); // __ Pop(no_reg)
+ __ pop();
}
Label exit;
if (has_then_stm && has_else_stm) {
+ Comment cmnt(masm_, "[ IfThenElse");
Label then;
Label else_;
// if (cond)
Visit(node->else_statement());
} else if (has_then_stm) {
+ Comment cmnt(masm_, "[ IfThen");
ASSERT(!has_else_stm);
Label then;
// if (cond)
Visit(node->then_statement());
} else if (has_else_stm) {
+ Comment cmnt(masm_, "[ IfElse");
ASSERT(!has_then_stm);
Label else_;
// if (!cond)
Visit(node->else_statement());
} else {
+ Comment cmnt(masm_, "[ If");
ASSERT(!has_then_stm && !has_else_stm);
// if (cond)
LoadCondition(node->condition(), CodeGenState::LOAD, &exit, &exit, false);
void ArmCodeGenerator::CleanStack(int num_bytes) {
ASSERT(num_bytes >= 0);
if (num_bytes > 0) {
- __ add(sp, sp, Operand(num_bytes - kPointerSize));
- __ pop(r0);
+ __ add(sp, sp, Operand(num_bytes));
}
}
Comment cmnt(masm_, "[ ReturnStatement");
if (FLAG_debug_info) RecordStatementPosition(node);
Load(node->expression());
+ // Move the function result into r0.
+ __ pop(r0);
+
__ b(&function_return_);
}
__ stop("PushContext: r0 is expected to be the same as cp");
__ bind(&verified_true);
}
- __ pop(r0); // restore TOS
// Update context local.
__ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
}
} else {
__ bind(&next);
next.Unuse();
+ __ ldr(r0, MemOperand(sp, 0));
__ push(r0); // duplicate TOS
Load(clause->label());
Comparison(eq, true);
Branch(false, &next);
- __ pop(r0); // __ Pop(no_reg)
+ // Entering the case statement -> remove the switch value from the stack
+ __ pop(r0);
}
// Generate code for the body.
}
__ bind(&next);
+ // Reached the end of the case statements -> remove the switch value
+ // from the stack.
__ pop(r0); // __ Pop(no_reg)
if (default_case.is_bound()) __ b(&default_case);
// Get the object to enumerate over (converted to JSObject).
Load(node->enumerable());
+ __ pop(r0);
// Both SpiderMonkey and kjs ignore null and undefined in contrast
// to the specification. 12.6.4 mandates a call to ToObject.
__ b(hs, &jsobject);
__ bind(&primitive);
- __ Push(Operand(0));
+ __ push(r0);
+ __ mov(r0, Operand(0));
__ InvokeBuiltin("TO_OBJECT", 0, CALL_JS);
// Get the set of properties (as a FixedArray or Map).
__ push(r0); // duplicate the object being enumerated
+ __ push(r0);
__ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
// If we got a Map, we can do a fast modification check.
__ ldr(r2,
FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset));
- __ Push(Operand(r2));
- __ Push(FieldMemOperand(r2, FixedArray::kLengthOffset));
+ __ push(r0); // map
+ __ push(r2); // enum cache bridge cache
+ __ ldr(r0, FieldMemOperand(r2, FixedArray::kLengthOffset));
__ mov(r0, Operand(r0, LSL, kSmiTagSize));
- __ Push(Operand(Smi::FromInt(0)));
+ __ push(r0);
+ __ mov(r0, Operand(Smi::FromInt(0)));
+ __ push(r0);
__ b(&entry);
__ mov(r1, Operand(Smi::FromInt(0)));
__ push(r1); // insert 0 in place of Map
+ __ push(r0);
// Push the length of the array and the initial index onto the stack.
- __ Push(FieldMemOperand(r0, FixedArray::kLengthOffset));
+ __ ldr(r0, FieldMemOperand(r0, FixedArray::kLengthOffset));
__ mov(r0, Operand(r0, LSL, kSmiTagSize));
- __ Push(Operand(Smi::FromInt(0)));
+ __ push(r0);
+ __ mov(r0, Operand(Smi::FromInt(0))); // init index
+ __ push(r0);
+
__ b(&entry);
// Body.
// Next.
__ bind(node->continue_target());
__ bind(&next);
+ __ pop(r0);
__ add(r0, r0, Operand(Smi::FromInt(1)));
+ __ push(r0);
// Condition.
__ bind(&entry);
- __ ldr(ip, MemOperand(sp, 0));
- __ cmp(r0, Operand(ip));
+ // sp[0] : index
+ // sp[1] : array/enum cache length
+ // sp[2] : array or enum cache
+ // sp[3] : 0 or map
+ // sp[4] : enumerable
+ __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); // load the current count
+ __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); // load the length
+ __ cmp(r0, Operand(r1)); // compare to the array length
__ b(hs, &cleanup);
+ __ ldr(r0, MemOperand(sp, 0 * kPointerSize));
+
// Get the i'th entry of the array.
- __ ldr(r2, MemOperand(sp, kPointerSize));
+ __ ldr(r2, MemOperand(sp, 2 * kPointerSize));
__ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
__ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize));
// Get Map or 0.
- __ ldr(r2, MemOperand(sp, 2 * kPointerSize));
+ __ ldr(r2, MemOperand(sp, 3 * kPointerSize));
// Check if this (still) matches the map of the enumerable.
// If not, we have to filter the key.
- __ ldr(r1, MemOperand(sp, 3 * kPointerSize));
+ __ ldr(r1, MemOperand(sp, 4 * kPointerSize));
__ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
__ cmp(r1, Operand(r2));
__ b(eq, &end_del_check);
// Convert the entry to a string (or null if it isn't a property anymore).
- __ Push(MemOperand(sp, 4 * kPointerSize)); // push enumerable
- __ Push(Operand(r3)); // push entry
- __ Push(Operand(1));
+ __ ldr(r0, MemOperand(sp, 4 * kPointerSize)); // push enumerable
+ __ push(r0);
+ __ push(r3); // push entry
+ __ mov(r0, Operand(1));
__ InvokeBuiltin("FILTER_KEY", 1, CALL_JS);
__ mov(r3, Operand(r0));
- __ pop(r0);
// If the property has been removed while iterating, we just skip it.
__ cmp(r3, Operand(Factory::null_value()));
__ bind(&end_del_check);
// Store the entry in the 'each' expression and take another spin in the loop.
- __ Push(Operand(r3));
+ // r3: i'th entry of the enum cache (or string there of)
+ __ push(r3); // push entry
{ Reference each(this, node->each());
if (!each.is_illegal()) {
- if (each.size() > 0) __ Push(MemOperand(sp, kPointerSize * each.size()));
+ if (each.size() > 0) {
+ __ ldr(r0, MemOperand(sp, kPointerSize * each.size()));
+ __ push(r0);
+ }
SetValue(&each);
- if (each.size() > 0) __ pop(r0);
+ if (each.size() > 0) {
+ __ pop(r0); // discard the value
+ }
}
}
- __ pop(r0);
+ __ pop(); // pop the i'th entry pushed above
CheckStack(); // TODO(1222600): ignore if body contains calls.
__ jmp(&loop);
// Cleanup.
__ bind(&cleanup);
__ bind(node->break_target());
- __ add(sp, sp, Operand(4 * kPointerSize));
+ __ add(sp, sp, Operand(5 * kPointerSize));
// Exit.
__ bind(&exit);
- __ pop(r0);
break_stack_height_ -= kForInStackSize;
}
Label try_block, exit;
- __ push(r0);
__ bl(&try_block);
-
// --- Catch block ---
// Store the caught exception in the catch variable.
+ __ push(r0);
{ Reference ref(this, node->catch_var());
// Load the exception to the top of the stack.
- __ Push(MemOperand(sp, ref.size() * kPointerSize));
+ __ ldr(r0, MemOperand(sp, ref.size() * kPointerSize));
+ __ push(r0);
SetValue(&ref);
+ __ pop(r0);
}
// Remove the exception from the stack.
- __ add(sp, sp, Operand(kPointerSize));
-
- // Restore TOS register caching.
- __ pop(r0);
+ __ pop();
VisitStatements(node->catch_block()->statements());
__ b(&exit);
// Generate code for the statements in the try block.
VisitStatements(node->try_block()->statements());
+ __ pop(r0); // Discard the result.
// Stop the introduced shadowing and count the number of required unlinks.
int nof_unlinks = 0;
ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code
__ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
// Code slot popped.
- __ pop(r0); // restore TOS
if (nof_unlinks > 0) __ b(&exit);
// Generate unlink code for all used shadow labels.
for (int i = 0; i <= nof_escapes; i++) {
if (shadows[i]->is_linked()) {
- // Unlink from try chain; be careful not to destroy the TOS.
+ // Unlink from try chain;
__ bind(shadows[i]);
- bool is_return = (shadows[i]->shadowed() == &function_return_);
- if (!is_return) {
- // Break/continue case. TOS is the code slot of the handler.
- __ push(r0); // flush TOS
- }
-
// Reload sp from the top handler, because some statements that we
// break from (eg, for...in) may have left stuff on the stack.
__ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
__ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
// Code slot popped.
- if (!is_return) {
- __ pop(r0); // restore TOS
- }
-
__ b(shadows[i]->shadowed());
}
}
Label exit, unlink, try_block, finally_block;
- __ push(r0);
__ bl(&try_block);
+ __ push(r0); // save exception object on the stack
// In case of thrown exceptions, this is where we continue.
__ mov(r2, Operand(Smi::FromInt(THROWING)));
__ b(&finally_block);
}
// Set the state on the stack to FALLING.
- __ Push(Operand(Factory::undefined_value())); // fake TOS
+ __ mov(r0, Operand(Factory::undefined_value())); // fake TOS
+ __ push(r0);
__ mov(r2, Operand(Smi::FromInt(FALLING)));
if (nof_unlinks > 0) __ b(&unlink);
for (int i = 0; i <= nof_escapes; i++) {
if (shadows[i]->is_linked()) {
__ bind(shadows[i]);
- if (shadows[i]->shadowed() != &function_return_) {
+ if (shadows[i]->shadowed() == &function_return_) {
+ __ push(r0); // Materialize the return value on the stack
+ } else {
// Fake TOS for break and continue (not return).
- __ Push(Operand(Factory::undefined_value()));
+ __ mov(r0, Operand(Factory::undefined_value()));
+ __ push(r0);
}
__ mov(r2, Operand(Smi::FromInt(JUMPING + i)));
__ b(&unlink);
}
}
- // Unlink from try chain; be careful not to destroy the TOS.
+ // Unlink from try chain;
__ bind(&unlink);
+ __ pop(r0); // Store TOS in r0 across stack manipulation
// Reload sp from the top handler, because some statements that we
// break from (eg, for...in) may have left stuff on the stack.
__ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code
__ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
// Code slot popped.
-
+ __ push(r0);
// --- Finally block ---
__ bind(&finally_block);
// Push the state on the stack. If necessary move the state to a
// local variable to avoid having extra values on the stack while
// evaluating the finally block.
- __ Push(Operand(r2));
+ __ push(r2);
if (node->finally_var() != NULL) {
Reference target(this, node->finally_var());
SetValue(&target);
ASSERT(target.size() == 0); // no extra stuff on the stack
- __ pop(r0);
+ __ pop(); // remove the extra avalue that was pushed above
}
// Generate code for the statements in the finally block.
VisitStatements(node->finally_block()->statements());
- // Get the state from the stack - or the local variable - and
- // restore the TOS register.
+ // Get the state from the stack - or the local variable.
if (node->finally_var() != NULL) {
Reference target(this, node->finally_var());
GetValue(&target);
}
- __ Pop(r2);
+ __ pop(r2);
+ __ pop(r0); // Restore value or faked TOS.
// Generate code that jumps to the right destination for all used
// shadow labels.
for (int i = 0; i <= nof_escapes; i++) {
if (shadows[i]->shadowed() != &function_return_) {
Label next;
__ b(ne, &next);
- __ pop(r0); // pop faked TOS
__ b(shadows[i]->shadowed());
__ bind(&next);
} else {
__ b(ne, &exit);
// Rethrow exception.
+ __ push(r0);
__ CallRuntime(Runtime::kReThrow, 1);
// Done.
__ bind(&exit);
- __ pop(r0); // restore TOS caching.
}
Comment cmnt(masm_, "[ DebuggerStatament");
if (FLAG_debug_info) RecordStatementPosition(node);
__ CallRuntime(Runtime::kDebugBreak, 1);
+ __ push(r0);
}
ASSERT(boilerplate->IsBoilerplate());
// Push the boilerplate on the stack.
- __ Push(Operand(boilerplate));
+ __ mov(r0, Operand(boilerplate));
+ __ push(r0);
// Create a new closure.
- __ Push(Operand(cp));
+ __ push(cp);
__ CallRuntime(Runtime::kNewClosure, 2);
+ __ push(r0);
}
ASSERT(node->var()->mode() == Variable::DYNAMIC);
// For now, just do a runtime call.
- __ Push(Operand(cp));
- __ Push(Operand(node->var()->name()));
+ __ push(cp);
+ __ mov(r0, Operand(node->var()->name()));
+ __ push(r0);
switch (access()) {
case CodeGenState::UNDEFINED:
case CodeGenState::LOAD:
__ CallRuntime(Runtime::kLoadContextSlot, 2);
- // result (TOS) is the value that was loaded
+ __ push(r0);
break;
case CodeGenState::LOAD_TYPEOF_EXPR:
__ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
- // result (TOS) is the value that was loaded
+ __ push(r0);
break;
case CodeGenState::STORE:
// Storing a variable must keep the (new) value on the stack. This
// is necessary for compiling assignment expressions.
__ CallRuntime(Runtime::kStoreContextSlot, 3);
+ __ push(r0);
// result (TOS) is the value that was stored
break;
// need the split into 2 operations: declaration of the
// context slot followed by initialization.
__ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
+ __ push(r0);
break;
}
case CodeGenState::LOAD: // fall through
case CodeGenState::LOAD_TYPEOF_EXPR:
// Special handling for locals allocated in registers.
- __ Push(SlotOperand(node, r2));
+ __ ldr(r0, SlotOperand(node, r2));
+ __ push(r0);
if (node->var()->mode() == Variable::CONST) {
// Const slots may contain 'the hole' value (the constant hasn't
// been initialized yet) which needs to be converted into the
// 'undefined' value.
Comment cmnt(masm_, "[ Unhole const");
+ __ pop(r0);
__ cmp(r0, Operand(Factory::the_hole_value()));
__ mov(r0, Operand(Factory::undefined_value()), LeaveCC, eq);
+ __ push(r0);
}
break;
__ b(ne, &L);
// We must execute the store.
// r2 may be loaded with context; used below in RecordWrite.
+ __ ldr(r0, MemOperand(sp, 0));
__ str(r0, SlotOperand(node, r2));
if (node->type() == Slot::CONTEXT) {
// Skip write barrier if the written value is a smi.
// initialize consts to 'the hole' value and by doing so, end
// up calling this code.
// r2 may be loaded with context; used below in RecordWrite.
+ __ pop(r0);
__ str(r0, SlotOperand(node, r2));
if (node->type() == Slot::CONTEXT) {
// Skip write barrier if the written value is a smi.
__ RecordWrite(r2, r3, r1);
__ bind(&exit);
}
+ __ push(r0);
break;
}
}
void ArmCodeGenerator::VisitLiteral(Literal* node) {
Comment cmnt(masm_, "[ Literal");
- __ Push(Operand(node->handle()));
+ __ mov(r0, Operand(node->handle()));
+ __ push(r0);
}
// If the entry is undefined we call the runtime system to computed
// the literal.
- __ Push(Operand(r1)); // literal array (0)
- __ Push(Operand(Smi::FromInt(node->literal_index()))); // literal index (1)
- __ Push(Operand(node->pattern())); // RegExp pattern (2)
- __ Push(Operand(node->flags())); // RegExp flags (3)
+ __ push(r1); // literal array (0)
+ __ mov(r0, Operand(Smi::FromInt(node->literal_index())));
+ __ push(r0); // literal index (1)
+ __ mov(r0, Operand(node->pattern())); // RegExp pattern (2)
+ __ push(r0);
+ __ mov(r0, Operand(node->flags())); // RegExp flags (3)
+ __ push(r0);
__ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
- __ Pop(r2);
- __ bind(&done);
+ __ mov(r2, Operand(r0));
+ __ bind(&done);
// Push the literal.
- __ Push(Operand(r2));
+ __ push(r2);
}
// the literal.
// Literal array (0).
- __ Push(Operand(r1));
+ __ push(r1);
// Literal index (1).
- __ Push(Operand(Smi::FromInt(node_->literal_index())));
+ __ mov(r0, Operand(Smi::FromInt(node_->literal_index())));
+ __ push(r0);
// Constant properties (2).
- __ Push(Operand(node_->constant_properties()));
+ __ mov(r0, Operand(node_->constant_properties()));
+ __ push(r0);
__ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3);
- __ Pop(r2);
+ __ mov(r2, Operand(r0));
}
__ bind(deferred->exit());
// Push the object literal boilerplate.
- __ Push(Operand(r2));
+ __ push(r2);
+
// Clone the boilerplate object.
__ CallRuntime(Runtime::kCloneObjectLiteralBoilerplate, 1);
+ __ push(r0); // save the result
+ // r0: cloned object literal
for (int i = 0; i < node->properties()->length(); i++) {
ObjectLiteral::Property* property = node->properties()->at(i);
case ObjectLiteral::Property::CONSTANT: break;
case ObjectLiteral::Property::COMPUTED: // fall through
case ObjectLiteral::Property::PROTOTYPE: {
- // Save a copy of the resulting object on the stack.
- __ push(r0);
+ __ push(r0); // dup the result
Load(key);
Load(value);
__ CallRuntime(Runtime::kSetProperty, 3);
- // Restore the result object from the stack.
- __ pop(r0);
+ // restore r0
+ __ ldr(r0, MemOperand(sp, 0));
break;
}
case ObjectLiteral::Property::SETTER: {
__ push(r0);
Load(key);
- __ Push(Operand(Smi::FromInt(1)));
+ __ mov(r0, Operand(Smi::FromInt(1)));
+ __ push(r0);
Load(value);
__ CallRuntime(Runtime::kDefineAccessor, 4);
- __ pop(r0);
+ __ ldr(r0, MemOperand(sp, 0));
break;
}
case ObjectLiteral::Property::GETTER: {
__ push(r0);
Load(key);
- __ Push(Operand(Smi::FromInt(0)));
+ __ mov(r0, Operand(Smi::FromInt(0)));
+ __ push(r0);
Load(value);
__ CallRuntime(Runtime::kDefineAccessor, 4);
- __ pop(r0);
+ __ ldr(r0, MemOperand(sp, 0));
break;
}
}
if (value->AsLiteral() == NULL) {
// The property must be set by generated code.
Load(value);
+ __ pop(r0);
// Fetch the object literal
__ ldr(r1, MemOperand(sp, 0));
// Update the write barrier for the array address.
__ mov(r3, Operand(offset));
__ RecordWrite(r1, r3, r2);
-
- __ pop(r0);
}
}
}
void ArmCodeGenerator::VisitAssignment(Assignment* node) {
Comment cmnt(masm_, "[ Assignment");
-
if (FLAG_debug_info) RecordStatementPosition(node);
+
Reference target(this, node->target());
if (target.is_illegal()) return;
Literal* literal = node->value()->AsLiteral();
if (literal != NULL && literal->handle()->IsSmi()) {
SmiOperation(node->binary_op(), literal->handle(), false);
+ __ push(r0);
+
} else {
Load(node->value());
GenericBinaryOperation(node->binary_op());
+ __ push(r0);
}
}
(var->mode() == Variable::CONST) &&
node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) {
// Assignment ignored - leave the value on the stack.
+
} else {
__ RecordPosition(node->position());
if (node->op() == Token::INIT_CONST) {
Load(node->exception());
__ RecordPosition(node->position());
__ CallRuntime(Runtime::kThrow, 1);
+ __ push(r0);
}
if (is_referenced()) {
__ RecordPosition(node->position());
AccessReferenceProperty(node->key(), access());
+
} else {
// All stores are through references.
ASSERT(access() != CodeGenState::STORE);
// ----------------------------------
// Push the name of the function and the receiver onto the stack.
- __ Push(Operand(var->name()));
+ __ mov(r0, Operand(var->name()));
+ __ push(r0);
LoadGlobal();
// Load the arguments.
for (int i = 0; i < args->length(); i++) Load(args->at(i));
- __ Push(Operand(args->length()));
// Setup the receiver register and call the IC initialization code.
Handle<Code> stub = ComputeCallInitialize(args->length());
- __ ldr(r1, GlobalObject());
__ RecordPosition(node->position());
__ Call(stub, code_target_context);
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
-
// Remove the function from the stack.
- __ add(sp, sp, Operand(kPointerSize));
+ __ pop();
+ __ push(r0);
} else if (var != NULL && var->slot() != NULL &&
var->slot()->type() == Slot::LOOKUP) {
// ----------------------------------
// Load the function
- __ Push(Operand(cp));
- __ Push(Operand(var->name()));
+ __ push(cp);
+ __ mov(r0, Operand(var->name()));
+ __ push(r0);
__ CallRuntime(Runtime::kLoadContextSlot, 2);
// r0: slot value; r1: receiver
// Load the receiver.
- __ push(r0);
- __ mov(r0, Operand(r1));
+ __ push(r0); // function
+ __ push(r1); // receiver
// Call the function.
CallWithArguments(args, node->position());
+ __ push(r0);
} else if (property != NULL) {
// Check if the key is a literal string.
// ------------------------------------------------------------------
// Push the name of the function and the receiver onto the stack.
- __ Push(Operand(literal->handle()));
+ __ mov(r0, Operand(literal->handle()));
+ __ push(r0);
Load(property->obj());
// Load the arguments.
for (int i = 0; i < args->length(); i++) Load(args->at(i));
- __ Push(Operand(args->length()));
// Set the receiver register and call the IC initialization code.
Handle<Code> stub = ComputeCallInitialize(args->length());
- __ ldr(r1, MemOperand(sp, args->length() * kPointerSize));
__ RecordPosition(node->position());
__ Call(stub, code_target);
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
// Remove the function from the stack.
- __ add(sp, sp, Operand(kPointerSize));
+ __ pop();
+
+ __ push(r0); // push after get rid of function from the stack
} else {
// -------------------------------------------
// Load the function to call from the property through a reference.
Reference ref(this, property);
- GetValue(&ref);
+ GetValue(&ref); // receiver
// Pass receiver to called function.
- __ Push(MemOperand(sp, ref.size() * kPointerSize));
-
+ __ ldr(r0, MemOperand(sp, ref.size() * kPointerSize));
+ __ push(r0);
// Call the function.
CallWithArguments(args, node->position());
+ __ push(r0);
}
} else {
// Load the function.
Load(function);
-
// Pass the global object as the receiver.
LoadGlobal();
-
// Call the function.
CallWithArguments(args, node->position());
+ __ push(r0);
}
}
ZoneList<Expression*>* args = node->arguments();
for (int i = 0; i < args->length(); i++) Load(args->at(i));
- // Push the number of arguments.
- __ Push(Operand(args->length()));
+ // r0: the number of arguments.
+ __ mov(r0, Operand(args->length()));
// Call the construct call builtin that handles allocation and
// constructor invocation.
__ RecordPosition(position);
__ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)),
js_construct_call);
- __ add(sp, sp, Operand(kPointerSize)); // discard
+
+ // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)).
+ __ str(r0, MemOperand(sp, 0 * kPointerSize));
}
void ArmCodeGenerator::GenerateSetThisFunction(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
Load(args->at(0));
+ __ ldr(r0, MemOperand(sp, 0));
__ str(r0, MemOperand(pp, JavaScriptFrameConstants::kFunctionOffset));
}
void ArmCodeGenerator::GenerateGetThisFunction(ZoneList<Expression*>* args) {
ASSERT(args->length() == 0);
- __ Push(MemOperand(pp, JavaScriptFrameConstants::kFunctionOffset));
+ __ ldr(r0, MemOperand(pp, JavaScriptFrameConstants::kFunctionOffset));
+ __ push(r0);
}
void ArmCodeGenerator::GenerateSetThis(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
Load(args->at(0));
+ __ ldr(r0, MemOperand(sp, 0));
__ str(r0, MemOperand(pp, JavaScriptFrameConstants::kReceiverOffset));
}
void ArmCodeGenerator::GenerateSetArgumentsLength(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
Load(args->at(0));
+ __ pop(r0);
__ mov(r0, Operand(r0, LSR, kSmiTagSize));
__ str(r0, MemOperand(fp, JavaScriptFrameConstants::kArgsLengthOffset));
- __ mov(r0, Operand(Smi::FromInt(0)));
+ __ mov(r0, Operand(Smi::FromInt(0))); // return a meaningful value
+ __ push(r0);
}
void ArmCodeGenerator::GenerateGetArgumentsLength(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
- __ push(r0);
__ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kArgsLengthOffset));
__ mov(r0, Operand(r0, LSL, kSmiTagSize));
+ __ push(r0);
}
ASSERT(args->length() == 1);
Label leave;
Load(args->at(0));
- // r0 contains object.
- // if (object->IsSmi()) return TOS.
+ __ pop(r0); // r0 contains object.
+ // if (object->IsSmi()) return the object.
__ tst(r0, Operand(kSmiTagMask));
__ b(eq, &leave);
// It is a heap object - get map.
__ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
__ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
- // if (!object->IsJSValue()) return TOS.
+ // if (!object->IsJSValue()) return the object.
__ cmp(r1, Operand(JS_VALUE_TYPE));
__ b(ne, &leave);
// Load the value.
__ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset));
__ bind(&leave);
+ __ push(r0);
}
Label leave;
Load(args->at(0)); // Load the object.
Load(args->at(1)); // Load the value.
- __ pop(r1);
- // r0 contains value.
- // r1 contains object.
+ __ pop(r0); // r0 contains value
+ __ pop(r1); // r1 contains object
// if (object->IsSmi()) return object.
__ tst(r1, Operand(kSmiTagMask));
__ b(eq, &leave);
__ RecordWrite(r1, r2, r3);
// Leave.
__ bind(&leave);
+ __ push(r0);
}
// r0 = number of arguments (smi)
ASSERT(args->length() == 1);
Load(args->at(0));
+ __ pop(r0);
__ mov(r0, Operand(r0, LSR, kSmiTagSize));
// r1 = new function (previously written to stack)
void ArmCodeGenerator::GenerateSetArgument(ZoneList<Expression*>* args) {
ASSERT(args->length() == 3);
- // r1 = args[i]
+ // r0 = args[i]; r1 = i
Comment cmnt(masm_, "[ GenerateSetArgument");
- Load(args->at(1));
- __ mov(r1, Operand(r0));
- // r0 = i
- Load(args->at(0));
+ Load(args->at(1)); // args[i] (value)
+ Load(args->at(0)); // i
+ __ pop(r1); // i
+ __ pop(r0); // value
#if defined(DEBUG)
{ Label L;
- __ tst(r0, Operand(kSmiTagMask));
+ __ tst(r1, Operand(kSmiTagMask));
__ b(eq, &L);
__ stop("SMI expected");
__ bind(&L);
}
#endif // defined(DEBUG)
__ add(r2, pp, Operand(JavaScriptFrameConstants::kParam0Offset));
- __ str(r1,
- MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize, NegOffset));
- __ pop(r0);
+ __ str(r0,
+ MemOperand(r2, r1, LSL, kPointerSizeLog2 - kSmiTagSize, NegOffset));
+ __ push(r0);
}
void ArmCodeGenerator::GenerateSquashFrame(ZoneList<Expression*>* args) {
ASSERT(args->length() == 2);
- // Load r1 with old number of arguments, r0 with new number, r1 > r0.
- Load(args->at(0));
- __ mov(r1, Operand(r0, LSR, kSmiTagSize));
- Load(args->at(1));
+ Load(args->at(0)); // old number of arguments
+ Load(args->at(1)); // new number of arguments, r1 > r0
+ __ pop(r0);
__ mov(r0, Operand(r0, LSR, kSmiTagSize));
+ __ pop(r1);
+ __ mov(r1, Operand(r1, LSR, kSmiTagSize));
// r1 = number of words to move stack.
__ sub(r1, r1, Operand(r0));
// r2 is source.
// Move down stack pointer esp.
__ mov(sp, Operand(r1));
- // Balance stack and put something GC-able in r0.
- __ pop(r0);
+ // Put something GC-able in r0.
+ __ mov(r0, Operand(Smi::FromInt(0)));
+ __ push(r0);
}
void ArmCodeGenerator::GenerateExpandFrame(ZoneList<Expression*>* args) {
ASSERT(args->length() == 2);
- // Load r1 with new number of arguments, r0 with old number (as Smi), r1 > r0.
Load(args->at(1));
- __ mov(r1, Operand(r0, LSR, kSmiTagSize));
Load(args->at(0));
+ __ pop(r0); // new number of arguments
+ __ pop(r1); // old number of arguments, r1 > r0
+ __ mov(r1, Operand(r1, LSR, kSmiTagSize));
+
// r1 = number of words to move stack.
__ sub(r1, r1, Operand(r0, LSR, kSmiTagSize));
Label end_of_expand_frame;
__ ldr(ip, MemOperand(ip));
__ cmp(r2, Operand(ip));
__ b(gt, ¬_too_big);
- __ pop(r0);
__ mov(r0, Operand(Factory::false_value()));
__ b(&end_of_expand_frame);
__ bind(¬_too_big);
__ cmp(r3, Operand(r0));
__ b(ne, &move);
- // Balance stack and put success value in top of stack
- __ pop(r0);
+ // Put success value in top of stack
__ mov(r0, Operand(Factory::true_value()));
__ bind(&end_of_expand_frame);
+ __ push(r0);
}
void ArmCodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
Load(args->at(0));
- __ tst(r0, Operand(kSmiTagMask));
__ pop(r0);
+ __ tst(r0, Operand(kSmiTagMask));
cc_reg_ = eq;
}
// It is not yet implemented on ARM, so it always goes to the slow case.
void ArmCodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
ASSERT(args->length() == 2);
- __ push(r0);
__ mov(r0, Operand(Factory::undefined_value()));
+ __ push(r0);
}
void ArmCodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
ASSERT(args->length() == 0);
- // Flush the TOS cache and seed the result with the formal
- // parameters count, which will be used in case no arguments adaptor
- // frame is found below the current frame.
- __ push(r0);
+ // Seed the result with the formal parameters count, which will be used
+ // in case no arguments adaptor frame is found below the current frame.
__ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
// Call the shared stub to get to the arguments.length.
ArgumentsAccessStub stub(true);
__ CallStub(&stub);
+ __ push(r0);
}
// Load the key onto the stack and set register r1 to the formal
// parameters count for the currently executing function.
Load(args->at(0));
+ __ pop(r0);
__ mov(r1, Operand(Smi::FromInt(scope_->num_parameters())));
// Call the shared stub to get to arguments[key].
ArgumentsAccessStub stub(false);
__ CallStub(&stub);
+ __ push(r0);
}
void ArmCodeGenerator::GenerateShiftDownAndTailCall(
ZoneList<Expression*>* args) {
- // r0 = number of arguments
- ASSERT(args->length() == 1);
- Load(args->at(0));
- __ mov(r0, Operand(r0, LSR, kSmiTagSize));
-
- // Get the 'this' function and exit the frame without returning.
- __ ldr(r1, MemOperand(pp, JavaScriptFrameConstants::kFunctionOffset));
- ExitJSFrame(DO_NOT_RETURN);
- // return address in lr
-
- // Move arguments one element down the stack.
- Label move;
- Label moved;
- __ sub(r2, r0, Operand(0), SetCC);
- __ b(eq, &moved);
- __ bind(&move);
- __ sub(ip, r2, Operand(1));
- __ ldr(r3, MemOperand(sp, ip, LSL, kPointerSizeLog2));
- __ str(r3, MemOperand(sp, r2, LSL, kPointerSizeLog2));
- __ sub(r2, r2, Operand(1), SetCC);
- __ b(ne, &move);
- __ bind(&moved);
-
- // Remove the TOS (copy of last argument)
- __ add(sp, sp, Operand(kPointerSize));
-
- // Jump (tail-call) to the function in register r1.
- __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
- __ ldr(r1, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
- __ ldr(r1, FieldMemOperand(r1, SharedFunctionInfo::kCodeOffset));
- __ add(pc, r1, Operand(Code::kHeaderSize - kHeapObjectTag));
- return;
+ // r0 = number of arguments
+ ASSERT(args->length() == 1);
+ Load(args->at(0));
+ __ pop(r0);
+ __ mov(r0, Operand(r0, LSR, kSmiTagSize));
+
+ // Get the 'this' function and exit the frame without returning.
+ __ ldr(r1, MemOperand(pp, JavaScriptFrameConstants::kFunctionOffset));
+ ExitJSFrame(DO_NOT_RETURN);
+ // return address in lr
+
+ // Move arguments one element down the stack.
+ Label move;
+ Label moved;
+ __ sub(r2, r0, Operand(0), SetCC);
+ __ b(eq, &moved);
+ __ bind(&move);
+ __ sub(ip, r2, Operand(1));
+ __ ldr(r3, MemOperand(sp, ip, LSL, kPointerSizeLog2));
+ __ str(r3, MemOperand(sp, r2, LSL, kPointerSizeLog2));
+ __ sub(r2, r2, Operand(1), SetCC);
+ __ b(ne, &move);
+ __ bind(&moved);
+
+ // Remove the TOS (copy of last argument)
+ __ pop();
+
+ // Jump (tail-call) to the function in register r1.
+ __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
+ __ ldr(r1, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
+ __ ldr(r1, FieldMemOperand(r1, SharedFunctionInfo::kCodeOffset));
+ __ add(pc, r1, Operand(Code::kHeaderSize - kHeapObjectTag));
+
+ return;
}
Comment cmnt(masm_, "[ CallRuntime");
Runtime::Function* function = node->function();
- if (function == NULL) {
+ if (function != NULL) {
+ // Push the arguments ("left-to-right").
+ for (int i = 0; i < args->length(); i++) Load(args->at(i));
+
+ // Call the C runtime function.
+ __ CallRuntime(function, args->length());
+ __ push(r0);
+
+ } else {
// Prepare stack for calling JS runtime function.
- __ Push(Operand(node->name()));
+ __ mov(r0, Operand(node->name()));
+ __ push(r0);
// Push the builtins object found in the current global object.
__ ldr(r1, GlobalObject());
- __ Push(FieldMemOperand(r1, GlobalObject::kBuiltinsOffset));
- }
+ __ ldr(r0, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset));
+ __ push(r0);
- // Push the arguments ("left-to-right").
- for (int i = 0; i < args->length(); i++) Load(args->at(i));
+ for (int i = 0; i < args->length(); i++) Load(args->at(i));
- if (function != NULL) {
- // Call the C runtime function.
- __ CallRuntime(function, args->length());
- } else {
// Call the JS runtime function.
- __ Push(Operand(args->length()));
- __ ldr(r1, MemOperand(sp, args->length() * kPointerSize));
Handle<Code> stub = ComputeCallInitialize(args->length());
__ Call(stub, code_target);
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
- __ add(sp, sp, Operand(kPointerSize));
+ __ pop();
+ __ push(r0);
}
}
} else if (op == Token::DELETE) {
Property* property = node->expression()->AsProperty();
+ Variable* variable = node->expression()->AsVariableProxy()->AsVariable();
if (property != NULL) {
Load(property->obj());
Load(property->key());
- __ Push(Operand(1)); // not counting receiver
+ __ mov(r0, Operand(1)); // not counting receiver
__ InvokeBuiltin("DELETE", 1, CALL_JS);
- return;
- }
- Variable* variable = node->expression()->AsVariableProxy()->AsVariable();
- if (variable != NULL) {
+ } else if (variable != NULL) {
Slot* slot = variable->slot();
if (variable->is_global()) {
LoadGlobal();
- __ Push(Operand(variable->name()));
- __ Push(Operand(1)); // not counting receiver
+ __ mov(r0, Operand(variable->name()));
+ __ push(r0);
+ __ mov(r0, Operand(1)); // not counting receiver
__ InvokeBuiltin("DELETE", 1, CALL_JS);
- return;
} else if (slot != NULL && slot->type() == Slot::LOOKUP) {
// lookup the context holding the named variable
- __ Push(Operand(cp));
- __ Push(Operand(variable->name()));
+ __ push(cp);
+ __ mov(r0, Operand(variable->name()));
+ __ push(r0);
__ CallRuntime(Runtime::kLookupContext, 2);
// r0: context
- __ Push(Operand(variable->name()));
- __ Push(Operand(1)); // not counting receiver
+ __ push(r0);
+ __ mov(r0, Operand(variable->name()));
+ __ push(r0);
+ __ mov(r0, Operand(1)); // not counting receiver
__ InvokeBuiltin("DELETE", 1, CALL_JS);
- return;
- }
- // Default: Result of deleting non-global, not dynamically
- // introduced variables is false.
- __ Push(Operand(Factory::false_value()));
+ } else {
+ // Default: Result of deleting non-global, not dynamically
+ // introduced variables is false.
+ __ mov(r0, Operand(Factory::false_value()));
+ }
} else {
// Default: Result of deleting expressions is true.
Load(node->expression()); // may have side-effects
+ __ pop();
__ mov(r0, Operand(Factory::true_value()));
}
+ __ push(r0);
} else if (op == Token::TYPEOF) {
// Special case for loading the typeof expression; see comment on
// LoadTypeofExpression().
LoadTypeofExpression(node->expression());
__ CallRuntime(Runtime::kTypeof, 1);
+ __ push(r0); // r0 has result
} else {
Load(node->expression());
+ __ pop(r0);
switch (op) {
case Token::NOT:
case Token::DELETE:
__ tst(r0, Operand(kSmiTagMask));
__ b(eq, &smi_label);
- __ Push(Operand(0)); // not counting receiver
+ __ push(r0);
+ __ mov(r0, Operand(0)); // not counting receiver
__ InvokeBuiltin("BIT_NOT", 0, CALL_JS);
__ b(&continue_label);
break;
case Token::ADD:
- __ Push(Operand(0)); // not counting receiver
+ __ push(r0);
+ __ mov(r0, Operand(0)); // not counting receiver
__ InvokeBuiltin("TO_NUMBER", 0, CALL_JS);
break;
default:
UNREACHABLE();
}
+ __ push(r0); // r0 has result
}
}
bool is_const = (var != NULL && var->mode() == Variable::CONST);
// Postfix: Make room for the result.
- if (is_postfix) __ Push(Operand(0));
+ if (is_postfix) {
+ __ mov(r0, Operand(0));
+ __ push(r0);
+ }
{ Reference target(this, node->expression());
if (target.is_illegal()) return;
GetValue(&target);
+ __ pop(r0);
Label slow, exit;
// Store the new value in the target if not const.
__ bind(&exit);
+ __ push(r0);
if (!is_const) SetValue(&target);
}
} else {
Label pop_and_continue, exit;
+ __ ldr(r0, MemOperand(sp, 0)); // dup the stack top
+ __ push(r0);
// Avoid popping the result if it converts to 'false' using the
// standard ToBoolean() conversion as described in ECMA-262,
// section 9.2, page 30.
- ToBoolean(r0, &pop_and_continue, &exit);
+ ToBoolean(&pop_and_continue, &exit);
Branch(false, &exit);
// Pop the result of evaluating the first part.
} else {
Label pop_and_continue, exit;
+ __ ldr(r0, MemOperand(sp, 0));
+ __ push(r0);
// Avoid popping the result if it converts to 'true' using the
// standard ToBoolean() conversion as described in ECMA-262,
// section 9.2, page 30.
- ToBoolean(r0, &exit, &pop_and_continue);
+ ToBoolean(&exit, &pop_and_continue);
Branch(true, &exit);
// Pop the result of evaluating the first part.
Load(node->right());
GenericBinaryOperation(node->op());
}
+ __ push(r0);
}
}
void ArmCodeGenerator::VisitThisFunction(ThisFunction* node) {
- __ Push(FunctionOperand());
+ __ ldr(r0, FunctionOperand());
+ __ push(r0);
}
if (left_is_null || right_is_null) {
Load(left_is_null ? right : left);
Label exit, undetectable;
+ __ pop(r0);
__ cmp(r0, Operand(Factory::null_value()));
// The 'null' value is only equal to 'undefined' if using
__ tst(r0, Operand(kSmiTagMask));
__ b(ne, &undetectable);
- __ pop(r0);
__ b(false_target());
__ bind(&undetectable);
}
__ bind(&exit);
- __ pop(r0);
cc_reg_ = eq;
return;
right->AsLiteral()->handle()->IsString())) {
Handle<String> check(String::cast(*right->AsLiteral()->handle()));
- // Load the operand, move it to register r1, and restore TOS.
+ // Load the operand, move it to register r1.
LoadTypeofExpression(operation->expression());
- __ mov(r1, Operand(r0));
- __ pop(r0);
+ __ pop(r1);
if (check->Equals(Heap::number_symbol())) {
__ tst(r1, Operand(kSmiTagMask));
break;
case Token::IN:
- __ Push(Operand(1)); // not counting receiver
+ __ mov(r0, Operand(1)); // not counting receiver
__ InvokeBuiltin("IN", 1, CALL_JS);
+ __ push(r0);
break;
case Token::INSTANCEOF:
- __ Push(Operand(1)); // not counting receiver
+ __ mov(r0, Operand(1)); // not counting receiver
__ InvokeBuiltin("INSTANCE_OF", 1, CALL_JS);
+ __ push(r0);
break;
default:
DECLARE_bool(debug_info);
DECLARE_bool(debug_code);
+#ifdef ENABLE_DISASSEMBLER
+DEFINE_bool(print_code, false, "print generated code");
+#endif
+
#ifdef DEBUG
DECLARE_bool(gc_greedy);
DEFINE_bool(trace_codegen, false,
"print name of functions for which code is generated");
-DEFINE_bool(print_code, false, "print generated code");
DEFINE_bool(print_builtin_code, false, "print generated code for builtins");
DEFINE_bool(print_source, false, "pretty print source code");
DEFINE_bool(print_builtin_source, false,
Handle<Code> Ia32CodeGenerator::MakeCode(FunctionLiteral* flit,
Handle<Script> script,
bool is_eval) {
+#ifdef ENABLE_DISASSEMBLER
+ bool print_code = FLAG_print_code && !Bootstrapper::IsActive();
+#endif
+
#ifdef DEBUG
bool print_source = false;
bool print_ast = false;
- bool print_code = false;
const char* ftype;
if (Bootstrapper::IsActive()) {
} else {
print_source = FLAG_print_source;
print_ast = FLAG_print_ast;
- print_code = FLAG_print_code;
ftype = "user-defined";
}
// Add unresolved entries in the code to the fixup list.
Bootstrapper::AddFixup(*code, cgen.masm());
-#ifdef DEBUG
+#ifdef ENABLE_DISASSEMBLER
if (print_code) {
// Print the source code if available.
if (!script->IsUndefined() && !script->source()->IsUndefined()) {
PrintF("\n\n");
}
PrintF("--- Code ---\n");
- code->Print();
+ code->Disassemble();
}
-#endif // DEBUG
+#endif // ENABLE_DISASSEMBLER
return code;
}
// by calling the runtime system.
if (!is_length_) {
__ bind(&slow);
- __ Set(eax, Immediate(0)); // not counting receiver
- __ JumpToBuiltin(ExternalReference(Runtime::kGetArgumentsProperty));
+ __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1);
}
}
__ push(eax);
// Do tail-call to runtime routine.
- __ Set(eax, Immediate(0)); // not counting receiver
- __ JumpToBuiltin(ExternalReference(Runtime::kStackGuard));
+ __ TailCallRuntime(ExternalReference(Runtime::kStackGuard), 1);
}
// ebx: pointer to C function (C callee-saved)
// ebp: frame pointer (restored after C call)
// esp: stack pointer (restored after C call)
- // edi: number of arguments (C callee-saved)
+ // edi: number of arguments including receiver (C callee-saved)
if (do_gc) {
__ mov(Operand(esp, 0 * kPointerSize), eax); // Result.
}
// Call C function.
- __ lea(eax,
- Operand(ebp, edi, times_4, StandardFrameConstants::kCallerSPOffset));
+ __ lea(eax, Operand(ebp,
+ edi,
+ times_4,
+ StandardFrameConstants::kCallerSPOffset - kPointerSize));
__ mov(Operand(esp, 0 * kPointerSize), edi); // argc.
__ mov(Operand(esp, 1 * kPointerSize), eax); // argv.
__ call(Operand(ebx));
// Pop arguments from caller's stack and return.
__ pop(ebx); // Ok to clobber ebx - function pointer not needed anymore.
- __ lea(esp, Operand(esp, ecx, times_4, +1 * kPointerSize)); // +1 ~ receiver.
+ __ lea(esp, Operand(esp, ecx, times_4, 0));
__ push(ebx);
__ ret(0);
void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
- // eax: number of arguments
+ // eax: number of arguments including receiver
// ebx: pointer to C function (C callee-saved)
// ebp: frame pointer (restored after C call)
// esp: stack pointer (restored after C call)
// ebx: pointer to builtin function (C callee-saved)
// ebp: frame pointer (restored after C call)
// esp: stack pointer (restored after C call)
- // edi: number of arguments (C callee-saved)
+ // edi: number of arguments including receiver (C callee-saved)
Label entry;
__ bind(&entry);
void RuntimeStub::Generate(MacroAssembler* masm) {
- masm->TailCallRuntime(Runtime::FunctionForId((Runtime::FunctionId)id_));
+ masm->TailCallRuntime(ExternalReference(id_), num_arguments_);
}
// RuntimeStub models code stubs calling entrypoints in the Runtime class.
class RuntimeStub : public CodeStub {
public:
- explicit RuntimeStub(Runtime::FunctionId id) : id_(id) { }
+ explicit RuntimeStub(Runtime::FunctionId id, int num_arguments)
+ : id_(id), num_arguments_(num_arguments) { }
void Generate(MacroAssembler* masm);
+ // Disassembler support. It is useful to be able to print the name
+ // of the runtime function called through this stub.
+ static const char* GetNameFromMinorKey(int minor_key) {
+ return Runtime::FunctionForId(IdField::decode(minor_key))->stub_name;
+ }
+
private:
Runtime::FunctionId id_;
+ int num_arguments_;
+
+ class ArgumentField: public BitField<int, 0, 16> {};
+ class IdField: public BitField<Runtime::FunctionId, 16, kMinorBits - 16> {};
Major MajorKey() { return Runtime; }
- int MinorKey() { return id_; }
+ int MinorKey() {
+ return IdField::encode(id_) | ArgumentField::encode(num_arguments_);
+ }
const char* GetName();
function LocalTimeOffset() {
if (IS_UNDEFINED(local_time_offset)) {
- local_time_offset = %DateLocalTimeOffset(0);
+ local_time_offset = %DateLocalTimeOffset();
}
return local_time_offset;
};
%SetCode($Date, function(year, month, date, hours, minutes, seconds, ms) {
- if (%IsConstructCall(this)) {
+ if (%IsConstructCall()) {
// ECMA 262 - 15.9.3
var argc = %_ArgumentsLength();
if (argc == 0) {
- %_SetValueOf(this, %DateCurrentTime(argc));
+ %_SetValueOf(this, %DateCurrentTime());
return;
}
if (argc == 1) {
// Mozilla-specific extension. Returns the number of milliseconds
// elapsed since 1 January 1970 00:00:00 UTC.
function DateNow() {
- return %DateCurrentTime(0);
+ return %DateCurrentTime();
};
};
Debug.Break = function(f) {
- %Break(0);
+ %Break();
};
Debug.breakLocations = function(f) {
Debug.clearStepping = function() {
- %ClearStepping(0);
+ %ClearStepping();
}
Debug.setBreakOnException = function() {
// scanning the heap.
Debug.scripts = function() {
// Collect all scripts in the heap.
- return %DebugGetLoadedScripts(0);
+ return %DebugGetLoadedScripts();
}
function MakeExecutionState(break_id) {
}
// Collect all scripts in the heap.
- var scripts = %DebugGetLoadedScripts(0);
+ var scripts = %DebugGetLoadedScripts();
response.body = [];
DebugCommandProcessor.prototype.systemBreak = function(cmd, args) {
- return %SystemBreak(0);
+ return %SystemBreak();
};
Object* Debug::Break(Arguments args) {
HandleScope scope;
- ASSERT(args.length() == 1);
+ ASSERT(args.length() == 0);
// Get the top-most JavaScript frame.
JavaScriptFrameIterator it;
// Just continue if breaks are disabled or debugger cannot be loaded.
if (disable_break() || !Load()) {
SetAfterBreakTarget(frame);
- return args[0];
+ return Heap::undefined_value();
}
SaveBreakFrame save;
// Install jump to the call address which was overwritten.
SetAfterBreakTarget(frame);
- return args[0];
+ return Heap::undefined_value();
}
#include "v8.h"
#include "code-stubs.h"
+#include "codegen.h"
#include "debug.h"
#include "disasm.h"
#include "disassembler.h"
out.AddFormatted("argc = %d)", minor_key);
break;
case CodeStub::Runtime: {
- Runtime::FunctionId id =
- static_cast<Runtime::FunctionId>(minor_key);
- out.AddFormatted("%s)", Runtime::FunctionForId(id)->name);
+ const char* name =
+ RuntimeStub::GetNameFromMinorKey(minor_key);
+ out.AddFormatted("%s)", name);
break;
}
default:
map->set_needs_access_check();
}
- // If the function template info specifies a lookup handler the
- // initial_map must have set the bit has_special_lookup.
- if (obj->lookup_callback()->IsProxy()) {
- ASSERT(!map->has_special_lookup());
- map->set_special_lookup();
- }
-
// Set interceptor information in the map.
if (!obj->named_property_handler()->IsUndefined()) {
map->set_has_named_interceptor();
kR9Available
<< 9 | // r9 v6
1 << 10 | // r10 v7 (pp in JavaScript code)
- 1 << 11 ; // r11 v8 (fp in JavaScript code)
+ 1 << 11; // r11 v8 (fp in JavaScript code)
static const int kNumCalleeSaved = 7 + kR9Available;
static const int kCodeNotPresent = 0;
private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
-
// Accessors.
inline State state() const;
inline Address pc() const;
inline void set_pc(Address value);
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
};
// Compute the stack frame type for the given state.
static Type ComputeType(State* state);
- private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(StackFrame);
-
protected:
// TODO(1233523): Once the ARM code uses the new calling
// conventions, we should be able to make state_ private again.
friend class StackFrameIterator;
friend class StackHandlerIterator;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(StackFrame);
};
void clear_overflowed() { overflowed_ = false; }
+ // Push the (marked) object on the marking stack if there is room,
+ // otherwise mark the object as overflowed and wait for a rescan of the
+ // heap.
void Push(HeapObject* object) {
- ASSERT(!is_full());
CHECK(object->IsHeapObject());
- *(top_++) = object;
- if (is_full()) overflowed_ = true;
+ if (is_full()) {
+ object->SetOverflow();
+ overflowed_ = true;
+ } else {
+ *(top_++) = object;
+ }
}
HeapObject* Pop() {
void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
// ----------- S t a t e -------------
- // -- r0 : receiver
// -- r2 : name
// -- lr : return address
// -- [sp] : receiver
Label miss;
+ __ ldr(r0, MemOperand(sp, 0));
+
// Check that the receiver isn't a smi.
__ tst(r0, Operand(kSmiTagMask));
__ b(eq, &miss);
void LoadIC::GenerateShortStringLength(MacroAssembler* masm) {
// ----------- S t a t e -------------
- // -- r0 : receiver
// -- r2 : name
// -- lr : return address
// -- [sp] : receiver
Label miss;
+ __ ldr(r0, MemOperand(sp, 0));
+
// Check that the receiver isn't a smi.
__ tst(r0, Operand(kSmiTagMask));
__ b(eq, &miss);
void LoadIC::GenerateMediumStringLength(MacroAssembler* masm) {
// ----------- S t a t e -------------
- // -- r0 : receiver
// -- r2 : name
// -- lr : return address
// -- [sp] : receiver
Label miss;
+ __ ldr(r0, MemOperand(sp, 0));
+
// Check that the receiver isn't a smi.
__ tst(r0, Operand(kSmiTagMask));
__ b(eq, &miss);
void LoadIC::GenerateLongStringLength(MacroAssembler* masm) {
// ----------- S t a t e -------------
- // -- r0 : receiver
// -- r2 : name
// -- lr : return address
// -- [sp] : receiver
Label miss;
+ __ ldr(r0, MemOperand(sp, 0));
// Check that the receiver isn't a smi.
__ tst(r0, Operand(kSmiTagMask));
__ b(eq, &miss);
void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
// ----------- S t a t e -------------
- // -- r0 : receiver
// -- r2 : name
// -- lr : return address
// -- [sp] : receiver
void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
// ----------- S t a t e -------------
- // -- r0: number of arguments
- // -- r1: receiver
// -- lr: return address
// -----------------------------------
Label number, non_number, non_string, boolean, probe, miss;
+ // Get the receiver of the function from the stack into r1.
+ __ ldr(r1, MemOperand(sp, argc * kPointerSize));
// Get the name of the function from the stack; 1 ~ receiver.
- __ add(ip, sp, Operand(r0, LSL, kPointerSizeLog2));
- __ ldr(r2, MemOperand(ip, 1 * kPointerSize));
+ __ ldr(r2, MemOperand(sp, (argc + 1) * kPointerSize));
// Probe the stub cache.
Code::Flags flags =
void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
// ----------- S t a t e -------------
- // -- r1: receiver
// -- lr: return address
// -----------------------------------
Label miss, probe, done, global;
+ // Get the receiver of the function from the stack into r1.
+ __ ldr(r1, MemOperand(sp, argc * kPointerSize));
// Get the name of the function from the stack; 1 ~ receiver.
__ ldr(r2, MemOperand(sp, (argc + 1) * kPointerSize));
// -- lr: return address
// -----------------------------------
+ // Setup number of arguments for EnterJSFrame.
+ __ mov(r0, Operand(argc));
// Get the receiver of the function from the stack into r1.
__ ldr(r1, MemOperand(sp, argc * kPointerSize));
-
- __ mov(r0, Operand(argc)); // Setup number of arguments for EnterJSFrame.
__ EnterJSFrame(0);
+ __ pop(); // remove the code slot
// Push the receiver and the name of the function.
__ ldr(r0, MemOperand(pp, 0));
__ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit());
// Call the entry.
- __ mov(r0, Operand(2 - 1)); // do not count receiver
+ __ mov(r0, Operand(2));
__ mov(r1, Operand(f));
CEntryStub stub;
void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
// ----------- S t a t e -------------
- // -- r0 : receiver
// -- r2 : name
// -- lr : return address
// -- [sp] : receiver
// -----------------------------------
+ __ ldr(r0, MemOperand(sp, 0));
// Probe the stub cache.
Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, MONOMORPHIC);
StubCache::GenerateProbe(masm, flags, r0, r2, r3);
void LoadIC::GenerateNormal(MacroAssembler* masm) {
// ----------- S t a t e -------------
- // -- r0 : receiver
// -- r2 : name
// -- lr : return address
// -- [sp] : receiver
Label miss, probe, done, global;
+ __ ldr(r0, MemOperand(sp, 0));
// Check that the receiver isn't a smi.
__ tst(r0, Operand(kSmiTagMask));
__ b(eq, &miss);
// Cache miss: Restore receiver from stack and jump to runtime.
__ bind(&miss);
- __ ldr(r0, MemOperand(sp));
Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
}
void LoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
// ----------- S t a t e -------------
- // -- r0 : receiver
// -- r2 : name
// -- lr : return address
// -- [sp] : receiver
// -----------------------------------
+ __ ldr(r0, MemOperand(sp, 0));
__ push(r0);
__ push(r2);
- // Set the number of arguments and jump to the entry.
- __ mov(r0, Operand(2 - 1)); // not counting receiver.
- __ JumpToBuiltin(f);
+ // Perform tail call to the entry.
+ __ TailCallRuntime(f, 2);
}
__ ldr(r3, MemOperand(sp)); // copy receiver
__ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
- // Set the number of arguments and jump to the entry.
- __ mov(r0, Operand(3 - 1)); // not counting receiver.
- __ JumpToBuiltin(f);
+ // Perform tail call to the entry.
+ __ TailCallRuntime(f, 3);
}
__ j(below, &fast, taken);
// Slow case: Load name and receiver from stack and jump to runtime.
__ bind(&slow);
- __ mov(eax, Operand(esp, 1 * kPointerSize)); // 1 ~ return address.
- __ mov(ecx, Operand(esp, 2 * kPointerSize)); // 1 ~ return address, name.
__ IncrementCounter(&Counters::keyed_load_generic_slow, 1);
KeyedLoadIC::Generate(masm, ExternalReference(Runtime::kGetProperty));
// Check if the key is a symbol that is not an array index.
__ push(eax);
__ push(ecx);
// Do tail-call to runtime routine.
- __ Set(eax, Immediate(2)); // not counting receiver
- __ JumpToBuiltin(ExternalReference(Runtime::kSetProperty));
+ __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3);
// Extra capacity case: Check if there is extra capacity to
// Call the entry.
CEntryStub stub;
- __ mov(Operand(eax), Immediate(2 - 1)); // do not count receiver
+ __ mov(Operand(eax), Immediate(2));
__ mov(Operand(ebx), Immediate(f));
__ CallStub(&stub);
__ push(ecx);
__ push(ebx);
- // Set the number of arguments and jump to the entry.
- __ mov(Operand(eax), Immediate(1)); // not counting receiver.
- __ JumpToBuiltin(f);
+ // Perform tail call to the entry.
+ __ TailCallRuntime(f, 2);
}
__ push(eax);
__ push(ebx);
- // Set the number of arguments and jump to the entry.
- __ mov(Operand(eax), Immediate(1)); // not counting receiver.
- __ JumpToBuiltin(f);
+ // Perform tail call to the entry.
+ __ TailCallRuntime(f, 2);
}
__ push(eax);
__ push(ebx);
- // Set the number of arguments and jump to the entry.
- __ Set(eax, Immediate(2)); // not counting receiver.
- __ JumpToBuiltin(f);
+ // Perform tail call to the entry.
+ __ TailCallRuntime(f, 3);
}
__ push(ecx);
// Do tail-call to runtime routine.
- __ Set(eax, Immediate(2)); // not counting receiver
- __ JumpToBuiltin(f);
+ __ TailCallRuntime(f, 3);
}
static inline void SetTargetAtAddress(Address address, Code* target);
private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
-
// Frame pointer for the frame that uses (calls) the IC.
Address fp_;
// GetProperty and SetProperty are called and they in turn might
// invoke the garbage collector.
Address* pc_address_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
};
}
-void MacroAssembler::Push(const Operand& src) {
- push(r0);
- mov(r0, src);
-}
-
-
-void MacroAssembler::Push(const MemOperand& src) {
- push(r0);
- ldr(r0, src);
-}
-
-
-void MacroAssembler::Pop(Register dst) {
- mov(dst, Operand(r0));
- pop(r0);
-}
-
-
-void MacroAssembler::Pop(const MemOperand& dst) {
- str(r0, dst);
- pop(r0);
-}
-
-
// Will clobber 4 registers: object, offset, scratch, ip. The
// register 'object' contains a heap object pointer. The heap object
// tag is shifted away.
add(fp, sp, Operand(-StandardFrameConstants::kContextOffset));
mov(pp, Operand(ip)); // setup new parameter pointer
mov(r0, Operand(0)); // spare slot to store caller code object during GC
- // r0: TOS (code slot == 0)
+ push(r0);
// r1: preserved
}
ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize); // adjust this code
// The pc (return address) is passed in register lr.
if (try_location == IN_JAVASCRIPT) {
- mov(r0, Operand(Smi::FromInt(StackHandler::kCodeNotPresent))); // new TOS
stm(db_w, sp, pp.bit() | fp.bit() | lr.bit());
if (type == TRY_CATCH_HANDLER) {
mov(r3, Operand(StackHandler::TRY_CATCH));
ldr(r1, MemOperand(r3));
push(r1); // next sp
str(sp, MemOperand(r3)); // chain handler
- // TOS is r0
+ mov(r0, Operand(Smi::FromInt(StackHandler::kCodeNotPresent))); // new TOS
+ push(r0);
} else {
// Must preserve r0-r3, r5-r7 are available.
ASSERT(try_location == IN_JS_ENTRY);
// The parameter pointer is meaningless here and fp does not point to a JS
// frame. So we save NULL for both pp and fp. We expect the code throwing an
// exception to check fp before dereferencing it to restore the context.
- mov(r5, Operand(Smi::FromInt(StackHandler::kCodeNotPresent))); // new TOS
mov(pp, Operand(0)); // set pp to NULL
mov(ip, Operand(0)); // to save a NULL fp
stm(db_w, sp, pp.bit() | ip.bit() | lr.bit());
ldr(r6, MemOperand(r7));
push(r6); // next sp
str(sp, MemOperand(r7)); // chain handler
+ mov(r5, Operand(Smi::FromInt(StackHandler::kCodeNotPresent))); // new TOS
push(r5); // flush TOS
}
}
Ret();
}
+
void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
- ASSERT(num_arguments >= 1); // must have receiver for call
+ // All parameters are on the stack. r0 has the return value after call.
- if (f->nargs < 0) {
- // The number of arguments is not constant for this call, or we don't
- // have an entry stub that pushes the value. Push it before the call.
- push(r0);
- // Receiver does not count as an argument.
- mov(r0, Operand(num_arguments - 1));
- } else {
- ASSERT(f->nargs == num_arguments);
- // TODO(1236192): Most runtime routines don't need the number of
- // arguments passed in because it is constant. At some point we
- // should remove this need and make the runtime routine entry code
- // smarter.
-
- // The number of arguments is fixed for this call.
- // Set r0 correspondingly.
- push(r0);
- mov(r0, Operand(f->nargs - 1)); // receiver does not count as an argument
- }
+ // Either the expected number of arguments is unknown, or the actual
+ // number of arguments match the expectation.
+ ASSERT(f->nargs < 0 || f->nargs == num_arguments);
- RuntimeStub stub((Runtime::FunctionId) f->stub_id);
+ Runtime::FunctionId function_id =
+ static_cast<Runtime::FunctionId>(f->stub_id);
+ RuntimeStub stub(function_id, num_arguments);
CallStub(&stub);
}
}
-void MacroAssembler::TailCallRuntime(Runtime::Function* f) {
- JumpToBuiltin(ExternalReference(f)); // tail call to runtime routine
+void MacroAssembler::TailCallRuntime(const ExternalReference& ext,
+ int num_arguments) {
+ // TODO(1236192): Most runtime routines don't need the number of
+ // arguments passed in because it is constant. At some point we
+ // should remove this need and make the runtime routine entry code
+ // smarter.
+ mov(r0, Operand(num_arguments));
+ JumpToBuiltin(ext);
}
RecordComment(msg);
}
#endif
- push(r0);
mov(r0, Operand(p0));
push(r0);
mov(r0, Operand(Smi::FromInt(p1 - p0)));
+ push(r0);
CallRuntime(Runtime::kAbort, 2);
// will not return here
}
void ExitJSFrame(ExitJSFlag flag);
- // Support functions.
- void Push(const Operand& src);
- void Push(const MemOperand& src);
- void Pop(Register dst);
- void Pop(const MemOperand& dst);
-
// ---------------------------------------------------------------------------
// JavaScript invokes
// Tail call of a runtime routine (jump).
// Like JumpToBuiltin, but also takes care of passing the number
- // of parameters, if known.
- void TailCallRuntime(Runtime::Function* f);
+ // of parameters.
+ void TailCallRuntime(const ExternalReference& ext, int num_arguments);
// Jump to the builtin routine.
void JumpToBuiltin(const ExternalReference& builtin);
void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
- if (num_arguments < 1) {
- // must have receiver for call
+ // If the expected number of arguments of the runtime function is
+ // constant, we check that the actual number of arguments match the
+ // expectation.
+ if (f->nargs >= 0 && f->nargs != num_arguments) {
IllegalOperation();
return;
}
- // TODO(1236192): Most runtime routines don't need the number of
- // arguments passed in because it is constant. At some point we
- // should remove this need and make the runtime routine entry code
- // smarter.
-
- if (f->nargs < 0) {
- // The number of arguments is not constant for this call.
- // Receiver does not count as an argument.
- mov(Operand(eax), Immediate(num_arguments - 1));
- } else {
- if (f->nargs != num_arguments) {
- IllegalOperation();
- return;
- }
- // Receiver does not count as an argument.
- mov(Operand(eax), Immediate(f->nargs - 1));
- }
-
- RuntimeStub stub((Runtime::FunctionId) f->stub_id);
+ Runtime::FunctionId function_id =
+ static_cast<Runtime::FunctionId>(f->stub_id);
+ RuntimeStub stub(function_id, num_arguments);
CallStub(&stub);
}
-
-void MacroAssembler::TailCallRuntime(Runtime::Function* f) {
- JumpToBuiltin(ExternalReference(f)); // tail call to runtime routine
+void MacroAssembler::TailCallRuntime(const ExternalReference& ext,
+ int num_arguments) {
+ // TODO(1236192): Most runtime routines don't need the number of
+ // arguments passed in because it is constant. At some point we
+ // should remove this need and make the runtime routine entry code
+ // smarter.
+ mov(Operand(eax), Immediate(num_arguments));
+ JumpToBuiltin(ext);
}
// Tail call of a runtime routine (jump).
// Like JumpToBuiltin, but also takes care of passing the number
- // of parameters, if known.
- void TailCallRuntime(Runtime::Function* f);
+ // of arguments.
+ void TailCallRuntime(const ExternalReference& ext, int num_arguments);
// Jump to the builtin routine.
void JumpToBuiltin(const ExternalReference& ext);
static MarkingStack marking_stack;
+
+inline HeapObject* ShortCircuitConsString(Object** p) {
+ // Optimization: If the heap object pointed to by p is a cons string whose
+ // right substring is Heap::empty_string, update it in place to its left
+ // substring. Return the updated value.
+ //
+ // Here we assume that if we change *p, we replace it with a heap object
+ // (ie, the left substring of a cons string is always a heap object).
+ //
+ // The check performed is:
+ // object->IsConsString() &&
+ // (ConsString::cast(object)->second() == Heap::empty_string())
+ // except the maps for the object and its possible substrings might be
+ // marked.
+ HeapObject* object = HeapObject::cast(*p);
+ MapWord map_word = object->map_word();
+ map_word.ClearMark();
+ InstanceType type = map_word.ToMap()->instance_type();
+ if (type >= FIRST_NONSTRING_TYPE) return object;
+
+ StringRepresentationTag rep =
+ static_cast<StringRepresentationTag>(type & kStringRepresentationMask);
+ if (rep != kConsStringTag) return object;
+
+ Object* second = reinterpret_cast<ConsString*>(object)->second();
+ if (reinterpret_cast<String*>(second) != Heap::empty_string()) return object;
+
+ // Since we don't have the object's start, it is impossible to update the
+ // remembered set. Therefore, we only replace the string with its left
+ // substring when the remembered set does not change.
+ Object* first = reinterpret_cast<ConsString*>(object)->first();
+ if (!Heap::InNewSpace(object) && Heap::InNewSpace(first)) return object;
+
+ *p = first;
+ return HeapObject::cast(first);
+}
+
+
// Helper class for marking pointers in HeapObjects.
class MarkingVisitor : public ObjectVisitor {
public:
private:
// Mark object pointed to by p.
void MarkObjectByPointer(Object** p) {
- Object* obj = *p;
- if (!obj->IsHeapObject()) return;
-
- // Optimization: Bypass ConsString object where right size is
- // Heap::empty_string().
- // Please note this checks performed equals:
- // object->IsConsString() &&
- // (ConsString::cast(object)->second() == Heap::empty_string())
- // except the map for the object might be marked.
- MapWord map_word = HeapObject::cast(obj)->map_word();
- map_word.ClearMark();
- InstanceType type = map_word.ToMap()->instance_type();
- if ((type < FIRST_NONSTRING_TYPE) &&
- (static_cast<StringRepresentationTag>(
- type & kStringRepresentationMask) == kConsStringTag) &&
- (reinterpret_cast<String*>(
- reinterpret_cast<ConsString*>(obj)->second()) ==
- Heap::empty_string())) {
- // Since we don't have the object start it is impossible to update the
- // remeber set quickly. Therefore this optimization only is taking
- // place when we can avoid changing.
- Object* first = reinterpret_cast<ConsString*>(obj)->first();
- if (Heap::InNewSpace(obj) || !Heap::InNewSpace(first)) {
- obj = first;
- *p = obj;
- }
- }
- MarkCompactCollector::MarkObject(HeapObject::cast(obj));
+ if (!(*p)->IsHeapObject()) return;
+ HeapObject* object = ShortCircuitConsString(p);
+ MarkCompactCollector::MarkObject(object);
}
// Tells whether the mark sweep collection will perform compaction.
};
+// Visitor class for marking heap roots.
+class RootMarkingVisitor : public ObjectVisitor {
+ public:
+ void VisitPointer(Object** p) {
+ MarkObjectByPointer(p);
+ }
+
+ void VisitPointers(Object** start, Object** end) {
+ for (Object** p = start; p < end; p++) MarkObjectByPointer(p);
+ }
+
+ MarkingVisitor* stack_visitor() { return &stack_visitor_; }
+
+ private:
+ MarkingVisitor stack_visitor_;
+
+ void MarkObjectByPointer(Object** p) {
+ if (!(*p)->IsHeapObject()) return;
+
+ // Replace flat cons strings in place.
+ HeapObject* object = ShortCircuitConsString(p);
+ if (object->IsMarked()) return;
+
+#ifdef DEBUG
+ MarkCompactCollector::UpdateLiveObjectCount(object);
+#endif
+ Map* map = object->map();
+ // Mark the object.
+ object->SetMark();
+ MarkCompactCollector::tracer()->increment_marked_count();
+ // Mark the map pointer and body, and push them on the marking stack.
+ MarkCompactCollector::MarkObject(map);
+ object->IterateBody(map->instance_type(), object->SizeFromMap(map),
+ &stack_visitor_);
+
+ // Mark all the objects reachable from the map and body. May leave
+ // overflowed objects in the heap.
+ MarkCompactCollector::EmptyMarkingStack(&stack_visitor_);
+ }
+};
+
+
// Helper class for pruning the symbol table.
class SymbolTableCleaner : public ObjectVisitor {
public:
};
-void MarkCompactCollector::MarkUnmarkedObject(HeapObject* obj) {
+void MarkCompactCollector::MarkUnmarkedObject(HeapObject* object) {
#ifdef DEBUG
- UpdateLiveObjectCount(obj);
+ UpdateLiveObjectCount(object);
#endif
- ASSERT(!obj->IsMarked());
- if (obj->IsJSGlobalObject()) Counters::global_objects.Increment();
+ ASSERT(!object->IsMarked());
+ if (object->IsJSGlobalObject()) Counters::global_objects.Increment();
- if (FLAG_cleanup_caches_in_maps_at_gc && obj->IsMap()) {
- Map::cast(obj)->ClearCodeCache();
+ if (FLAG_cleanup_caches_in_maps_at_gc && object->IsMap()) {
+ Map::cast(object)->ClearCodeCache();
}
- obj->SetMark();
+ object->SetMark();
tracer_->increment_marked_count();
- if (!marking_stack.overflowed()) {
- ASSERT(Heap::Contains(obj));
- marking_stack.Push(obj);
- } else {
- // Set object's stack overflow bit, wait for rescan.
- obj->SetOverflow();
- }
+ ASSERT(Heap::Contains(object));
+ marking_stack.Push(object);
}
}
-static bool VisitOverflowedObject(HeapObject* obj) {
- if (!obj->IsOverflowed()) return true;
- ASSERT(obj->IsMarked());
-
- if (marking_stack.overflowed()) return false;
-
- obj->ClearOverflow();
- ASSERT(Heap::Contains(obj));
- marking_stack.Push(obj);
- return true;
-}
-
-
+// Fill the marking stack with overflowed objects returned by the given
+// iterator. Stop when the marking stack is filled or the end of the space
+// is reached, whichever comes first.
template<class T>
static void ScanOverflowedObjects(T* it) {
+ // The caller should ensure that the marking stack is initially not full,
+ // so that we don't waste effort pointlessly scanning for objects.
+ ASSERT(!marking_stack.is_full());
+
while (it->has_next()) {
- HeapObject* obj = it->next();
- if (!VisitOverflowedObject(obj)) {
- ASSERT(marking_stack.overflowed());
- break;
+ HeapObject* object = it->next();
+ if (object->IsOverflowed()) {
+ object->ClearOverflow();
+ ASSERT(object->IsMarked());
+ ASSERT(Heap::Contains(object));
+ marking_stack.Push(object);
+ if (marking_stack.is_full()) return;
}
}
}
}
-void MarkCompactCollector::MarkStrongRoots(MarkingVisitor* marking_visitor) {
+void MarkCompactCollector::ProcessRoots(RootMarkingVisitor* visitor) {
// Mark the heap roots gray, including global variables, stack variables,
// etc.
- Heap::IterateStrongRoots(marking_visitor);
+ Heap::IterateStrongRoots(visitor);
// Take care of the symbol table specially.
SymbolTable* symbol_table = SymbolTable::cast(Heap::symbol_table());
// 1. Mark the prefix of the symbol table gray.
- symbol_table->IteratePrefix(marking_visitor);
+ symbol_table->IteratePrefix(visitor);
#ifdef DEBUG
UpdateLiveObjectCount(symbol_table);
#endif
// or mark it overflowed).
symbol_table->SetMark();
tracer_->increment_marked_count();
+
+ // There may be overflowed objects in the heap. Visit them now.
+ while (marking_stack.overflowed()) {
+ RefillMarkingStack();
+ EmptyMarkingStack(visitor->stack_visitor());
+ }
}
}
-// Mark as black all objects reachable starting from gray objects. (Gray
-// objects are marked and on the marking stack, or marked and marked as
-// overflowed and not on the marking stack).
-//
-// Before: the heap contains a mixture of white, gray, and black objects.
-// After: the heap contains a mixture of white and black objects.
-void MarkCompactCollector::ProcessMarkingStack(
- MarkingVisitor* marking_visitor) {
-
- while (true) {
- while (!marking_stack.is_empty()) {
- HeapObject* object = marking_stack.Pop();
- ASSERT(object->IsHeapObject());
- ASSERT(Heap::Contains(object));
- // Removing a (gray) object from the marking stack turns it black.
- ASSERT(object->IsMarked() && !object->IsOverflowed());
-
- // Because the object is marked, we have to recover the original map
- // pointer and use it to mark the object's body.
- MapWord map_word = object->map_word();
- map_word.ClearMark();
- Map* map = map_word.ToMap();
- MarkObject(map);
- object->IterateBody(map->instance_type(), object->SizeFromMap(map),
- marking_visitor);
- }
+// Mark all objects reachable from the objects on the marking stack.
+// Before: the marking stack contains zero or more heap object pointers.
+// After: the marking stack is empty, and all objects reachable from the
+// marking stack have been marked, or are overflowed in the heap.
+void MarkCompactCollector::EmptyMarkingStack(MarkingVisitor* visitor) {
+ while (!marking_stack.is_empty()) {
+ HeapObject* object = marking_stack.Pop();
+ ASSERT(object->IsHeapObject());
+ ASSERT(Heap::Contains(object));
+ ASSERT(object->IsMarked());
+ ASSERT(!object->IsOverflowed());
+
+ // Because the object is marked, we have to recover the original map
+ // pointer and use it to mark the object's body.
+ MapWord map_word = object->map_word();
+ map_word.ClearMark();
+ Map* map = map_word.ToMap();
+ MarkObject(map);
+ object->IterateBody(map->instance_type(), object->SizeFromMap(map),
+ visitor);
+ }
+}
+
- // The only gray objects are marked overflowed in the heap. If there
- // are any, refill the marking stack and continue.
- if (!marking_stack.overflowed()) return;
+// Sweep the heap for overflowed objects, clear their overflow bits, and
+// push them on the marking stack. Stop early if the marking stack fills
+// before sweeping completes. If sweeping completes, there are no remaining
+// overflowed objects in the heap so the overflow flag on the markings stack
+// is cleared.
+void MarkCompactCollector::RefillMarkingStack() {
+ ASSERT(marking_stack.overflowed());
- marking_stack.clear_overflowed();
- // We have early stops if the marking stack overflows while refilling it
- // with gray objects to avoid pointlessly scanning extra spaces.
- SemiSpaceIterator new_it(Heap::new_space(), &OverflowObjectSize);
- ScanOverflowedObjects(&new_it);
- if (marking_stack.overflowed()) continue;
+ SemiSpaceIterator new_it(Heap::new_space(), &OverflowObjectSize);
+ ScanOverflowedObjects(&new_it);
+ if (marking_stack.is_full()) return;
- HeapObjectIterator old_it(Heap::old_space(), &OverflowObjectSize);
- ScanOverflowedObjects(&old_it);
- if (marking_stack.overflowed()) continue;
+ HeapObjectIterator old_it(Heap::old_space(), &OverflowObjectSize);
+ ScanOverflowedObjects(&old_it);
+ if (marking_stack.is_full()) return;
- HeapObjectIterator code_it(Heap::code_space(), &OverflowObjectSize);
- ScanOverflowedObjects(&code_it);
- if (marking_stack.overflowed()) continue;
+ HeapObjectIterator code_it(Heap::code_space(), &OverflowObjectSize);
+ ScanOverflowedObjects(&code_it);
+ if (marking_stack.is_full()) return;
- HeapObjectIterator map_it(Heap::map_space(), &OverflowObjectSize);
- ScanOverflowedObjects(&map_it);
- if (marking_stack.overflowed()) continue;
+ HeapObjectIterator map_it(Heap::map_space(), &OverflowObjectSize);
+ ScanOverflowedObjects(&map_it);
+ if (marking_stack.is_full()) return;
- LargeObjectIterator lo_it(Heap::lo_space(), &OverflowObjectSize);
- ScanOverflowedObjects(&lo_it);
+ LargeObjectIterator lo_it(Heap::lo_space(), &OverflowObjectSize);
+ ScanOverflowedObjects(&lo_it);
+ if (marking_stack.is_full()) return;
+
+ marking_stack.clear_overflowed();
+}
+
+
+// Mark all objects reachable (transitively) from objects on the marking
+// stack. Before: the marking stack contains zero or more heap object
+// pointers. After: the marking stack is empty and there are no overflowed
+// objects in the heap.
+void MarkCompactCollector::ProcessMarkingStack(MarkingVisitor* visitor) {
+ EmptyMarkingStack(visitor);
+ while (marking_stack.overflowed()) {
+ RefillMarkingStack();
+ EmptyMarkingStack(visitor);
}
}
-void MarkCompactCollector::ProcessObjectGroups(
- MarkingVisitor* marking_visitor) {
+void MarkCompactCollector::ProcessObjectGroups(MarkingVisitor* visitor) {
bool work_to_do = true;
ASSERT(marking_stack.is_empty());
while (work_to_do) {
MarkObjectGroups();
work_to_do = !marking_stack.is_empty();
- ProcessMarkingStack(marking_visitor);
+ ProcessMarkingStack(visitor);
}
}
ASSERT(!marking_stack.overflowed());
- MarkingVisitor marking_visitor;
- MarkStrongRoots(&marking_visitor);
- ProcessMarkingStack(&marking_visitor);
+ RootMarkingVisitor root_visitor;
+ ProcessRoots(&root_visitor);
// The objects reachable from the roots are marked black, unreachable
// objects are white. Mark objects reachable from object groups with at
// least one marked object, and continue until no new objects are
// reachable from the object groups.
- ProcessObjectGroups(&marking_visitor);
+ ProcessObjectGroups(root_visitor.stack_visitor());
// The objects reachable from the roots or object groups are marked black,
// unreachable objects are white. Process objects reachable only from
// First we mark weak pointers not yet reachable.
GlobalHandles::MarkWeakRoots(&MustBeMarked);
// Then we process weak pointers and process the transitive closure.
- GlobalHandles::IterateWeakRoots(&marking_visitor);
- ProcessMarkingStack(&marking_visitor);
+ GlobalHandles::IterateWeakRoots(&root_visitor);
+ while (marking_stack.overflowed()) {
+ RefillMarkingStack();
+ EmptyMarkingStack(root_visitor.stack_visitor());
+ }
// Repeat the object groups to mark unmarked groups reachable from the
// weak roots.
- ProcessObjectGroups(&marking_visitor);
+ ProcessObjectGroups(root_visitor.stack_visitor());
// Prune the symbol table removing all symbols only pointed to by the
// symbol table. Cannot use SymbolTable::cast here because the symbol
typedef void (*DeallocateFunction)(Address start, int size_in_bytes);
-// Forward declaration of visitor.
+// Forward declarations.
+class RootMarkingVisitor;
class MarkingVisitor;
+
// ----------------------------------------------------------------------------
// Mark-Compact collector
//
//
// after: live objects are marked.
+ friend class RootMarkingVisitor;
friend class MarkingVisitor;
// Marking operations for objects reachable from roots.
static void MarkLiveObjects();
- static void UnmarkLiveObjects();
-
- // Visit overflowed object, push overflowed object on the marking stack and
- // clear the overflow bit. If the marking stack is overflowed during this
- // process, return false;
- static bool VisitOverflowedObject(HeapObject* obj);
static void MarkUnmarkedObject(HeapObject* obj);
if (!obj->IsMarked()) MarkUnmarkedObject(obj);
}
- // Mark the heap roots.
- static void MarkStrongRoots(MarkingVisitor* marking_visitor);
+ // Mark the heap roots and all objects reachable from them.
+ static void ProcessRoots(RootMarkingVisitor* visitor);
// Mark objects in object groups that have at least one object in the
// group marked.
// Mark all objects in an object group with at least one marked
// object, then all objects reachable from marked objects in object
// groups, and repeat.
- static void ProcessObjectGroups(MarkingVisitor* marking_visitor);
-
- // Mark all objects reachable (transitively) from objects in the
- // marking stack or marked as overflowed in the heap.
- static void ProcessMarkingStack(MarkingVisitor* marking_visitor);
+ static void ProcessObjectGroups(MarkingVisitor* visitor);
+
+ // Mark objects reachable (transitively) from objects in the marking stack
+ // or overflowed in the heap.
+ static void ProcessMarkingStack(MarkingVisitor* visitor);
+
+ // Mark objects reachable (transitively) from objects in the marking
+ // stack. This function empties the marking stack, but may leave
+ // overflowed objects in the heap, in which case the marking stack's
+ // overflow flag will be set.
+ static void EmptyMarkingStack(MarkingVisitor* visitor);
+
+ // Refill the marking stack with overflowed objects from the heap. This
+ // function either leaves the marking stack full or clears the overflow
+ // flag on the marking stack.
+ static void RefillMarkingStack();
// Callback function for telling whether the object *p must be marked.
static bool MustBeMarked(Object** p);
%AddProperty(global, "Math", $Math, DONT_ENUM);
-// TODO(1240985): Make this work without arguments to the runtime
-// call.
-function $Math_random() { return %Math_random(0); }
+function $Math_random() { return %Math_random(); }
%AddProperty($Math, "random", $Math_random, DONT_ENUM);
function $Math_abs(x) {
f.prototype.name = name;
f.prototype.constructor = f;
%SetCode(f, function(m) {
- if (%IsConstructCall(this)) {
+ if (%IsConstructCall()) {
if (!IS_UNDEFINED(m)) this.message = ToString(m);
} else {
return new f(m);
void Code::CodePrint() {
HeapObject::PrintHeader("Code");
- PrintF("kind = %s", Kind2String(kind()));
-
- PrintF("\nInstructions (size = %d)\n", instruction_size());
- Disassembler::Decode(NULL /*use PrintF*/, this);
- PrintF("\n");
-
- PrintF("RelocInfo (size = %d)\n", relocation_size());
- for (RelocIterator it(this); !it.done(); it.next())
- it.rinfo()->Print();
- PrintF("\n");
+#ifdef ENABLE_DISASSEMBLER
+ Disassemble();
+#endif
}
#include "scopeinfo.h"
#include "string-stream.h"
+#ifdef ENABLE_DISASSEMBLER
+#include "disassembler.h"
+#endif
+
namespace v8 { namespace internal {
#ifdef DEBUG
Object* r = old_descriptors->CopyRemove(name);
if (r->IsFailure()) return r;
old_descriptors = DescriptorArray::cast(r);
- map()->set_instance_descriptors(old_descriptors);
old_name_index = DescriptorArray::kNotFound;
}
// Allocate new instance descriptors with (name, index) added
FieldDescriptor new_field(name, index, attributes);
Object* new_descriptors =
- map()->instance_descriptors()->CopyInsert(&new_field, true);
+ old_descriptors->CopyInsert(&new_field, true);
if (new_descriptors->IsFailure()) return new_descriptors;
// Only allow map transition if the object's map is NOT equal to the
// global object_function's map and there is not a transition for name.
bool allow_map_transition =
- !map()->instance_descriptors()->Contains(name) &&
+ !old_descriptors->Contains(name) &&
(Top::context()->global_context()->object_function()->map() != map());
ASSERT(allow_map_transition || !constant_transition);
if (map()->unused_property_fields() > 0) {
ASSERT(index < properties()->length());
// Allocate a new map for the object.
- Object* new_map = map()->Copy();
- if (new_map->IsFailure()) return new_map;
+ Object* r = map()->Copy();
+ if (r->IsFailure()) return r;
+ Map* new_map = Map::cast(r);
if (allow_map_transition) {
// Allocate new instance descriptors for the old map with map transition.
MapTransitionDescriptor d(name, Map::cast(new_map), attributes);
- Object* old_descriptors = map()->instance_descriptors()->CopyInsert(&d);
- if (old_descriptors->IsFailure()) return old_descriptors;
- // We have now allocate all the necessary object and change can be
- // applied.
- map()->set_instance_descriptors(DescriptorArray::cast(old_descriptors));
+ Object* r = old_descriptors->CopyInsert(&d);
+ if (r->IsFailure()) return r;
+ old_descriptors = DescriptorArray::cast(r);
}
- Map::cast(new_map)->
- set_instance_descriptors(DescriptorArray::cast(new_descriptors));
- Map::cast(new_map)->
- set_unused_property_fields(map()->unused_property_fields() - 1);
- set_map(Map::cast(new_map));
+ // We have now allocated all the necessary objects.
+ // All the changes can be applied at once, so they are atomic.
+ map()->set_instance_descriptors(old_descriptors);
+ new_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
+ new_map->set_unused_property_fields(map()->unused_property_fields() - 1);
+ set_map(new_map);
properties()->set(index, value);
} else {
ASSERT(map()->unused_property_fields() == 0);
FixedArray::cast(values)->set(index, value);
// Allocate a new map for the object.
- Object* new_map = map()->Copy();
- if (new_map->IsFailure()) return new_map;
+ Object* r = map()->Copy();
+ if (r->IsFailure()) return r;
+ Map* new_map = Map::cast(r);
if (allow_map_transition) {
MapTransitionDescriptor d(name, Map::cast(new_map), attributes);
- // Allocate a new instance descriptors for the old map with map
- // transition.
- Object* old_descriptors = map()->instance_descriptors()->CopyInsert(&d);
- if (old_descriptors->IsFailure()) return old_descriptors;
-
- // We have now allocate all the necessary object and change can be
- // applied.
- map()->set_instance_descriptors(DescriptorArray::cast(old_descriptors));
+ // Allocate new instance descriptors for the old map with map transition.
+ Object* r = old_descriptors->CopyInsert(&d);
+ if (r->IsFailure()) return r;
+ old_descriptors = DescriptorArray::cast(r);
}
-
- Map::cast(new_map)->
- set_instance_descriptors(DescriptorArray::cast(new_descriptors));
- Map::cast(new_map)->
- set_unused_property_fields(kExtraFields - 1);
- set_map(Map::cast(new_map));
+ // We have now allocated all the necessary objects.
+ // All changes can be done at once, atomically.
+ map()->set_instance_descriptors(old_descriptors);
+ new_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
+ new_map->set_unused_property_fields(kExtraFields - 1);
+ set_map(new_map);
set_properties(FixedArray::cast(values));
}
ConstTransitionDescriptor mark(name);
new_descriptors = old_map->instance_descriptors()->CopyInsert(&mark, false);
if (new_descriptors->IsFailure()) {
- return new_descriptors;
+ return function; // We have accomplished the main goal, so return success.
}
old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
UNREACHABLE();
return NULL;
}
+
+
+void Code::Disassemble() {
+ PrintF("kind = %s", Kind2String(kind()));
+
+ PrintF("\nInstructions (size = %d)\n", instruction_size());
+ Disassembler::Decode(NULL, this);
+ PrintF("\n");
+
+ PrintF("RelocInfo (size = %d)\n", relocation_size());
+ for (RelocIterator it(this); !it.done(); it.next())
+ it.rinfo()->Print();
+ PrintF("\n");
+}
#endif // ENABLE_DISASSEMBLER
#ifdef ENABLE_DISASSEMBLER
// Printing
static const char* Kind2String(Kind kind);
+ void Disassemble();
#endif // ENABLE_DISASSEMBLER
// [instruction_size]: Size of the native instructions
inline byte bit_field();
inline void set_bit_field(byte value);
- // Tells whether this object has a special lookup behavior.
- void set_special_lookup() {
- set_bit_field(bit_field() | (1 << kHasSpecialLookup));
- }
-
- bool has_special_lookup() {
- return ((1 << kHasSpecialLookup) & bit_field()) != 0;
- }
-
// Tells whether the object in the prototype property will be used
// for instances created from this function. If the prototype
// property is set to a value that is not a JSObject, the prototype
static const int kBitFieldOffset = kInstanceAttributesOffset + 3;
// Bit positions for bit field.
- static const int kHasSpecialLookup = 0;
+ static const int kUnused = 0; // To be used for marking recently used maps.
static const int kHasNonInstancePrototype = 1;
static const int kIsHiddenPrototype = 2;
static const int kHasNamedInterceptor = 3;
};
-// Script describes a script which has beed added to the VM.
+// Script describes a script which has been added to the VM.
class Script: public Struct {
public:
// [source]: the script source.
static const int kSize = kDebugInfoOffset + kPointerSize;
private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo);
-
// Bit positions in length_and_flg.
// The least significant bit is used as the flag.
static const int kFlagBit = 0;
static const int kIsTopLevelBit = 1;
static const int kStartPositionShift = 2;
static const int kStartPositionMask = ~((1 << kStartPositionShift) - 1);
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo);
};
static const int kHeaderSize = kGlobalContextOffset + kPointerSize;
private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(GlobalObject);
friend class AGCCVersionRequiresThisClassToHaveAFriendSoHereItIs;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(GlobalObject);
};
static const int kSize = kFlagOffset + kPointerSize;
private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorInfo);
-
// Bit positions in flag.
static const int kAllCanReadBit = 0;
static const int kAllCanWriteBit = 1;
class AttributesField: public BitField<PropertyAttributes, 2, 3> {};
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorInfo);
};
static const int kSize = kFlagOffset + kPointerSize;
private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(FunctionTemplateInfo);
-
// Bit position in the flag, from least significant bit position.
static const int kHiddenPrototypeBit = 0;
static const int kUndetectableBit = 1;
static const int kNeedsAccessCheckBit = 2;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(FunctionTemplateInfo);
};
static double nan_value();
private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
-
static const int msPerSecond = 1000;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
};
function RegExpConstructor(pattern, flags) {
- if (%IsConstructCall(this)) {
+ if (%IsConstructCall()) {
DoConstructRegExp(this, pattern, flags, true);
} else {
// RegExp : Called as function; see ECMA-262, section 15.10.3.1.
static Object* Runtime_IsConstructCall(Arguments args) {
NoHandleAllocation ha;
+ ASSERT(args.length() == 0);
JavaScriptFrameIterator it;
return Heap::ToBoolean(it.frame()->IsConstructor());
}
-static Object* Runtime_GetBuiltins(Arguments args) {
- NoHandleAllocation ha;
- return Top::context()->builtins();
-}
-
-
static Object* Runtime_RegExpCompile(Arguments args) {
HandleScope scope; // create a new handle scope
ASSERT(args.length() == 3);
// with the exact length. This is implemented using a goto back
// to this label if we discover that the assumption doesn't hold.
// I apologize sincerely for this and will give a vaffel-is to
- // anyone who can implement it in a nicer way.
+ // the first person who can implement it in a nicer way.
try_convert:
// Allocate the resulting string.
}
-static Object* Runtime_NumberAlloc(Arguments args) {
- NoHandleAllocation ha;
- ASSERT(args.length() == 1);
- return Heap::AllocateHeapNumber(0);
-}
-
-
static Object* Runtime_NumberUnaryMinus(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 1);
// Returns a number value with positive sign, greater than or equal to
// 0 but less than 1, chosen randomly.
-static Object* Runtime_Math_random(Arguments) {
+static Object* Runtime_Math_random(Arguments args) {
NoHandleAllocation ha;
+ ASSERT(args.length() == 0);
// To get much better precision, we combine the results of two
// invocations of random(). The result is computed by normalizing a
static Object* Runtime_GetCalledFunction(Arguments args) {
HandleScope scope;
- ASSERT(args.length() == 1);
+ ASSERT(args.length() == 0);
StackFrameIterator it;
// Get past the JS-to-C exit frame.
ASSERT(it.frame()->is_exit());
}
-static Object* Runtime_DateCurrentTime(Arguments) {
+static Object* Runtime_DateCurrentTime(Arguments args) {
NoHandleAllocation ha;
+ ASSERT(args.length() == 0);
// According to ECMA-262, section 15.9.1, page 117, the precision of
// the number in a Date object representing a particular instant in
static Object* Runtime_DateLocalTimeOffset(Arguments args) {
NoHandleAllocation ha;
- ASSERT(args.length() == 1);
+ ASSERT(args.length() == 0);
return Heap::NumberFromDouble(OS::LocalTimeOffset());
}
}
-static Object* Runtime_NumberMaxValue(Arguments) {
+static Object* Runtime_NumberMaxValue(Arguments args) {
NoHandleAllocation ha;
+ ASSERT(args.length() == 0);
return Heap::number_max_value();
}
-static Object* Runtime_NumberMinValue(Arguments) {
+static Object* Runtime_NumberMinValue(Arguments args) {
NoHandleAllocation ha;
+ ASSERT(args.length() == 0);
return Heap::number_min_value();
}
-static Object* Runtime_NumberNaN(Arguments) {
+static Object* Runtime_NumberNaN(Arguments args) {
NoHandleAllocation ha;
+ ASSERT(args.length() == 0);
return Heap::nan_value();
}
static Object* Runtime_Break(Arguments args) {
- ASSERT(args.length() == 1);
+ ASSERT(args.length() == 0);
StackGuard::DebugBreak();
return Heap::undefined_value();
}
// Clear all stepping set by PrepareStep.
static Object* Runtime_ClearStepping(Arguments args) {
HandleScope scope;
- ASSERT(args.length() == 1);
+ ASSERT(args.length() == 0);
Debug::ClearStepping();
return Heap::undefined_value();
}
static Object* Runtime_DebugGetLoadedScripts(Arguments args) {
HandleScope scope;
- ASSERT(args.length() == 1);
+ ASSERT(args.length() == 0);
// Perform two GCs to get rid of all unreferenced scripts. The first GC gets
// rid of all the cached script wrappes and the second gets rid of the
static Object* Runtime_SystemBreak(Arguments args) {
+ ASSERT(args.length() == 0);
CPU::DebugBreak();
return Heap::undefined_value();
}
// ListNatives is ONLY used by the fuzz-natives.js in debug mode
// Exclude the code in release mode.
static Object* Runtime_ListNatives(Arguments args) {
- ASSERT(args.length() == 1);
+ ASSERT(args.length() == 0);
HandleScope scope;
Handle<JSArray> result = Factory::NewJSArray(0);
int index = 0;
\
F(IsInPrototypeChain, 2) \
\
- F(IsConstructCall, 1) \
+ F(IsConstructCall, 0) \
\
/* Utilities */ \
- F(GetBuiltins, 1) \
- F(GetCalledFunction, 1) \
+ F(GetCalledFunction, 0) \
F(GetFunctionDelegate, 1) \
F(NewArguments, 1) \
F(LazyCompile, 1) \
F(NumberMul, 2) \
F(NumberDiv, 2) \
F(NumberMod, 2) \
- F(NumberAlloc, 1) \
F(NumberUnaryMinus, 1) \
\
F(StringAdd, 2) \
F(Math_floor, 1) \
F(Math_log, 1) \
F(Math_pow, 2) \
- F(Math_random, 1) \
+ F(Math_random, 0) \
F(Math_round, 1) \
F(Math_sin, 1) \
F(Math_sqrt, 1) \
F(GetTemplateField, 2) \
\
/* Dates */ \
- F(DateCurrentTime, 1) \
+ F(DateCurrentTime, 0) \
F(DateParseString, 1) \
F(DateLocalTimezone, 1) \
- F(DateLocalTimeOffset, 1) \
+ F(DateLocalTimeOffset, 0) \
F(DateDaylightSavingsOffset, 1) \
\
/* Numbers */ \
F(NumberIsFinite, 1) \
- F(NumberMaxValue, 1) \
- F(NumberMinValue, 1) \
- F(NumberNaN, 1) \
+ F(NumberMaxValue, 0) \
+ F(NumberMinValue, 0) \
+ F(NumberNaN, 0) \
\
/* Globals */ \
F(CompileString, 2) \
/* Debugging */ \
F(AddDebugEventListener, 2) \
F(RemoveDebugEventListener, 1) \
- F(Break, 1) \
+ F(Break, 0) \
F(DebugGetLocalPropertyDetails, 2) \
F(DebugGetProperty, 2) \
F(DebugLocalPropertyNames, 1) \
F(ClearBreakPoint, 1) \
F(ChangeBreakOnException, 2) \
F(PrepareStep, 3) \
- F(ClearStepping, 1) \
+ F(ClearStepping, 0) \
F(DebugEvaluate, 4) \
F(DebugEvaluateGlobal, 3) \
- F(DebugGetLoadedScripts, 1) \
+ F(DebugGetLoadedScripts, 0) \
F(DebugReferencedBy, 3) \
F(DebugConstructedBy, 2) \
F(GetPrototype, 1) \
- F(SystemBreak, 1) \
+ F(SystemBreak, 0) \
\
/* Literals */ \
F(MaterializeRegExpLiteral, 4)\
F(DeclareGlobals, 3) \
F(DeclareContextSlot, 5) \
F(InitializeVarGlobal, -1 /* 1 or 2 */) \
- F(InitializeConstGlobal, -1 /* 1 or 2 */) \
+ F(InitializeConstGlobal, 2) \
F(InitializeConstContextSlot, 3) \
\
/* Debugging */ \
#ifdef DEBUG
#define RUNTIME_FUNCTION_LIST_DEBUG(F) \
/* Testing */ \
- F(ListNatives, 1)
+ F(ListNatives, 0)
#else
#define RUNTIME_FUNCTION_LIST_DEBUG(F)
#endif
const $Number = global.Number;
const $Function = global.Function;
const $Boolean = global.Boolean;
-const $NaN = %NumberNaN(1);
+const $NaN = %NumberNaN();
// ECMA-262, section 11.9.1, page 55.
function CALL_NON_FUNCTION() {
- var callee = %GetCalledFunction(0);
+ var callee = %GetCalledFunction();
var delegate = %GetFunctionDelegate(callee);
if (!IS_FUNCTION(delegate)) {
throw %MakeTypeError('called_non_callable', [typeof callee]);
if (IS_NUMBER(x)) return x;
if (IS_STRING(x)) return %StringToNumber(x);
if (IS_BOOLEAN(x)) return x ? 1 : 0;
- if (IS_UNDEFINED(x)) return %NumberNaN(1);
+ if (IS_UNDEFINED(x)) return %NumberNaN();
return (IS_NULL(x)) ? 0 : ToNumber(%DefaultNumber(x));
};
writer_->PutInt(size >> kObjectAlignmentBits);
PutEncodedAddress(addr); // encodes AllocationSpace
- // Get the map's encoded address, possibly serializing it on first
- // visit. Note that we do not update obj->map(), since
- // it already contains the forwarding address of 'obj'.
- bool serialized;
- Address map_addr = Encode(map, &serialized);
-
// Visit all the pointers in the object other than the map. This
// will recursively serialize any as-yet-unvisited objects.
- obj->IterateBody(type, size, this);
+ obj->Iterate(this);
// Mark end of recursively embedded objects, start of object body.
writer_->PutC('|');
- // Write out the encoded address for the map.
- PutEncodedAddress(map_addr);
-
- // Write out the raw contents of the object following the map
- // pointer containing the now-updated pointers. No compression, but
+ // Write out the raw contents of the object. No compression, but
// fast to deserialize.
+ writer_->PutBytes(obj->address(), size);
+ // Update pointers and external references in the written object.
ReferenceUpdater updater(obj, this);
- obj->IterateBody(type, size, &updater);
- writer_->PutBytes(obj->address() + HeapObject::kSize,
- size - HeapObject::kSize);
+ obj->Iterate(&updater);
updater.Update(writer_->position() - size);
#ifdef DEBUG
GetHeader();
Heap::IterateRoots(this);
GetContextStack();
- Heap::RebuildRSets();
}
}
ASSERT(c == '|');
- // Read, resolve and set the map pointer: don't rely on map being initialized.
- Address map_addr = GetEncodedAddress();
- Map* map = reinterpret_cast<Map*>(Resolve(map_addr));
HeapObject* obj = reinterpret_cast<HeapObject*>(o);
- obj->set_map(map);
-
// Read the uninterpreted contents of the object after the map
- reader_.GetBytes(obj->address() + HeapObject::kSize,
- size - HeapObject::kSize);
-
+ reader_.GetBytes(obj->address(), size);
#ifdef DEBUG
if (expect_debug_information_) {
// Read in the epilogue to check that we're still synchronized
}
#endif
- // Resolve the encoded pointers we just read in
+ // Resolve the encoded pointers we just read in.
+ // Same as obj->Iterate(this), but doesn't rely on the map pointer being set.
+ VisitPointer(reinterpret_cast<Object**>(obj->address()));
obj->IterateBody(type, size, this);
if (type == CODE_TYPE) {
// Set the String function and constructor.
%SetCode($String, function(x) {
var value = %_ArgumentsLength() == 0 ? '' : ToString(x);
- if (%IsConstructCall(this)) {
+ if (%IsConstructCall()) {
%_SetValueOf(this, value);
} else {
return value;
var pat = ToString(searchString);
var index = (%_ArgumentsLength() > 1)
? ToNumber(%_Arguments(1) /* position */)
- : %NumberNaN(1);
+ : %NumberNaN();
var firstIndex;
if ($isNaN(index)) {
firstIndex = sub.length - pat.length;
__ EnterJSFrame(0);
// Push the function on the stack and call the runtime function.
- __ Push(MemOperand(pp, 0));
+ __ ldr(r0, MemOperand(pp, 0));
+ __ push(r0);
__ CallRuntime(Runtime::kLazyCompile, 1);
// Move result to r1 and restore number of arguments.
JSObject* holder,
int index) {
// ----------- S t a t e -------------
- // -- r0: number of arguments
- // -- r1: receiver
// -- lr: return address
// -----------------------------------
HandleScope scope;
Label miss;
+ const int argc = arguments().immediate();
+
+ // Get the receiver of the function from the stack into r1.
+ __ ldr(r1, MemOperand(sp, argc * kPointerSize));
// Check that the receiver isn't a smi.
__ tst(r1, Operand(kSmiTagMask));
__ b(eq, &miss);
__ cmp(r2, Operand(JS_FUNCTION_TYPE));
__ b(ne, &miss);
+ // TODO(1233523): remove r0 after changing Jump to InvokeCode
+ // Setup argument length register.
+ __ mov(r0, Operand(argc));
// Patch the function on the stack; 1 ~ receiver.
- __ add(ip, sp, Operand(r0, LSL, kPointerSizeLog2));
- __ str(r3, MemOperand(ip, 1 * kPointerSize));
+ __ str(r3, MemOperand(sp, (argc + 1) * kPointerSize));
// Setup the context and jump to the call code of the function (tail call).
__ ldr(cp, FieldMemOperand(r3, JSFunction::kContextOffset));
JSFunction* function,
CheckType check) {
// ----------- S t a t e -------------
- // -- r1: receiver
// -- lr: return address
// -----------------------------------
HandleScope scope;
Label miss;
+ // Get the receiver from the stack
+ const int argc = arguments().immediate();
+ __ ldr(r1, MemOperand(sp, argc * kPointerSize));
+
// Check that the receiver isn't a smi.
if (check != NUMBER_CHECK) {
__ tst(r1, Operand(kSmiTagMask));
UNREACHABLE();
}
- // Number of arguments for this function.
- const int argc = arguments().immediate();
-
// Get the function and setup the context.
__ mov(r3, Operand(Handle<JSFunction>(function)));
__ ldr(cp, FieldMemOperand(r3, JSFunction::kContextOffset));
JSObject* holder,
String* name) {
// ----------- S t a t e -------------
- // -- r0: number of arguments
- // -- r1: receiver
// -- lr: return address
// -----------------------------------
__ push(r2); // name
__ push(r0); // value
- // Do tail-call to the C builtin.
- __ mov(r0, Operand(3)); // not counting receiver
- __ JumpToBuiltin(ExternalReference(IC_Utility(IC::kStoreCallbackProperty)));
+ // Do tail-call to the runtime system.
+ ExternalReference store_callback_property =
+ ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
+ __ TailCallRuntime(store_callback_property, 4);
// Handle store cache miss.
__ bind(&miss);
__ push(r2); // name
__ push(r0); // value
- // Do tail-call to the C builtin.
- __ mov(r0, Operand(2)); // not counting receiver
- ExternalReference store_interceptor =
+ // Do tail-call to the runtime system.
+ ExternalReference store_ic_property =
ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
- __ JumpToBuiltin(store_interceptor);
+ __ TailCallRuntime(store_ic_property, 3);
// Handle store cache miss.
__ bind(&miss);
JSObject* holder,
int index) {
// ----------- S t a t e -------------
- // -- r0 : receiver
// -- r2 : name
// -- lr : return address
// -- [sp] : receiver
HandleScope scope;
Label miss;
+ __ ldr(r0, MemOperand(sp, 0));
+
// Check that the receiver isn't a smi.
__ tst(r0, Operand(kSmiTagMask));
__ b(eq, &miss);
JSObject* holder,
AccessorInfo* callback) {
// ----------- S t a t e -------------
- // -- r0 : receiver
// -- r2 : name
// -- lr : return address
// -- [sp] : receiver
HandleScope scope;
Label miss;
+ __ ldr(r0, MemOperand(sp, 0));
// Check that the receiver isn't a smi.
__ tst(r0, Operand(kSmiTagMask));
__ b(eq, &miss);
__ push(r2); // name
__ push(reg); // holder
- // Do tail-call to the C builtin.
- __ mov(r0, Operand(3)); // not counting receiver
- __ JumpToBuiltin(ExternalReference(IC_Utility(IC::kLoadCallbackProperty)));
+ // Do tail-call to the runtime system.
+ ExternalReference load_callback_property =
+ ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
+ __ TailCallRuntime(load_callback_property, 4);
// Handle load cache miss.
__ bind(&miss);
JSObject* holder,
Object* value) {
// ----------- S t a t e -------------
- // -- r0 : receiver
// -- r2 : name
// -- lr : return address
// -- [sp] : receiver
HandleScope scope;
Label miss;
+ __ ldr(r0, MemOperand(sp, 0));
// Check that the receiver isn't a smi.
__ tst(r0, Operand(kSmiTagMask));
__ b(eq, &miss);
JSObject* holder,
String* name) {
// ----------- S t a t e -------------
- // -- r0 : receiver
// -- r2 : name
// -- lr : return address
// -- [sp] : receiver
HandleScope scope;
Label miss;
+ __ ldr(r0, MemOperand(sp, 0));
// Check that the receiver isn't a smi.
__ tst(r0, Operand(kSmiTagMask));
__ b(eq, &miss);
__ push(reg); // holder
__ push(r2); // name
- // Do tail-call to the C builtin.
- __ mov(r0, Operand(2)); // not counting receiver
- __ JumpToBuiltin(ExternalReference(IC_Utility(IC::kLoadInterceptorProperty)));
+ // Do tail-call to the runtime system.
+ ExternalReference load_ic_property =
+ ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
+ __ TailCallRuntime(load_ic_property, 3);
// Handle load cache miss.
__ bind(&miss);
__ push(reg); // holder
__ push(scratch2); // restore return address
- // Do tail-call to the C builtin.
- __ mov(eax, 3); // not counting receiver
- __ JumpToBuiltin(ExternalReference(IC_Utility(IC::kLoadCallbackProperty)));
+ // Do tail-call to the runtime system.
+ ExternalReference load_callback_property =
+ ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
+ __ TailCallRuntime(load_callback_property, 4);
}
__ push(name); // name
__ push(scratch2); // restore return address
- // Do tail-call to the C builtin.
- __ mov(eax, 2); // not counting receiver
- __ JumpToBuiltin(ExternalReference(IC_Utility(IC::kLoadInterceptorProperty)));
+ // Do tail-call to the runtime system.
+ ExternalReference load_ic_property =
+ ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
+ __ TailCallRuntime(load_ic_property, 3);
}
__ push(Operand(ebp, (argc + 3) * kPointerSize)); // name
// Perform call.
- __ mov(Operand(eax), Immediate(2)); // 2 arguments w/o receiver
ExternalReference load_interceptor =
ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
+ __ mov(Operand(eax), Immediate(3));
__ mov(Operand(ebx), Immediate(load_interceptor));
CEntryStub stub;
__ push(eax); // value
__ push(ebx); // restore return address
- // Do tail-call to the C builtin.
- __ mov(eax, 3); // not counting receiver
- __ JumpToBuiltin(ExternalReference(IC_Utility(IC::kStoreCallbackProperty)));
+ // Do tail-call to the runtime system.
+ ExternalReference store_callback_property =
+ ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
+ __ TailCallRuntime(store_callback_property, 4);
// Handle store cache miss.
__ bind(&miss);
__ push(eax); // value
__ push(ebx); // restore return address
- // Do tail-call to the C builtin.
- __ mov(eax, 2); // not counting receiver
- ExternalReference store_interceptor =
+ // Do tail-call to the runtime system.
+ ExternalReference store_ic_property =
ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
- __ JumpToBuiltin(store_interceptor);
+ __ TailCallRuntime(store_ic_property, 3);
// Handle store cache miss.
__ bind(&miss);
char* Finalize();
private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
-
char* buffer_;
int size_;
int position_;
bool is_finalized() const { return position_ < 0; }
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
};
} } // namespace v8::internal
#ifndef V8_V8_H_
#define V8_V8_H_
-// Google3 uses NDEBUG.
-#if defined(GOOGLE3) && !defined(NDEBUG)
-#define DEBUG
+#if defined(GOOGLE3)
+// Google3 special flag handling.
+#if defined(DEBUG) && defined(NDEBUG)
+// If both are defined in Google3, then we are building an optimized v8 with
+// assertions enabled.
+#undef NDEBUG
#endif
+#endif // defined(GOOGLE3)
// V8 only uses DEBUG, but included external files
// may use NDEBUG - make sure they are consistent.
// const $Number = global.Number;
// const $Function = global.Function;
// const $Array = global.Array;
-// const $NaN = %NumberNaN(1);
+// const $NaN = %NumberNaN();
// ECMA 262 - 15.1.1.1.
%SetCode($Boolean, function(x) {
- if (%IsConstructCall(this)) {
+ if (%IsConstructCall()) {
%_SetValueOf(this, ToBoolean(x));
} else {
return ToBoolean(x);
%SetCode($Object, function(x) {
- if (%IsConstructCall(this)) {
+ if (%IsConstructCall()) {
if (x == null) return this;
return ToObject(x);
} else {
// Set the Number function and constructor.
%SetCode($Number, function(x) {
var value = %_ArgumentsLength() == 0 ? 0 : ToNumber(x);
- if (%IsConstructCall(this)) {
+ if (%IsConstructCall()) {
%_SetValueOf(this, value);
} else {
return value;
%AddProperty($Number.prototype, "constructor", $Number, DONT_ENUM);
// ECMA-262 section 15.7.3.1.
-%AddProperty($Number, "MAX_VALUE", %NumberMaxValue(1), DONT_ENUM | DONT_DELETE | READ_ONLY);
+%AddProperty($Number, "MAX_VALUE", %NumberMaxValue(), DONT_ENUM | DONT_DELETE | READ_ONLY);
// ECMA-262 section 15.7.3.2.
-%AddProperty($Number, "MIN_VALUE", %NumberMinValue(1), DONT_ENUM | DONT_DELETE | READ_ONLY);
+%AddProperty($Number, "MIN_VALUE", %NumberMinValue(), DONT_ENUM | DONT_DELETE | READ_ONLY);
// ECMA-262 section 15.7.3.3.
%AddProperty($Number, "NaN", $NaN, DONT_ENUM | DONT_DELETE | READ_ONLY);
+#!/usr/bin/env python
# Copyright 2006 Google Inc. All Rights Reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
output.close()
def main():
- output = sys.argv[1]
- input = sys.argv[2:]
- JS2C(input, [output], None)
+ natives = sys.argv[1]
+ natives_empty = sys.argv[2]
+ source_files = sys.argv[3:]
+ JS2C(source_files, [natives, natives_empty], None)
if __name__ == "__main__":
main()
--- /dev/null
+This directory contains Microsoft Visual Studio project files for including v8
+in a Visual Studio solution.
+
+v8_base.vcproj
+--------------
+Base V8 library containing all the V8 code but no JavaScript library code. This
+includes third party code for regular expression handling (jscre) and
+string/number convertions (dtoa).
+
+v8.vcproj
+---------
+V8 library containing all the V8 and JavaScript library code embedded as source
+which is compiled as V8 is running.
+
+v8_mksnapshot.vcproj
+--------------------
+Executable v8_mksnapshot.exe for building a heap snapshot from a running V8.
+
+v8_snapshot.vcproj
+------------------
+V8 library containing all the V8 and JavaScript library code embedded as a heap
+snapshot instead of source to be compiled as V8 is running. Using this library
+provides significantly faster startup time than v8.vcproj.
+
+The property sheets common.vsprops, debug.vsprops and release.vsprops contains
+most of the configuration options and are inhireted by the project files
+described above. The location of the output directory used are defined in
+common.vsprops.
+
+With regard to Platform SDK version V8 has no specific requriments and builds
+with either what is supplied with Visual Studio 2005 or the latest Platform SDK
+from Microsoft.
+
+When adding these projects to a solution the following dependencies needs to be
+in place:
+
+ v8.vcproj depends on v8_base.vcproj
+ v8_mksnapshot.vcproj depends on v8.vcproj
+ v8_snapshot.vcproj depends on v8_mksnapshot.vcproj and v8_base.vcproj
+
+A project which uses V8 should then depend on v8_snapshot.vcproj.
+
+If V8 without snapshot if preferred only v8_base.vcproj and v8.vcproj are
+required and a project which uses V8 should depend on v8.vcproj.
+
+Python requirements
+-------------------
+When using the Microsoft Visual Studio project files Python version 2.4 or later
+is required. Make sure that python.exe is on the path before running Visual
+Studio. The use of Python is in the command script js2c.cmd which is used in the
+Custom Build Step for v8natives.js in the v8.vcproj project.
--- /dev/null
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="essential"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)\obj\$(ProjectName)"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="$(ProjectDir)\..\..\src;$(IntDir)\DerivedSources"
+ PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_USE_32BIT_TIME_T;_HAS_EXCEPTIONS=0;PCRE_STATIC;ENABLE_LOGGING_AND_PROFILING"
+ MinimalRebuild="false"
+ ExceptionHandling="0"
+ RuntimeTypeInfo="false"
+ WarningLevel="3"
+ WarnAsError="true"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ DisableSpecificWarnings="4355;4800"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="true"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)\lib\$(ProjectName).lib"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ GenerateDebugInformation="true"
+ MapFileName="$(OutDir)\$(TargetName).map"
+ ImportLibrary="$(OutDir)\lib\$(TargetName).lib"
+ TargetMachine="1"
+ FixedBaseAddress="1"
+ AdditionalOptions="/IGNORE:4221 /NXCOMPAT"
+ />
+</VisualStudioPropertySheet>
--- /dev/null
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="debug"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="DEBUG;_DEBUG;ENABLE_DISASSEMBLER"
+ RuntimeLibrary="1"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ />
+</VisualStudioPropertySheet>
--- /dev/null
+@echo off
+set SOURCE_DIR=%1
+set TARGET_DIR=%2
+set PYTHON="..\..\..\third_party\python_24\python.exe"
+if not exist %PYTHON% set PYTHON=python.exe
+%PYTHON% ..\js2c.py %TARGET_DIR%\natives.cc %TARGET_DIR%\natives-empty.cc %SOURCE_DIR%\macros.py %SOURCE_DIR%\runtime.js %SOURCE_DIR%\v8natives.js %SOURCE_DIR%\array.js %SOURCE_DIR%\string.js %SOURCE_DIR%\uri.js %SOURCE_DIR%\math.js %SOURCE_DIR%\messages.js %SOURCE_DIR%\apinatives.js %SOURCE_DIR%\debug-delay.js %SOURCE_DIR%\mirror-delay.js %SOURCE_DIR%\date-delay.js %SOURCE_DIR%\regexp-delay.js
--- /dev/null
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="release"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ RuntimeLibrary="0"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="0"
+ OmitFramePointers="true"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ OptimizeReferences="2"
+ OptimizeForWindows98="1"
+ EnableCOMDATFolding="2"
+ />
+</VisualStudioPropertySheet>
--- /dev/null
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="v8"
+ ProjectGUID="{21E22961-22BF-4493-BD3A-868F93DA5179}"
+ RootNamespace="v8"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets=".\common.vsprops;.\debug.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets=".\common.vsprops;.\release.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="js"
+ >
+ <File
+ RelativePath="..\..\src\apinatives.js"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\array.js"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\date-delay.js"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\debug-delay.js"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\macros.py"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\math.js"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\messages.js"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\mirror-delay.js"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\regexp-delay.js"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\runtime.js"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\string.js"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\uri.js"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\v8natives.js"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Processing js files..."
+ CommandLine=".\js2c.cmd ..\..\src $(IntDir)\DerivedSources"
+ AdditionalDependencies="..\..\src\macros.py;..\..\src\runtime.js;..\..\src\v8natives.js;..\..\src\array.js;..\..\src\string.js;..\..\src\uri.js;..\..\src\math.js;..\..\src\messages.js;..\..\src\apinatives.js;..\..\src\debug-delay.js;..\..\src\mirror-delay.js;..\..\src\date-delay.js;..\..\src\regexp-delay.js"
+ Outputs="$(IntDir)\DerivedSources\natives.cc;$(IntDir)\DerivedSources\natives-empty.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Processing js files..."
+ CommandLine=".\js2c.cmd ..\..\src $(IntDir)\DerivedSources"
+ AdditionalDependencies="..\..\src\macros.py;..\..\src\runtime.js;..\..\src\v8natives.js;..\..\src\array.js;..\..\src\string.js;..\..\src\uri.js;..\..\src\math.js;..\..\src\messages.js;..\..\src\apinatives.js;..\..\src\debug-delay.js;..\..\src\mirror-delay.js;..\..\src\date-delay.js;..\..\src\regexp-delay.js"
+ Outputs="$(IntDir)\DerivedSources\natives.cc;$(IntDir)\DerivedSources\natives-empty.cc"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="generated files"
+ >
+ <File
+ RelativePath="$(IntDir)\DerivedSources\natives.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\prebuild.py"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="..\..\src\snapshot-empty.cc"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
--- /dev/null
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="v8_base"
+ ProjectGUID="{EC8B7909-62AF-470D-A75D-E1D89C837142}"
+ RootNamespace="v8_base"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets=".\common.vsprops;.\debug.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets=".\common.vsprops;.\release.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="jscre"
+ >
+ <File
+ RelativePath="..\..\src\third_party\jscre\pcre_compile.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UndefinePreprocessorDefinitions="DEBUG"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UndefinePreprocessorDefinitions="DEBUG"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\third_party\jscre\pcre_exec.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UndefinePreprocessorDefinitions="DEBUG"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UndefinePreprocessorDefinitions="DEBUG"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\third_party\jscre\pcre_internal.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\third_party\jscre\pcre_tables.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UndefinePreprocessorDefinitions="DEBUG"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UndefinePreprocessorDefinitions="DEBUG"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\third_party\jscre\pcre_ucp_searchfuncs.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UndefinePreprocessorDefinitions="DEBUG"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UndefinePreprocessorDefinitions="DEBUG"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\third_party\jscre\pcre_xclass.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UndefinePreprocessorDefinitions="DEBUG"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ UndefinePreprocessorDefinitions="DEBUG"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="dtoa"
+ >
+ <File
+ RelativePath="..\..\src\dtoa-config.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ DisableSpecificWarnings="4018;4244"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ DisableSpecificWarnings="4018;4244"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="src"
+ >
+ <File
+ RelativePath="..\..\src\accessors.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\accessors.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\allocation.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\allocation.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\api.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\api.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\arguments.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\assembler-arm-inl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\assembler-arm.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\assembler-ia32-inl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\assembler-ia32.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\assembler-ia32.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\assembler.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ast.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ast.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\bootstrapper.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\bootstrapper.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\builtins-ia32.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\builtins.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\builtins.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\char-predicates-inl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\char-predicates.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\checks.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\checks.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\code-stubs.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\code-stubs.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\code.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\codegen-ia32.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\codegen-inl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\codegen.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\codegen.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\compiler.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\compiler.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\contexts.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\contexts.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\conversions-inl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\conversions.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\conversions.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\counters.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\counters.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\cpu-ia32.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\cpu.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\dateparser.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\dateparser.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\debug.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\debug.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\disassembler.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\disassembler.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\execution.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\execution.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\factory.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\factory.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\flags.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\flags.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\frames-arm-inl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\frames-arm.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\frames-ia32-inl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\frames-ia32.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\frames-ia32.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\frames-inl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\frames.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\frames.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\global-handles.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\global-handles.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\globals.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\handles-inl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\handles.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\handles.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\hashmap.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\hashmap.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\heap-inl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\heap.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\heap.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ic-ia32.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ic-inl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ic.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\ic.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\interceptors.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\jsregexp.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\jsregexp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\list-inl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\list.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\log.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\log.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\macro-assembler-arm.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\macro-assembler-ia32.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\macro-assembler-ia32.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\macro-assembler.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\mark-compact.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\mark-compact.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\memory.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\messages.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\messages.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\natives.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\objects-debug.cc"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\objects-inl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\objects.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\objects.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\parser.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\parser.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\platform-win32.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\platform.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\prettyprinter.cc"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\src\prettyprinter.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\property.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\property.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\rewriter.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\rewriter.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\runtime.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\runtime.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\scanner.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\scanner.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\scopeinfo.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\scopeinfo.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\scopes.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\scopes.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\serialize.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\serialize.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\shell.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\snapshot-common.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\snapshot.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\spaces-inl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\spaces.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\spaces.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\string-stream.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\string-stream.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\stub-cache-ia32.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\stub-cache.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\stub-cache.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\token.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\token.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\top.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\top.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\unicode-inl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\unicode.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\usage-analyzer.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\usage-analyzer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\utils.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\utils.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\v8-counters.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\v8-counters.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\v8.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\v8.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\v8threads.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\v8threads.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\variables.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\variables.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\zone-inl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\zone.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\zone.h"
+ >
+ </File>
+ <Filter
+ Name="third party"
+ >
+ <File
+ RelativePath="..\..\src\disasm-ia32.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\disasm.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="generated files"
+ >
+ <File
+ RelativePath="..\..\src\unicode.cc"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="public"
+ >
+ <File
+ RelativePath="..\public\debug.h"
+ >
+ </File>
+ <File
+ RelativePath="..\public\v8.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
--- /dev/null
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="v8_mksnapshot"
+ ProjectGUID="{865575D0-37E2-405E-8CBA-5F6C485B5A26}"
+ RootNamespace="v8_mksnapshot"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets=".\common.vsprops;.\debug.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="1"
+ InheritedPropertySheets=".\common.vsprops;.\release.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\..\src\mksnapshot.cc"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
--- /dev/null
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="v8_snapshot"
+ ProjectGUID="{C0334F9A-1168-4101-9DD8-C30FB252D435}"
+ RootNamespace="v8_snapshot"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets=".\common.vsprops;.\debug.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ ConfigurationType="4"
+ InheritedPropertySheets=".\common.vsprops;.\release.vsprops"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="generated files"
+ >
+ <File
+ RelativePath="$(IntDir)\..\v8\DerivedSources\natives-empty.cc"
+ >
+ </File>
+ <File
+ RelativePath="$(IntDir)\DerivedSources\snapshot.cc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="$(SolutionDir)..\v8\src"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="$(SolutionDir)..\v8\src"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <File
+ RelativePath="$(OutDir)\mksnapshot.exe"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Building snapshot..."
+ CommandLine="$(OutDir)\v8_mksnapshot.exe $(IntDir)\DerivedSources\snapshot.cc"
+ Outputs="$(IntDir)\DerivedSources\snapshot.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Building snapshot..."
+ CommandLine="$(OutDir)\v8_mksnapshot.exe $(IntDir)\DerivedSources\snapshot.cc"
+ Outputs="$(IntDir)\DerivedSources\snapshot.cc"
+ />
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>