Improved performance of unary addition by avoiding runtime calls.

Fixed the handling of '>' and '<=' to use right-to-left conversion and left-to-right evaluation as specified by ECMA-262.

Fixed a branch elimination bug on the ARM platform where incorrect code was generated because of overly aggressive branch elimination.

Improved performance of code that repeatedly assigns the same function to the same property of different objects with the same map.

Untangled DEBUG and ENABLE_DISASSEMBLER defines.  The disassembler no longer expects DEBUG to be defined.

Added platform-nullos.cc to serve as the basis for new platform implementations.


git-svn-id: http://v8.googlecode.com/svn/trunk@9 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index f04d709..021ea61 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2008-08-06: Version 0.2.1 (130029)
+
+        Improved performance of unary addition by avoiding runtime calls.
+
+        Fixed the handling of '>' and '<=' to use right-to-left conversion
+        and left-to-right evaluation as specified by ECMA-262.
+
+        Fixed a branch elimination bug on the ARM platform where incorrect
+        code was generated because of overly aggressive branch
+        elimination.
+
+        Improved performance of code that repeatedly assigns the same
+        function to the same property of different objects with the same
+        map.
+
+        Untangled DEBUG and ENABLE_DISASSEMBLER defines.  The disassembler
+        no longer expects DEBUG to be defined.
+
+        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.
diff --git a/src/SConscript b/src/SConscript
index 20e0c71..d784fa4 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -233,6 +233,7 @@
   'arch:ia32': ['assembler-ia32.cc', 'builtins-ia32.cc', 'codegen-ia32.cc', 'cpu-ia32.cc', 'disasm-ia32.cc', 'frames-ia32.cc', 'ic-ia32.cc', 'macro-assembler-ia32.cc', 'simulator-ia32.cc', 'stub-cache-ia32.cc'],
   'os:linux': ['platform-linux.cc'],
   'os:macos': ['platform-macos.cc'],
+  'os:nullos': ['platform-nullos.cc'],
   'os:win32': ['platform-win32.cc']
 }
 
diff --git a/src/api.cc b/src/api.cc
index 06e8d2f..8051962 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -2091,7 +2091,7 @@
 
 
 const char* v8::V8::GetVersion() {
-  return "0.2.0 (129146)";
+  return "0.2.1 (130029)";
 }
 
 
diff --git a/src/assembler-arm.cc b/src/assembler-arm.cc
index 9e946ed..d92e35c 100644
--- a/src/assembler-arm.cc
+++ b/src/assembler-arm.cc
@@ -711,12 +711,12 @@
 }
 
 
-int Assembler::branch_offset(Label* L, Condition cond) {
+int Assembler::branch_offset(Label* L, bool jump_elimination_allowed) {
   // if we emit an unconditional jump/call and if the current position is the
   // target of the unbound label, we can change the binding position of the
   // unbound label, thereby eliminating an unnessary jump
   bool can_eliminate = false;
-  if (cond == al && FLAG_eliminate_jumps &&
+  if (jump_elimination_allowed && FLAG_eliminate_jumps &&
       unbound_label_.is_linked() && binding_pos_ == pc_offset()) {
     can_eliminate = true;
     if (FLAG_print_jump_elimination) {
diff --git a/src/assembler-arm.h b/src/assembler-arm.h
index d5d0493..e3f5692 100644
--- a/src/assembler-arm.h
+++ b/src/assembler-arm.h
@@ -177,6 +177,31 @@
 INLINE(Condition NegateCondition(Condition cc));
 
 
+// Corresponds to transposing the operands of a comparison.
+inline Condition ReverseCondition(Condition cc) {
+  switch (cc) {
+    case lo:
+      return hi;
+    case hi:
+      return lo;
+    case hs:
+      return ls;
+    case ls:
+      return hs;
+    case lt:
+      return gt;
+    case gt:
+      return lt;
+    case ge:
+      return le;
+    case le:
+      return ge;
+    default:
+      return cc;
+  };
+}
+
+
 // The pc store offset may be 8 or 12 depending on the processor implementation.
 int PcStoreOffset();
 
@@ -371,8 +396,8 @@
 
   // Returns the branch offset to the given label from the current code position
   // Links the label to the current position if it is still unbound
-  // Manages the jump elimination optimization if necessary
-  int branch_offset(Label* L, Condition cond);
+  // Manages the jump elimination optimization if the second parameter is true.
+  int branch_offset(Label* L, bool jump_elimination_allowed);
 
   // Return the address in the constant pool of the code target address used by
   // the branch/call instruction at pc.
@@ -403,11 +428,13 @@
   void bx(Register target, Condition cond = al);  // v5 and above, plus v4t
 
   // Convenience branch instructions using labels
-  void b(Label* L, Condition cond = al)  { b(branch_offset(L, cond), cond); }
-  void b(Condition cond, Label* L)  { b(branch_offset(L, cond), cond); }
-  void bl(Label* L, Condition cond = al)  { bl(branch_offset(L, cond), cond); }
-  void bl(Condition cond, Label* L)  { bl(branch_offset(L, cond), cond); }
-  void blx(Label* L)  { blx(branch_offset(L, al)); }  // v5 and above
+  void b(Label* L, Condition cond = al)  {
+    b(branch_offset(L, cond == al), cond);
+  }
+  void b(Condition cond, Label* L)  { b(branch_offset(L, cond == al), cond); }
+  void bl(Label* L, Condition cond = al)  { bl(branch_offset(L, false), cond); }
+  void bl(Condition cond, Label* L)  { bl(branch_offset(L, false), cond); }
+  void blx(Label* L)  { blx(branch_offset(L, false)); }  // v5 and above
 
   // Data-processing instructions
   void and_(Register dst, Register src1, const Operand& src2,
diff --git a/src/assembler-ia32.cc b/src/assembler-ia32.cc
index 8af8be1..b9e1bdb 100644
--- a/src/assembler-ia32.cc
+++ b/src/assembler-ia32.cc
@@ -2018,6 +2018,12 @@
 
 void Assembler::RecordRelocInfo(RelocMode rmode, intptr_t data) {
   ASSERT(rmode != no_reloc);
+  // Don't record external references unless the heap will be serialized.
+  if (rmode == external_reference &&
+      !Serializer::enabled() &&
+      !FLAG_debug_code) {
+    return;
+  }
   RelocInfo rinfo(pc_, rmode, data);
   reloc_info_writer.Write(&rinfo);
 }
diff --git a/src/assembler.cc b/src/assembler.cc
index d407007..b3c8afb 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -400,7 +400,7 @@
 // Implementation of RelocInfo
 
 
-#ifdef DEBUG
+#ifdef ENABLE_DISASSEMBLER
 const char* RelocInfo::RelocModeName(RelocMode rmode) {
   switch (rmode) {
     case no_reloc:
@@ -435,8 +435,10 @@
   }
   return "unknown relocation type";
 }
+#endif  // ENABLE_DISASSEMBLER
 
 
+#ifdef DEBUG
 void RelocInfo::Print() {
   PrintF("%p  %s", pc_, RelocModeName(rmode_));
   if (rmode_ == comment) {
diff --git a/src/assembler.h b/src/assembler.h
index 5c3267b..a149f8c 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -268,11 +268,14 @@
   void patch_code_with_call(Address target, int guard_bytes);
   INLINE(bool is_call_instruction());
 
+#ifdef ENABLE_DISASSEMBLER
+  // Printing
+  static const char* RelocModeName(RelocMode rmode);
+#endif  // ENABLE_DISASSEMBLER
 #ifdef DEBUG
   // Debugging
   void Print();
   void Verify();
-  static const char* RelocModeName(RelocMode rmode);
 #endif
 
   static const int kCodeTargetMask = (1 << (last_code_enum + 1)) - 1;
diff --git a/src/builtins-arm.cc b/src/builtins-arm.cc
index 562d906..4cb54f5 100644
--- a/src/builtins-arm.cc
+++ b/src/builtins-arm.cc
@@ -78,17 +78,14 @@
   __ sub(r1, r1, Operand(1), SetCC);
   __ b(ge, &loop);
 
-  // Get the function to call from the stack and get the code from it.
+  // Get the function to call from the stack.
   __ ldr(r1, MemOperand(pp, JavaScriptFrameConstants::kFunctionOffset));
-  __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
-  __ ldr(r1, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
-  __ ldr(r1, FieldMemOperand(r1, SharedFunctionInfo::kCodeOffset));
-  __ add(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag));
 
   // Call the function.
   Label return_site;
   __ RecordPosition(position);
-  __ Call(r1);
+  ParameterCount actual(r0);
+  __ InvokeFunction(r1, actual, CALL_FUNCTION);
   __ bind(&return_site);
 
   // Restore context from the frame and discard the function.
@@ -161,10 +158,11 @@
   __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
 
   // Push the function and the receiver onto the stack.
-  __ mov(r5, Operand(r1));  // change save order: function above receiver
-  __ stm(db_w, sp, r2.bit() | r5.bit());
+  __ push(r1);
+  __ push(r2);
 
   // Copy arguments to the stack in a loop.
+  // r1: function
   // r3: argc
   // r4: argv, i.e. points to first arg
   Label loop, entry;
@@ -172,9 +170,9 @@
   // r2 points past last arg.
   __ b(&entry);
   __ bind(&loop);
-  __ ldr(r1, MemOperand(r4, kPointerSize, PostIndex));  // read next parameter
-  __ ldr(r1, MemOperand(r1));  // dereference handle
-  __ push(r1);  // push parameter
+  __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex));  // read next parameter
+  __ ldr(r0, MemOperand(r0));  // dereference handle
+  __ push(r0);  // push parameter
   __ bind(&entry);
   __ cmp(r4, Operand(r2));
   __ b(ne, &loop);
@@ -194,9 +192,8 @@
     __ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)),
             code_target);
   } else {
-    __ mov(ip, Operand(r0));
-    __ mov(r0, Operand(r3));
-    __ Call(ip);
+    ParameterCount actual(r3);
+    __ InvokeFunction(r1, actual, CALL_FUNCTION);
   }
 
   // Exit the JS frame and remove the parameters (except function), and return.
diff --git a/src/codegen-arm.cc b/src/codegen-arm.cc
index 5976426..4513291 100644
--- a/src/codegen-arm.cc
+++ b/src/codegen-arm.cc
@@ -2033,7 +2033,14 @@
   ASSERT(!strict || cc == eq);
 
   Label exit, smi;
-  __ pop(r1);
+  // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
+  if (cc == gt || cc == le) {
+    cc = ReverseCondition(cc);
+    __ mov(r1, Operand(r0));
+    __ pop(r0);
+  } else {
+    __ pop(r1);
+  }
   __ orr(r2, r0, Operand(r1));
   __ tst(r2, Operand(kSmiTagMask));
   __ b(eq, &smi);
@@ -2100,14 +2107,15 @@
 void CallFunctionStub::Generate(MacroAssembler* masm) {
   Label slow;
 
-  // Push the number of arguments.
-  masm->Push(Operand(argc_));
+  // Flush the TOS cache
+  masm->push(r0);
 
   // Get the function to call from the stack.
-  // function, receiver [, arguments], argc_
+  // function, receiver [, arguments]
   masm->ldr(r1, MemOperand(sp, (argc_ + 1) * kPointerSize));
 
   // Check that the function is really a JavaScript function.
+  // r1: pushed function (to be verified)
   masm->tst(r1, Operand(kSmiTagMask));
   masm->b(eq, &slow);
   // Get the map of the function object.
@@ -2117,15 +2125,13 @@
   masm->b(ne, &slow);
 
   // Fast-case: Invoke the function now.
-  masm->ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
-  masm->ldr(r1, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
-  masm->ldr(r1,
-            MemOperand(r1, SharedFunctionInfo::kCodeOffset - kHeapObjectTag));
-  masm->add(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag));
-  masm->Jump(r1);  // Callee will return to the original call site directly.
+  // r1: pushed function
+  ParameterCount actual(argc_);
+  masm->InvokeFunction(r1, actual, JUMP_FUNCTION);
 
   // Slow-case: Non-function called.
   masm->bind(&slow);
+  masm->mov(r0, Operand(argc_));  // Setup the number of arguments.
   masm->InvokeBuiltin("CALL_NON_FUNCTION", 0, JUMP_JS);
 }
 
diff --git a/src/codegen-ia32.cc b/src/codegen-ia32.cc
index aee8304..e240a13 100644
--- a/src/codegen-ia32.cc
+++ b/src/codegen-ia32.cc
@@ -2304,9 +2304,16 @@
   // Strict only makes sense for equality comparisons.
   ASSERT(!strict || cc == equal);
 
+  // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
+  if (cc == greater || cc == less_equal) {
+    cc = ReverseCondition(cc);
+    __ pop(edx);
+    __ pop(eax);
+  } else {
+    __ pop(eax);
+    __ pop(edx);
+  }
   ComparisonDeferred* deferred = new ComparisonDeferred(this, cc, strict);
-  __ pop(eax);
-  __ pop(edx);
   __ mov(ecx, Operand(eax));
   __ or_(ecx, Operand(edx));
   __ test(ecx, Immediate(kSmiTagMask));
@@ -4354,10 +4361,20 @@
         __ mov(TOS, Factory::undefined_value());
         break;
 
-      case Token::ADD:
+      case Token::ADD: {
+        // Smi check.
+        Label continue_label;
+        __ pop(eax);
+        __ test(eax, Immediate(kSmiTagMask));
+        __ j(zero, &continue_label);
+
+        __ push(eax);
         __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
+
+        __ bind(&continue_label);
         __ push(eax);
         break;
+      }
 
       default:
         UNREACHABLE();
diff --git a/src/debug.cc b/src/debug.cc
index b0e47cb..7901ca1 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -1742,9 +1742,7 @@
 // The new copy of the event string is destroyed in Run().
 void DebugMessageThread::SendMessage(Vector<uint16_t> message) {
   Vector<uint16_t> message_copy = message.Clone();
-  if (FLAG_log_debugger) {
-    Logger::StringEvent("Put message on event message_queue.", "");
-  }
+  Logger::DebugTag("Put message on event message_queue.");
   message_queue_.Put(message_copy);
   message_received_->Signal();
 }
@@ -1801,9 +1799,7 @@
   while (true) {
     // Wait and Get are paired so that semaphore count equals queue length.
     message_received_->Wait();
-    if (FLAG_log_debugger) {
-      Logger::StringEvent("Get message from event message_queue.", "");
-    }
+    Logger::DebugTag("Get message from event message_queue.");
     Vector<uint16_t> message = message_queue_.Get();
     if (message.length() > 0) {
       Debugger::SendMessage(message);
@@ -1867,11 +1863,7 @@
     // Drain queue.
     while (!command_queue_.IsEmpty()) {
       command_received_->Wait();
-      if (FLAG_log_debugger) {
-        Logger::StringEvent(
-            "Get command from command_queue, in drain queue loop.",
-            "");
-      }
+      Logger::DebugTag("Get command from command_queue, in drain queue loop.");
       Vector<uint16_t> command = command_queue_.Get();
       // Support for sending a break command as just "break" instead of an
       // actual JSON break command.
@@ -1921,11 +1913,7 @@
   // Wait for commands from the debugger.
   while (true) {
     command_received_->Wait();
-    if (FLAG_log_debugger) {
-      Logger::StringEvent(
-          "Get command from command queue, in interactive loop.",
-          "");
-    }
+    Logger::DebugTag("Get command from command queue, in interactive loop.");
     Vector<uint16_t> command = command_queue_.Get();
     ASSERT(!host_running_);
     if (!Debugger::debugger_active()) {
@@ -2002,9 +1990,7 @@
 // The new copy of the command is destroyed in HandleCommand().
 void DebugMessageThread::ProcessCommand(Vector<uint16_t> command) {
   Vector<uint16_t> command_copy = command.Clone();
-  if (FLAG_log_debugger) {
-    Logger::StringEvent("Put command on command_queue.", "");
-  }
+  Logger::DebugTag("Put command on command_queue.");
   command_queue_.Put(command_copy);
   // If not in a break schedule a break and send the "request queued" response.
   if (host_running_) {
@@ -2084,11 +2070,7 @@
 Vector<uint16_t> LockingMessageQueue::Get() {
   ScopedLock sl(lock_);
   Vector<uint16_t> result = queue_.Get();
-  // Logging code for debugging debugger.
-  if (FLAG_log_debugger) {
-    LogQueueOperation("Get", result);
-  }
-
+  Logger::DebugEvent("Get", result);
   return result;
 }
 
@@ -2096,10 +2078,7 @@
 void LockingMessageQueue::Put(const Vector<uint16_t>& message) {
   ScopedLock sl(lock_);
   queue_.Put(message);
-  // Logging code for debugging debugger.
-  if (FLAG_log_debugger) {
-    LogQueueOperation("Put", message);
-  }
+  Logger::DebugEvent("Put", message);
 }
 
 
@@ -2109,17 +2088,4 @@
 }
 
 
-void LockingMessageQueue::LogQueueOperation(const char* operation_name,
-                                            Vector<uint16_t> parameter) {
-  StringBuilder s(23+parameter.length()+strlen(operation_name) +1);
-  s.AddFormatted("Time: %f15.3 %s ", OS::TimeCurrentMillis(), operation_name);
-  for (int i = 0; i < parameter.length(); ++i) {
-    s.AddCharacter(static_cast<char>(parameter[i]));
-  }
-  char* result_string = s.Finalize();
-  Logger::StringEvent(result_string, "");
-  DeleteArray(result_string);
-}
-
-
 } }  // namespace v8::internal
diff --git a/src/debug.h b/src/debug.h
index 94ad17b..d7d267a 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -407,7 +407,7 @@
 // LockingMessageQueue is a thread-safe circular buffer of Vector<uint16_t>
 // messages.  The message data is not managed by LockingMessageQueue.
 // Pointers to the data are passed in and out. Implemented by adding a
-// Mutex to MessageQueue.
+// Mutex to MessageQueue.  Includes logging of all puts and gets.
 class LockingMessageQueue BASE_EMBEDDED {
  public:
   explicit LockingMessageQueue(int size);
@@ -417,9 +417,6 @@
   void Put(const Vector<uint16_t>& message);
   void Clear();
  private:
-  // Logs a timestamp, operation name, and operation argument
-  void LogQueueOperation(const char* operation_name,
-                                              Vector<uint16_t> parameter);
   MessageQueue queue_;
   Mutex* lock_;
   DISALLOW_EVIL_CONSTRUCTORS(LockingMessageQueue);
diff --git a/src/disassembler.cc b/src/disassembler.cc
index 82c5964..dba4a3d 100644
--- a/src/disassembler.cc
+++ b/src/disassembler.cc
@@ -224,9 +224,8 @@
               ASSERT(obj->IsSmi());
               // Get the STUB key and extract major and minor key.
               uint32_t key = Smi::cast(obj)->value();
-              CodeStub::Major major_key = code->major_key();
               uint32_t minor_key = CodeStub::MinorKeyFromKey(key);
-              ASSERT(major_key == CodeStub::MajorKeyFromKey(key));
+              ASSERT(code->major_key() == CodeStub::MajorKeyFromKey(key));
               out.AddFormatted(" (%s, %s, ",
                                Code::Kind2String(kind),
                                CodeStub::MajorName(code->major_key()));
diff --git a/src/frames-ia32.h b/src/frames-ia32.h
index 1b9d2f2..0e9176c 100644
--- a/src/frames-ia32.h
+++ b/src/frames-ia32.h
@@ -111,7 +111,7 @@
   static const int kSavedRegistersOffset = +2 * kPointerSize;
   static const int kFunctionOffset = StandardFrameConstants::kMarkerOffset;
 
-  // PP-relative.
+  // CallerSP-relative (aka PP-relative)
   static const int kParam0Offset   = -2 * kPointerSize;
   static const int kReceiverOffset = -1 * kPointerSize;
 };
diff --git a/src/heap.cc b/src/heap.cc
index 058c084..2c7660d 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -2420,7 +2420,7 @@
 
   // The new space size must be a power of two to support single-bit testing
   // for containment.
-  semispace_size_ = NextPowerOf2(semispace_size_);
+  semispace_size_ = RoundUpToPowerOf2(semispace_size_);
   initial_semispace_size_ = Min(initial_semispace_size_, semispace_size_);
   young_generation_size_ = 2 * semispace_size_;
 
diff --git a/src/heap.h b/src/heap.h
index 1afa96e..ebce468 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -985,15 +985,18 @@
 
   void clear_overflowed() { overflowed_ = false; }
 
-  void Push(HeapObject* p) {
+  void Push(HeapObject* object) {
     ASSERT(!is_full());
-    *(top_++) = p;
+    CHECK(object->IsHeapObject());
+    *(top_++) = object;
     if (is_full()) overflowed_ = true;
   }
 
   HeapObject* Pop() {
     ASSERT(!is_empty());
-    return *(--top_);
+    HeapObject* object = *(--top_);
+    CHECK(object->IsHeapObject());
+    return object;
   }
 
  private:
diff --git a/src/ic-arm.cc b/src/ic-arm.cc
index 6c22849..d39808e 100644
--- a/src/ic-arm.cc
+++ b/src/ic-arm.cc
@@ -340,7 +340,6 @@
 
 void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
   // ----------- S t a t e -------------
-  //  -- r0: number of arguments
   //  -- r1: receiver
   //  -- lr: return address
   // -----------------------------------
@@ -348,11 +347,7 @@
   Label miss, probe, done, global;
 
   // Get the name of the function from the stack; 1 ~ receiver.
-  __ add(ip, sp, Operand(r0, LSL, kPointerSizeLog2));
-  __ ldr(r2, MemOperand(ip, 1 * kPointerSize));
-
-  // Push the number of arguments on the stack to free r0.
-  __ push(r0);
+  __ ldr(r2, MemOperand(sp, (argc + 1) * kPointerSize));
 
   // Check that the receiver isn't a smi.
   __ tst(r1, Operand(kSmiTagMask));
@@ -385,33 +380,20 @@
   __ cmp(r0, Operand(JS_FUNCTION_TYPE));
   __ b(ne, &miss);
 
-  // Restore the number of arguments.
-  __ pop(r0);
-
   // Patch the function on the stack; 1 ~ receiver.
-  __ add(ip, sp, Operand(r0, LSL, kPointerSizeLog2));
-  __ str(r1, MemOperand(ip, 1 * kPointerSize));
+  __ str(r1, MemOperand(sp, (argc + 1) * kPointerSize));
 
-  // Get the context and call code from the function.
-  __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
-  __ ldr(r1, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
-  __ ldr(r1, FieldMemOperand(r1, SharedFunctionInfo::kCodeOffset));
-
-  // Jump to the code.
-  __ add(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag));
-  __ Jump(r1);
+  // Invoke the function.
+  ParameterCount actual(argc);
+  __ InvokeFunction(r1, actual, JUMP_FUNCTION);
 
   // Global object access: Check access rights.
   __ bind(&global);
   __ CheckAccessGlobal(r1, r0, &miss);
   __ b(&probe);
 
-  // Cache miss: Restore number of arguments and receiver from stack
-  // and jump to runtime.
+  // Cache miss: Jump to runtime.
   __ bind(&miss);
-  __ pop(r0);
-  __ add(ip, sp, Operand(r0, LSL, kPointerSizeLog2));
-  __ ldr(r1, MemOperand(ip));
   Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
 }
 
@@ -420,14 +402,13 @@
                       int argc,
                       const ExternalReference& f) {
   // ----------- S t a t e -------------
-  //  -- r0: number of arguments
   //  -- lr: return address
   // -----------------------------------
 
   // Get the receiver of the function from the stack into r1.
-  __ add(ip, sp, Operand(r0, LSL, kPointerSizeLog2));
-  __ ldr(r1, MemOperand(ip, 0 * kPointerSize));
+  __ ldr(r1, MemOperand(sp, argc * kPointerSize));
 
+  __ mov(r0, Operand(argc));  // Setup number of arguments for EnterJSFrame.
   __ EnterJSFrame(0);
 
   // Push the receiver and the name of the function.
@@ -442,25 +423,17 @@
   CEntryStub stub;
   __ CallStub(&stub);
 
-  // Move result to r1 and restore number of arguments.
+  // Move result to r1.
   __ mov(r1, Operand(r0));
-  __ ldr(r0, MemOperand(v8::internal::fp,  // fp is shadowed by IC::fp
-                        JavaScriptFrameConstants::kArgsLengthOffset));
 
   __ ExitJSFrame(DO_NOT_RETURN);
 
   // Patch the function on the stack; 1 ~ receiver.
-  __ add(ip, sp, Operand(r0, LSL, kPointerSizeLog2));
-  __ str(r1, MemOperand(ip, 1 * kPointerSize));
+  __ str(r1, MemOperand(sp, (argc + 1) * kPointerSize));
 
-  // Get the context and call code from the function.
-  __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
-  __ ldr(r1, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
-  __ ldr(r1, FieldMemOperand(r1, SharedFunctionInfo::kCodeOffset));
-
-  // Jump to the code.
-  __ add(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag));
-  __ Jump(r1);
+  // Invoke the function.
+  ParameterCount actual(argc);
+  __ InvokeFunction(r1, actual, JUMP_FUNCTION);
 }
 
 
diff --git a/src/ic-ia32.cc b/src/ic-ia32.cc
index 97811cb..38216b5 100644
--- a/src/ic-ia32.cc
+++ b/src/ic-ia32.cc
@@ -503,9 +503,8 @@
   __ CheckAccessGlobal(edx, eax, &miss);
   __ jmp(&probe);
 
-  // Cache miss: Restore receiver from stack and jump to runtime.
+  // Cache miss: Jump to runtime.
   __ bind(&miss);
-  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));  // 1 ~ return address
   Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
 }
 
diff --git a/src/log.cc b/src/log.cc
index a13f9d6..abac0aa 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -45,7 +45,6 @@
 DEFINE_bool(log_api, false, "Log API events to the log file.");
 DEFINE_bool(log_code, false,
             "Log code events to the log file without profiling.");
-DEFINE_bool(log_debugger, false, "Log debugger internal messages.");
 DEFINE_bool(log_gc, false,
             "Log heap samples on garbage collection for the hp2ps tool.");
 DEFINE_bool(log_handles, false, "Log global handle events.");
@@ -564,6 +563,34 @@
 }
 
 
+void Logger::DebugTag(const char* call_site_tag) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL) return;
+  ScopedLock sl(mutex_);
+  fprintf(logfile_, "debug-tag,%s\n", call_site_tag);
+#endif
+}
+
+
+void Logger::DebugEvent(const char* event_type, Vector<uint16_t> parameter) {
+#ifdef ENABLE_LOGGING_AND_PROFILING
+  if (logfile_ == NULL) return;
+  StringBuilder s(parameter.length() + 1);
+  for (int i = 0; i < parameter.length(); ++i) {
+    s.AddCharacter(static_cast<char>(parameter[i]));
+  }
+  char* parameter_string = s.Finalize();
+  ScopedLock sl(mutex_);
+  fprintf(logfile_,
+          "debug-queue-event,%s,%15.3f,%s\n",
+          event_type,
+          OS::TimeCurrentMillis(),
+          parameter_string);
+  DeleteArray(parameter_string);
+#endif
+}
+
+
 #ifdef ENABLE_LOGGING_AND_PROFILING
 void Logger::TickEvent(TickSample* sample, bool overflow) {
   if (logfile_ == NULL) return;
@@ -592,7 +619,7 @@
 
   // Each of the individual log flags implies --log.  Check after
   // checking --log-all and --prof in case they set --log-code.
-  if (FLAG_log_api || FLAG_log_code || FLAG_log_debugger || FLAG_log_gc ||
+  if (FLAG_log_api || FLAG_log_code || FLAG_log_gc ||
       FLAG_log_handles || FLAG_log_suspect) {
     FLAG_log = true;
   }
diff --git a/src/log.h b/src/log.h
index b5918fe..ec1c684 100644
--- a/src/log.h
+++ b/src/log.h
@@ -49,9 +49,6 @@
 // Log code (create, move, and delete) events to the logfile, default is off.
 // --log-code implies --log.
 //
-// --log-debugger
-// Log the internal activity of the debugger, to aid in debugging the debugger.
-//
 // --log-gc
 // Log GC heap samples after each GC that can be processed by hp2ps, default
 // is off.  --log-gc implies --log.
@@ -135,6 +132,11 @@
   // object.
   static void SuspectReadEvent(String* name, String* obj);
 
+  // Emits an event when a message is put on or read from a debugging queue.
+  // DebugTag lets us put a call-site specific label on the event.
+  static void DebugTag(const char* call_site_tag);
+  static void DebugEvent(const char* event_type, Vector<uint16_t> parameter);
+
 
   // ==== Events logged by --log-api. ====
   static void ApiNamedSecurityCheck(Object* key);
diff --git a/src/macro-assembler-arm.cc b/src/macro-assembler-arm.cc
index 16003c0..bf81510 100644
--- a/src/macro-assembler-arm.cc
+++ b/src/macro-assembler-arm.cc
@@ -364,6 +364,95 @@
 }
 
 
+void MacroAssembler::InvokePrologue(const ParameterCount& expected,
+                                    const ParameterCount& actual,
+                                    Handle<Code> code_constant,
+                                    Register code_reg,
+                                    Label* done,
+                                    InvokeFlag flag) {
+  if (actual.is_immediate()) {
+    mov(r0, Operand(actual.immediate()));  // Push the number of arguments.
+  } else {
+    if (!actual.reg().is(r0)) {
+      mov(r0, Operand(actual.reg()));
+    }
+  }
+}
+
+
+void MacroAssembler::InvokeCode(Register code,
+                                const ParameterCount& expected,
+                                const ParameterCount& actual,
+                                InvokeFlag flag) {
+  Label done;
+
+  InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag);
+  if (flag == CALL_FUNCTION) {
+    Call(code);
+  } else {
+    ASSERT(flag == JUMP_FUNCTION);
+    Jump(code);
+  }
+
+  // Continue here if InvokePrologue does handle the invocation due to
+  // mismatched parameter counts.
+  bind(&done);
+}
+
+
+void MacroAssembler::InvokeCode(Handle<Code> code,
+                                const ParameterCount& expected,
+                                const ParameterCount& actual,
+                                RelocMode rmode,
+                                InvokeFlag flag) {
+  Label done;
+
+  InvokePrologue(expected, actual, code, no_reg, &done, flag);
+  if (flag == CALL_FUNCTION) {
+    Call(code, rmode);
+  } else {
+    Jump(code, rmode);
+  }
+
+  // Continue here if InvokePrologue does handle the invocation due to
+  // mismatched parameter counts.
+  bind(&done);
+}
+
+
+void MacroAssembler::InvokeFunction(Register fun,
+                                    const ParameterCount& actual,
+                                    InvokeFlag flag) {
+  // Contract with called JS functions requires that function is passed in r1.
+  ASSERT(fun.is(r1));
+
+  Register code_reg = r3;
+  Register expected_reg = r2;
+
+  // Make sure that the code and expected registers do not collide with the
+  // actual register being passed in.
+  if (actual.is_reg()) {
+    if (actual.reg().is(code_reg)) {
+      code_reg = r4;
+    } else if (actual.reg().is(expected_reg)) {
+      expected_reg = r4;
+    }
+  }
+
+  ldr(code_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
+  ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
+  ldr(expected_reg,
+      FieldMemOperand(code_reg,
+                      SharedFunctionInfo::kFormalParameterCountOffset));
+  ldr(code_reg,
+      MemOperand(code_reg, SharedFunctionInfo::kCodeOffset - kHeapObjectTag));
+  add(code_reg, code_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
+
+  ParameterCount expected(expected_reg);
+  InvokeCode(code_reg, expected, actual, flag);
+}
+
+
 void MacroAssembler::SaveRegistersToMemory(RegList regs) {
   ASSERT((regs & ~kJSCallerSaved) == 0);
   // Copy the content of registers to memory location.
diff --git a/src/macro-assembler-arm.h b/src/macro-assembler-arm.h
index a201359..60a827d 100644
--- a/src/macro-assembler-arm.h
+++ b/src/macro-assembler-arm.h
@@ -39,6 +39,11 @@
 
 
 // Helper types to make boolean flag easier to read at call-site.
+enum InvokeFlag {
+  CALL_FUNCTION,
+  JUMP_FUNCTION
+};
+
 enum InvokeJSFlags {
   CALL_JS,
   JUMP_JS
@@ -104,6 +109,35 @@
   void Pop(const MemOperand& dst);
 
   // ---------------------------------------------------------------------------
+  // JavaScript invokes
+
+  // Helper functions for generating invokes.
+  void InvokePrologue(const ParameterCount& expected,
+                      const ParameterCount& actual,
+                      Handle<Code> code_constant,
+                      Register code_reg,
+                      Label* done,
+                      InvokeFlag flag);
+
+  // Invoke the JavaScript function code by either calling or jumping.
+  void InvokeCode(Register code,
+                  const ParameterCount& expected,
+                  const ParameterCount& actual,
+                  InvokeFlag flag);
+
+  void InvokeCode(Handle<Code> code,
+                  const ParameterCount& expected,
+                  const ParameterCount& actual,
+                  RelocMode rmode,
+                  InvokeFlag flag);
+
+  // Invoke the JavaScript function in the given register. Changes the
+  // current context to the context in the function before invoking.
+  void InvokeFunction(Register function,
+                      const ParameterCount& actual,
+                      InvokeFlag flag);
+
+  // ---------------------------------------------------------------------------
   // Debugger Support
 
   void SaveRegistersToMemory(RegList regs);
diff --git a/src/macros.py b/src/macros.py
index ba54b2c..32f714c 100644
--- a/src/macros.py
+++ b/src/macros.py
@@ -86,6 +86,7 @@
 
 # 'Inline' macros
 # (Make sure arg is evaluated only once via %IS_VAR)
+macro NUMBER_IS_NAN(arg)        = (!%_IsSmi(%IS_VAR(arg)) && !(arg == arg));
 macro TO_INTEGER(arg)           = (%_IsSmi(%IS_VAR(arg)) ? arg : ToInteger(arg));
 macro TO_INT32(arg)             = (%_IsSmi(%IS_VAR(arg)) ? arg : ToInt32(arg));
 
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index 93f8ac8..b28ee5e 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -270,12 +270,6 @@
   }
 
  private:
-  // Mark obj if needed.
-  void MarkObject(Object* obj) {
-    if (!obj->IsHeapObject()) return;
-    MarkCompactCollector::MarkObject(HeapObject::cast(obj));
-  }
-
   // Mark object pointed to by p.
   void MarkObjectByPointer(Object** p) {
     Object* obj = *p;
diff --git a/src/math.js b/src/math.js
index 734a442..eb4a4cc 100644
--- a/src/math.js
+++ b/src/math.js
@@ -46,7 +46,13 @@
 function $Math_random() { return %Math_random(0); }
 %AddProperty($Math, "random", $Math_random, DONT_ENUM);
 
-function $Math_abs(x) { return %Math_abs(ToNumber(x)); }
+function $Math_abs(x) {
+  if (%_IsSmi(x)) {
+    return x >= 0 ? x : -x;
+  } else {
+    return %Math_abs(ToNumber(x));
+  }
+}
 %AddProperty($Math, "abs", $Math_abs, DONT_ENUM);
 
 function $Math_acos(x) { return %Math_acos(ToNumber(x)); }
@@ -95,7 +101,7 @@
   var r = -$Infinity;
   for (var i = %_ArgumentsLength() - 1; i >= 0; --i) {
     var n = ToNumber(%_Arguments(i));
-    if (%NumberIsNaN(n)) return n;
+    if (NUMBER_IS_NAN(n)) return n;
     // Make sure +0 is consider greater than -0.
     if (n > r || (n === 0 && r === 0 && (1 / n) > (1 / r))) r = n;
   }
@@ -107,7 +113,7 @@
   var r = $Infinity;
   for (var i = %_ArgumentsLength() - 1; i >= 0; --i) {
     var n = ToNumber(%_Arguments(i));
-    if (%NumberIsNaN(n)) return n;
+    if (NUMBER_IS_NAN(n)) return n;
     // Make sure -0 is consider less than +0.
     if (n < r || (n === 0 && r === 0 && (1 / n) < (1 / r))) r = n;
   }
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index 5d7357e..c70ab16 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -592,22 +592,6 @@
 }
 
 
-const char* Code::Kind2String(Kind kind) {
-  switch (kind) {
-    case FUNCTION: return "FUNCTION";
-    case STUB: return "STUB";
-    case BUILTIN: return "BUILTIN";
-    case LOAD_IC: return "LOAD_IC";
-    case KEYED_LOAD_IC: return "KEYED_LOAD_IC";
-    case STORE_IC: return "STORE_IC";
-    case KEYED_STORE_IC: return "KEYED_STORE_IC";
-    case CALL_IC: return "CALL_IC";
-  }
-  UNREACHABLE();
-  return NULL;
-}
-
-
 void Code::CodePrint() {
   HeapObject::PrintHeader("Code");
   PrintF("kind = %s", Kind2String(kind()));
@@ -995,6 +979,27 @@
 }
 
 
+bool DescriptorArray::IsSortedNoDuplicates() {
+  String* current_key = NULL;
+  uint32_t current = 0;
+  for (DescriptorReader r(this); !r.eos(); r.advance()) {
+    String* key = r.GetKey();
+    if (key == current_key) {
+      PrintDescriptors();
+      return false;
+    }
+    current_key = key;
+    uint32_t hash = r.GetKey()->Hash();
+    if (hash < current) {
+      PrintDescriptors();
+      return false;
+    }
+    current = hash;
+  }
+  return true;
+}
+
+
 #endif  // DEBUG
 
 } }  // namespace v8::internal
diff --git a/src/objects.cc b/src/objects.cc
index b56869d..5527cfb 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -139,6 +139,19 @@
   } else if (IsBoolean()) {
     holder = global_context->boolean_function()->instance_prototype();
   }
+#ifdef DEBUG
+  // Used to track outstanding bug #1308895.
+  // TODO(1308895) Remove when bug is fixed.
+  if (holder == NULL) {
+    PrintF("\nName being looked up: ");
+    name->Print();
+    PrintF("\nThis (object name is looked up in: ");
+    this->Print();
+    if (IsScript()) {
+      PrintF("IsScript() returns true.\n");
+    }
+  }
+#endif
   ASSERT(holder != NULL);  // cannot handle null or undefined.
   JSObject::cast(holder)->Lookup(name, result);
 }
@@ -960,13 +973,29 @@
     return AddSlowProperty(name, value, attributes);
   }
 
+  // Replace a CONSTANT_TRANSITION flag with a transition.
+  // Do this by removing it, and the standard code for adding a map transition
+  // will then run.
+  DescriptorArray* old_descriptors = map()->instance_descriptors();
+  int old_name_index = old_descriptors->Search(name);
+  bool constant_transition = false;  // Only used in assertions.
+  if (old_name_index != DescriptorArray::kNotFound && CONSTANT_TRANSITION ==
+      PropertyDetails(old_descriptors->GetDetails(old_name_index)).type()) {
+    constant_transition = true;
+    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;
+  }
+
   // Compute the new index for new field.
   int index = map()->NextFreePropertyIndex();
 
   // Allocate new instance descriptors with (name, index) added
-  FieldDescriptor fd(name, index, attributes);
+  FieldDescriptor new_field(name, index, attributes);
   Object* new_descriptors =
-      map()->instance_descriptors()->CopyInsert(&fd, true);
+      map()->instance_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
@@ -974,6 +1003,7 @@
   bool allow_map_transition =
         !map()->instance_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());
@@ -1055,8 +1085,34 @@
 
   DescriptorArray* descriptors = DescriptorArray::cast(new_descriptors);
   Map::cast(new_map)->set_instance_descriptors(descriptors);
+  Map* old_map = map();
   set_map(Map::cast(new_map));
 
+  // If the old map is the global object map (from new Object()),
+  // then transitions are not added to it, so we are done.
+  if (old_map == Top::context()->global_context()->object_function()->map()) {
+    return function;
+  }
+
+  // Do not add CONSTANT_TRANSITIONS to global objects
+  if (IsGlobalObject()) {
+    return function;
+  }
+
+  // Add a CONSTANT_TRANSITION descriptor to the old map,
+  // so future assignments to this property on other objects
+  // of the same type will create a normal field, not a constant function.
+  // Don't do this for special properties, with non-trival attributes.
+  if (attributes != NONE) {
+    return function;
+  }
+  ConstTransitionDescriptor mark(name);
+  new_descriptors = old_map->instance_descriptors()->CopyInsert(&mark, false);
+  if (new_descriptors->IsFailure()) {
+    return new_descriptors;
+  }
+  old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
+
   return function;
 }
 
@@ -1356,7 +1412,7 @@
     }
   } else {
     int entry = property_dictionary()->FindStringEntry(name);
-    if (entry != -1) {
+    if (entry != DescriptorArray::kNotFound) {
       // Make sure to disallow caching for uninitialized constants
       // found in the dictionary-mode objects.
       if (property_dictionary()->ValueAt(entry)->IsTheHole()) {
@@ -1494,7 +1550,12 @@
       case INTERCEPTOR:
         return SetPropertyWithInterceptor(name, value, attributes);
       case CONSTANT_TRANSITION:
-        break;
+        // Replace with a MAP_TRANSITION to a new map with a FIELD, even
+        // if the value is a function.
+        // AddProperty has been extended to do this, in this case.
+        return AddFastProperty(name, value, attributes);
+      default:
+        UNREACHABLE();
     }
   }
 
@@ -1731,6 +1792,7 @@
         break;
       }
       default:
+        ASSERT(details.IsTransition());
         break;
     }
   }
@@ -2631,18 +2693,33 @@
 }
 
 
-bool DescriptorArray::IsSortedNoDuplicates() {
-  String* current_key = NULL;
-  uint32_t current = 0;
-  for (DescriptorReader r(this); !r.eos(); r.advance()) {
-    String* key = r.GetKey();
-    if (key == current_key) return false;
-    current_key = key;
-    uint32_t hash = r.GetKey()->Hash();
-    if (hash < current) return false;
-    current = hash;
+Object* DescriptorArray::CopyRemove(String* name) {
+  if (!name->IsSymbol()) {
+    Object* result = Heap::LookupSymbol(name);
+    if (result->IsFailure()) return result;
+    name = String::cast(result);
   }
-  return true;
+  ASSERT(name->IsSymbol());
+  Object* result = Allocate(number_of_descriptors() - 1);
+  if (result->IsFailure()) return result;
+  DescriptorArray* new_descriptors = DescriptorArray::cast(result);
+
+  // Set the enumeration index in the descriptors and set the enumeration index
+  // in the result.
+  new_descriptors->SetNextEnumerationIndex(NextEnumerationIndex());
+
+  // Write the old content and the descriptor information
+  DescriptorWriter w(new_descriptors);
+  DescriptorReader r(this);
+  while (!r.eos()) {
+    if (r.GetKey() != name) {  // Both are symbols; object identity suffices.
+      w.WriteFrom(&r);
+    }
+    r.advance();
+  }
+  ASSERT(w.eos());
+
+  return new_descriptors;
 }
 
 
@@ -3990,6 +4067,25 @@
 }
 
 
+#ifdef ENABLE_DISASSEMBLER
+// Identify kind of code.
+const char* Code::Kind2String(Kind kind) {
+  switch (kind) {
+    case FUNCTION: return "FUNCTION";
+    case STUB: return "STUB";
+    case BUILTIN: return "BUILTIN";
+    case LOAD_IC: return "LOAD_IC";
+    case KEYED_LOAD_IC: return "KEYED_LOAD_IC";
+    case STORE_IC: return "STORE_IC";
+    case KEYED_STORE_IC: return "KEYED_STORE_IC";
+    case CALL_IC: return "CALL_IC";
+  }
+  UNREACHABLE();
+  return NULL;
+}
+#endif  // ENABLE_DISASSEMBLER
+
+
 void JSObject::SetFastElements(FixedArray* elems) {
 #ifdef DEBUG
   // Check the provided array is filled with the_hole.
@@ -5193,7 +5289,7 @@
 
 template<int prefix_size, int element_size>
 Object* HashTable<prefix_size, element_size>::Allocate(int at_least_space_for) {
-  int capacity = NextPowerOf2(at_least_space_for);
+  int capacity = RoundUpToPowerOf2(at_least_space_for);
   if (capacity < 4) capacity = 4;  // Guarantee min capacity.
   Object* obj = Heap::AllocateHashTable(EntryToIndex(capacity));
   if (!obj->IsFailure()) {
diff --git a/src/objects.h b/src/objects.h
index 845bf9d..4b1f8c8 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -96,8 +96,10 @@
   READ_ONLY         = v8::ReadOnly,
   DONT_ENUM         = v8::DontEnum,
   DONT_DELETE       = v8::DontDelete,
-  INTERCEPTED       = 1 << 3,
   ABSENT            = 16  // Used in runtime to indicate a property is absent.
+  // ABSENT can never be stored in or returned from a descriptor's attributes
+  // bitfield.  It is only used as a return value meaning the attributes of
+  // a non-existent property.
 };
 
 namespace v8 { namespace internal {
@@ -1133,6 +1135,8 @@
                                      PropertyAttributes attributes);
   Object* IgnoreAttributesAndSetLocalProperty(String* key,
                                               Object* value);
+
+  // Sets a property that currently has lazy loading.
   Object* SetLazyProperty(LookupResult* result,
                           String* name,
                           Object* value,
@@ -1284,6 +1288,11 @@
                                   Object* value);
 
   // Add a constant function property to a fast-case object.
+  // This leaves a CONSTANT_TRANSITION in the old map, and
+  // if it is called on a second object with this map, a
+  // normal property is added instead, with a map transition.
+  // This avoids the creation of many maps with the same constant
+  // function, all orphaned.
   Object* AddConstantFunctionProperty(String* name,
                                       JSFunction* function,
                                       PropertyAttributes attributes);
@@ -1551,12 +1560,13 @@
   // of the named property, but preserve its enumeration index.
   Object* CopyReplace(String* name, int index, PropertyAttributes attributes);
 
+  // Copy the descriptor array, removing the property index and attributes
+  // of the named property.
+  Object* CopyRemove(String* name);
+
   // Sort the instance descriptors by the hash codes of their keys.
   void Sort();
 
-  // Is the descriptor array sorted and without duplicates?
-  bool IsSortedNoDuplicates();
-
   // Search the instance descriptors for given name.
   inline int Search(String* name);
 
@@ -1599,6 +1609,9 @@
 #ifdef DEBUG
   // Print all the descriptors.
   void PrintDescriptors();
+
+  // Is the descriptor array sorted and without duplicates?
+  bool IsSortedNoDuplicates();
 #endif
 
   // The maximum number of descriptors we want in a descriptor array (should
@@ -2014,9 +2027,10 @@
     IC_TARGET_IS_OBJECT
   };
 
-#ifdef DEBUG
+#ifdef ENABLE_DISASSEMBLER
+  // Printing
   static const char* Kind2String(Kind kind);
-#endif
+#endif  // ENABLE_DISASSEMBLER
 
   // [instruction_size]: Size of the native instructions
   inline int instruction_size();
@@ -2511,8 +2525,7 @@
   static const int kEndPositionOffset = kStartPositionAndTypeOffset + kIntSize;
   static const int kFunctionTokenPositionOffset = kEndPositionOffset + kIntSize;
   static const int kDebugInfoOffset = kFunctionTokenPositionOffset + kIntSize;
-  static const int kAccessAttributesOffset = kDebugInfoOffset + kPointerSize;
-  static const int kSize = kAccessAttributesOffset + kPointerSize;
+  static const int kSize = kDebugInfoOffset + kPointerSize;
 
  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo);
diff --git a/src/parser.cc b/src/parser.cc
index 2189b8f..b491cfb 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -2174,6 +2174,8 @@
     if (x && x->AsLiteral() && x->AsLiteral()->handle()->IsNumber()) {
       double x_val = x->AsLiteral()->handle()->Number();
       switch (op) {
+        case Token::ADD:
+          return x;
         case Token::SUB:
           return NewNumberLiteral(-x_val);
         case Token::BIT_NOT:
diff --git a/src/platform-nullos.cc b/src/platform-nullos.cc
new file mode 100644
index 0000000..214ee94
--- /dev/null
+++ b/src/platform-nullos.cc
@@ -0,0 +1,421 @@
+// Copyright 2006-2008 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
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Platform specific code for NULLOS goes here
+
+// Minimal include to get access to abort, fprintf and friends for bootstrapping
+// messages.
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "v8.h"
+
+#include "platform.h"
+
+
+namespace v8 { namespace internal {
+
+// Give V8 the opportunity to override the default ceil behaviour.
+double ceiling(double x) {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+// Initialize OS class early in the V8 startup.
+void OS::Setup() {
+  // Seed the random number generator.
+  UNIMPLEMENTED();
+}
+
+
+// Returns the accumulated user time for thread.
+int OS::GetUserTime(uint32_t* secs,  uint32_t* usecs) {
+  UNIMPLEMENTED();
+  *secs = 0;
+  *usecs = 0;
+  return 0;
+}
+
+
+// Returns current time as the number of milliseconds since
+// 00:00:00 UTC, January 1, 1970.
+double OS::TimeCurrentMillis() {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+// Returns ticks in microsecond resolution.
+int64_t OS::Ticks() {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+// Returns a string identifying the current timezone taking into
+// account daylight saving.
+char* OS::LocalTimezone(double time) {
+  UNIMPLEMENTED();
+  return "<none>";
+}
+
+
+// Returns the daylight savings offset in milliseconds for the given time.
+double OS::DaylightSavingsOffset(double time) {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+// Returns the local time offset in milliseconds east of UTC without
+// taking daylight savings time into account.
+double OS::LocalTimeOffset() {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+// Print (debug) message to console.
+void OS::Print(const char* format, ...) {
+  UNIMPLEMENTED();
+}
+
+
+// Print (debug) message to console.
+void OS::VPrint(const char* format, va_list args) {
+  // Minimalistic implementation for bootstrapping.
+  vfprintf(stdout, format, args);
+}
+
+
+// Print error message to console.
+void OS::PrintError(const char* format, ...) {
+  // Minimalistic implementation for bootstrapping.
+  va_list args;
+  va_start(args, format);
+  VPrintError(format, args);
+  va_end(args);
+}
+
+
+// Print error message to console.
+void OS::VPrintError(const char* format, va_list args) {
+  // Minimalistic implementation for bootstrapping.
+  vfprintf(stderr, format, args);
+}
+
+
+int OS::SNPrintF(char* str, size_t size, const char* format, ...) {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+int OS::VSNPrintF(char* str, size_t size, const char* format, va_list args) {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+double OS::nan_value() {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+bool OS::IsOutsideAllocatedSpace(void* address) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+size_t OS::AllocateAlignment() {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+void* OS::Allocate(const size_t requested,
+                   size_t* allocated,
+                   bool executable) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void OS::Free(void* buf, const size_t length) {
+  // TODO(1240712): potential system call return value which is ignored here.
+  UNIMPLEMENTED();
+}
+
+
+void OS::Sleep(int milliseconds) {
+  UNIMPLEMENTED();
+}
+
+
+void OS::Abort() {
+  // Minimalistic implementation for bootstrapping.
+  abort();
+}
+
+
+void OS::DebugBreak() {
+  UNIMPLEMENTED();
+}
+
+
+OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
+    void* initial) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void OS::LogSharedLibraryAddresses() {
+  UNIMPLEMENTED();
+}
+
+
+int OS::StackWalk(OS::StackFrame* frames, int frames_size) {
+  UNIMPLEMENTED();
+  return 0;
+}
+
+
+VirtualMemory::VirtualMemory(size_t size, void* address_hint) {
+  UNIMPLEMENTED();
+}
+
+
+VirtualMemory::~VirtualMemory() {
+  UNIMPLEMENTED();
+}
+
+
+bool VirtualMemory::IsReserved() {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+bool VirtualMemory::Commit(void* address, size_t size, bool executable) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+bool VirtualMemory::Uncommit(void* address, size_t size) {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+class ThreadHandle::PlatformData : public Malloced {
+ public:
+  explicit PlatformData(ThreadHandle::Kind kind) {
+    UNIMPLEMENTED();
+  }
+
+  void* pd_data_;
+};
+
+
+ThreadHandle::ThreadHandle(Kind kind) {
+  UNIMPLEMENTED();
+  // Shared setup follows.
+  data_ = new PlatformData(kind);
+}
+
+
+void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
+  UNIMPLEMENTED();
+}
+
+
+ThreadHandle::~ThreadHandle() {
+  UNIMPLEMENTED();
+  // Shared tear down follows.
+  delete data_;
+}
+
+
+bool ThreadHandle::IsSelf() const {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+bool ThreadHandle::IsValid() const {
+  UNIMPLEMENTED();
+  return false;
+}
+
+
+Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
+  UNIMPLEMENTED();
+}
+
+
+Thread::~Thread() {
+  UNIMPLEMENTED();
+}
+
+
+void Thread::Start() {
+  UNIMPLEMENTED();
+}
+
+
+void Thread::Join() {
+  UNIMPLEMENTED();
+}
+
+
+Thread::LocalStorageKey Thread::CreateThreadLocalKey() {
+  UNIMPLEMENTED();
+  return static_cast<LocalStorageKey>(0);
+}
+
+
+void Thread::DeleteThreadLocalKey(LocalStorageKey key) {
+  UNIMPLEMENTED();
+}
+
+
+void* Thread::GetThreadLocal(LocalStorageKey key) {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
+  UNIMPLEMENTED();
+}
+
+
+void Thread::YieldCPU() {
+  UNIMPLEMENTED();
+}
+
+
+class NullMutex : public Mutex {
+ public:
+  NullMutex() : data_(NULL) {
+    UNIMPLEMENTED();
+  }
+
+  virtual ~NullMutex() {
+    UNIMPLEMENTED();
+  }
+
+  virtual int Lock() {
+    UNIMPLEMENTED();
+    return 0;
+  }
+
+  virtual int Unlock() {
+    UNIMPLEMENTED();
+    return 0;
+  }
+
+ private:
+  void* data_;
+};
+
+
+Mutex* OS::CreateMutex() {
+  UNIMPLEMENTED();
+  return new NullMutex();
+}
+
+
+class NullSemaphore : public Semaphore {
+ public:
+  explicit NullSemaphore(int count) : data_(NULL) {
+    UNIMPLEMENTED();
+  }
+
+  virtual ~NullSemaphore() {
+    UNIMPLEMENTED();
+  }
+
+  virtual void Wait() {
+    UNIMPLEMENTED();
+  }
+
+  virtual void Signal() {
+    UNIMPLEMENTED();
+  }
+ private:
+  void* data_;
+};
+
+
+Semaphore* OS::CreateSemaphore(int count) {
+  UNIMPLEMENTED();
+  return new NullSemaphore(count);
+}
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+
+class ProfileSampler::PlatformData  : public Malloced {
+ public:
+  PlatformData() {
+    UNIMPLEMENTED();
+  }
+};
+
+
+ProfileSampler::ProfileSampler(int interval) {
+  UNIMPLEMENTED();
+  // Shared setup follows.
+  data_ = new PlatformData();
+  interval_ = interval;
+  active_ = false;
+}
+
+
+ProfileSampler::~ProfileSampler() {
+  UNIMPLEMENTED();
+  // Shared tear down follows.
+  delete data_;
+}
+
+
+void ProfileSampler::Start() {
+  UNIMPLEMENTED();
+}
+
+
+void ProfileSampler::Stop() {
+  UNIMPLEMENTED();
+}
+
+#endif  // ENABLE_LOGGING_AND_PROFILING
+
+} }  // namespace v8::internal
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index 102e443..87d7a3e 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -690,22 +690,30 @@
 }
 
 
-// Get the system's page size used by VirtualAlloc().
+// Get the system's page size used by VirtualAlloc() or the next power
+// of two. The reason for always returning a power of two is that the
+// rounding up in OS::Allocate expects that.
 static size_t GetPageSize() {
   static size_t page_size = 0;
   if (page_size == 0) {
     SYSTEM_INFO info;
     GetSystemInfo(&info);
-    page_size = info.dwPageSize;
+    page_size = RoundUpToPowerOf2(info.dwPageSize);
   }
   return page_size;
 }
 
 
+// The allocation alignment is the guaranteed alignment for
+// VirtualAlloc'ed blocks of memory.
 size_t OS::AllocateAlignment() {
-  // See also http://blogs.msdn.com/oldnewthing/archive/2003/10/08/55239.aspx
-  const size_t kWindowsVirtualAllocAlignment = 64*1024;
-  return kWindowsVirtualAllocAlignment;
+  static size_t allocate_alignment = 0;
+  if (allocate_alignment == 0) {
+    SYSTEM_INFO info;
+    GetSystemInfo(&info);
+    allocate_alignment = info.dwAllocationGranularity;
+  }
+  return allocate_alignment;
 }
 
 
@@ -717,7 +725,7 @@
 
   // Windows XP SP2 allows Data Excution Prevention (DEP).
   int prot = executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
-  LPVOID mbase = VirtualAlloc(NULL, requested, MEM_COMMIT | MEM_RESERVE, prot);
+  LPVOID mbase = VirtualAlloc(NULL, msize, MEM_COMMIT | MEM_RESERVE, prot);
   if (mbase == NULL) {
     LOG(StringEvent("OS::Allocate", "VirtualAlloc failed"));
     return NULL;
diff --git a/src/prettyprinter.cc b/src/prettyprinter.cc
index 0f14f55..b07d9a7 100644
--- a/src/prettyprinter.cc
+++ b/src/prettyprinter.cc
@@ -456,17 +456,7 @@
     int n = OS::VSNPrintF(output_ + pos_, available, format, arguments);
     va_end(arguments);
 
-    // Return value from VSNPrintF is not portable. On linux the return value
-    // is the number of  characters which would have been written to the string
-    // if enough space had been  available. On windows it returns -1 if the
-    // result is truncated but does not indicate the required buffer size.
-#ifdef WIN32
-    if (n <= 0) n = available;
-#else
-    CHECK_GE(n, 0);  // no errors
-#endif
-
-    if (n < available) {
+    if (n >= 0) {
       // there was enough space - we are done
       pos_ += n;
       return;
@@ -474,8 +464,6 @@
       // there was not enough space - allocate more and try again
       const int slack = 32;
       int new_size = size_ + (size_ >> 1) + slack;
-      if (new_size < size_ + n)
-        new_size = size_ + n + slack;
       char* new_output = NewArray<char>(new_size);
       memcpy(new_output, output_, pos_);
       DeleteArray(output_);
diff --git a/src/property.h b/src/property.h
index 0863e19..3cb2752 100644
--- a/src/property.h
+++ b/src/property.h
@@ -108,7 +108,11 @@
       : Descriptor(key, map, attributes, MAP_TRANSITION) { }
 };
 
-
+// Marks a field name in a map so that adding the field is guaranteed
+// to create a FIELD descriptor in the new map.  Used after adding
+// a constant function the first time, creating a CONSTANT_FUNCTION
+// descriptor in the new map.  This avoids creating multiple maps with
+// the same CONSTANT_FUNCTION field.
 class ConstTransitionDescriptor: public Descriptor {
  public:
   explicit ConstTransitionDescriptor(String* key)
diff --git a/src/runtime.cc b/src/runtime.cc
index b54ed6a..5f22980 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -3232,20 +3232,6 @@
 }
 
 
-
-static Object* Runtime_NumberIsNaN(Arguments args) {
-  NoHandleAllocation ha;
-  ASSERT(args.length() == 1);
-
-  CONVERT_DOUBLE_CHECKED(value, args[0]);
-  if (isnan(value)) {
-    return Heap::true_value();
-  } else {
-    return Heap::false_value();
-  }
-}
-
-
 static Object* Runtime_NumberIsFinite(Arguments args) {
   NoHandleAllocation ha;
   ASSERT(args.length() == 1);
@@ -3282,20 +3268,6 @@
 }
 
 
-static Object* Runtime_NumberNegativeInfinity(Arguments) {
-  NoHandleAllocation ha;
-
-  return Heap::negative_infinity_value();
-}
-
-
-static Object* Runtime_NumberPositiveInfinity(Arguments) {
-  NoHandleAllocation ha;
-
-  return Heap::infinity_value();
-}
-
-
 static Object* EvalContext() {
   // The topmost JS frame belongs to the eval function which called
   // the CompileString runtime function. We need to unwind one level
diff --git a/src/runtime.h b/src/runtime.h
index 929e64f..0e0ae97 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -107,9 +107,6 @@
   F(NumberShr, 2) \
   F(NumberSar, 2) \
   \
-  F(NumberIsNaN, 1) \
-  F(NumberIsFinite, 1) \
-  \
   /* Comparisons */ \
   F(ObjectEquals, 2) \
   F(NumberEquals, 2) \
@@ -179,11 +176,10 @@
   F(DateDaylightSavingsOffset, 1) \
   \
   /* Numbers */ \
+  F(NumberIsFinite, 1) \
   F(NumberMaxValue, 1) \
   F(NumberMinValue, 1) \
   F(NumberNaN, 1) \
-  F(NumberNegativeInfinity, 1) \
-  F(NumberPositiveInfinity, 1) \
   \
   /* Globals */ \
   F(CompileString, 2) \
diff --git a/src/runtime.js b/src/runtime.js
index 52a92c0..e518c5b 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -428,7 +428,7 @@
   if (IS_BOOLEAN(x)) return x;
   if (IS_STRING(x)) return x.length != 0;
   if (x == null) return false;
-  if (IS_NUMBER(x)) return !((x == 0) || %NumberIsNaN(x));
+  if (IS_NUMBER(x)) return !((x == 0) || NUMBER_IS_NAN(x));
   return true;
 };
 
@@ -452,6 +452,7 @@
 
 // ECMA-262, section 9.6, page 34.
 function ToUint32(x) {
+  if (%_IsSmi(x) && x >= 0) return x;
   return %NumberToJSUint32(ToNumber(x));
 };
 
diff --git a/src/simulator-arm.cc b/src/simulator-arm.cc
index 3aa774c..9f20fc9 100644
--- a/src/simulator-arm.cc
+++ b/src/simulator-arm.cc
@@ -59,7 +59,9 @@
 
  private:
   static const instr_t kBreakpointInstr =
-      (AL << 28 | 7 << 25 | 1 << 24 | break_point);
+      ((AL << 28) | (7 << 25) | (1 << 24) | break_point);
+  static const instr_t kNopInstr =
+      ((AL << 28) | (13 << 21));
 
   Simulator* sim_;
 
@@ -311,6 +313,14 @@
         PrintF("Z flag: %d; ", sim_->z_flag_);
         PrintF("C flag: %d; ", sim_->c_flag_);
         PrintF("V flag: %d\n", sim_->v_flag_);
+      } else if (strcmp(cmd, "unstop") == 0) {
+        intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize;
+        Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc);
+        if (stop_instr->ConditionField() == special_condition) {
+          stop_instr->SetInstructionBits(kNopInstr);
+        } else {
+          PrintF("Not at debugger stop.");
+        }
       } else {
         PrintF("Unknown command: %s\n", cmd);
       }
diff --git a/src/stub-cache-arm.cc b/src/stub-cache-arm.cc
index e14dfe6..b553306 100644
--- a/src/stub-cache-arm.cc
+++ b/src/stub-cache-arm.cc
@@ -237,7 +237,6 @@
                                               JSFunction* function,
                                               CheckType check) {
   // ----------- S t a t e -------------
-  //  -- r0: number of arguments
   //  -- r1: receiver
   //  -- lr: return address
   // -----------------------------------
@@ -322,17 +321,20 @@
       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));
 
   // 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));
 
   // Jump to the cached code (tail call).
   Handle<Code> code(function->code());
-  __ Jump(code, code_target);
+  ParameterCount expected(function->shared()->formal_parameter_count());
+  __ InvokeCode(code, expected, arguments(), code_target, JUMP_FUNCTION);
 
   // Handle call cache miss.
   __ bind(&miss);
diff --git a/src/utils.cc b/src/utils.cc
index 19a6124..48ccc31 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -36,7 +36,9 @@
 namespace v8 { namespace internal {
 
 
-int32_t NextPowerOf2(uint32_t x) {
+// Implementation is from "Hacker's Delight" by Henry S. Warren, Jr.,
+// figure 3-3, page 48, where the function is called clp2.
+uint32_t RoundUpToPowerOf2(uint32_t x) {
   x = x - 1;
   x = x | (x >> 1);
   x = x | (x >> 2);
diff --git a/src/utils.h b/src/utils.h
index a91a2ab..f9bf028 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -40,21 +40,19 @@
 }
 
 
-// Returns smallest power of 2 greater or equal to x (from Hacker's Delight).
-int32_t NextPowerOf2(uint32_t x);
 
 
-// The C++ standard leaves the semantics of '>>'
-// undefined for negative signed operands. Most
-// implementations do the right thing, though.
+// The C++ standard leaves the semantics of '>>' undefined for
+// negative signed operands. Most implementations do the right thing,
+// though.
 static inline int ArithmeticShiftRight(int x, int s) {
   return x >> s;
 }
 
 
 // Compute the 0-relative offset of some absolute value x of type T.
-// This allows conversion of Addresses and integral types into 0-relative
-// int offsets.
+// This allows conversion of Addresses and integral types into
+// 0-relative int offsets.
 template <typename T>
 static inline int OffsetFrom(T x) {
   return x - static_cast<T>(0);
@@ -62,8 +60,8 @@
 
 
 // Compute the absolute value of type T for some 0-relative offset x.
-// This allows conversion of 0-relative int offsets into Addresses
-// and integral types.
+// This allows conversion of 0-relative int offsets into Addresses and
+// integral types.
 template <typename T>
 static inline T AddressFrom(int x) {
   return static_cast<T>(0) + x;
@@ -85,6 +83,11 @@
 }
 
 
+// Returns the smallest power of two which is >= x. If you pass in a
+// number that is already a power of two, it is returned as is.
+uint32_t RoundUpToPowerOf2(uint32_t x);
+
+
 template <typename T>
 static inline bool IsAligned(T value, T alignment) {
   ASSERT(IsPowerOf2(alignment));
@@ -114,8 +117,8 @@
 
 
 // ----------------------------------------------------------------------------
-// BitField is a help template for encoding and decode bitfield with unsigned
-// content.
+// BitField is a help template for encoding and decode bitfield with
+// unsigned content.
 template<class T, int shift, int size>
 class BitField {
  public:
diff --git a/src/v8natives.js b/src/v8natives.js
index 495f285..6f1519b 100644
--- a/src/v8natives.js
+++ b/src/v8natives.js
@@ -41,7 +41,7 @@
 
 
 // ECMA-262 - 15.1.1.2.
-%AddProperty(global, "Infinity", %NumberPositiveInfinity(1), DONT_ENUM | DONT_DELETE);
+%AddProperty(global, "Infinity", 1/0, DONT_ENUM | DONT_DELETE);
 
 
 // ECMA-262 - 15.1.1.3.
@@ -50,7 +50,8 @@
 
 // ECMA 262 - 15.1.4
 function $isNaN(number) {
-  return %NumberIsNaN(ToNumber(number));
+  var n = ToNumber(number);
+  return NUMBER_IS_NAN(n);
 };
 %AddProperty(global, "isNaN", $isNaN, DONT_ENUM);
 
@@ -265,10 +266,10 @@
 %AddProperty($Number, "NaN", $NaN, DONT_ENUM | DONT_DELETE | READ_ONLY);
 
 // ECMA-262 section 15.7.3.4.
-%AddProperty($Number, "NEGATIVE_INFINITY", %NumberNegativeInfinity(1),  DONT_ENUM | DONT_DELETE | READ_ONLY);
+%AddProperty($Number, "NEGATIVE_INFINITY", -1/0,  DONT_ENUM | DONT_DELETE | READ_ONLY);
 
 // ECMA-262 section 15.7.3.5.
-%AddProperty($Number, "POSITIVE_INFINITY", %NumberPositiveInfinity(1),  DONT_ENUM | DONT_DELETE | READ_ONLY);
+%AddProperty($Number, "POSITIVE_INFINITY", 1/0,  DONT_ENUM | DONT_DELETE | READ_ONLY);
 
 // ECMA-262 section 15.7.4.2.
 %AddProperty($Number.prototype, "toString", function(radix) {