Version 3.2.4.

Added isolates which allows several V8 instances in the same process. This is controlled through the new Isolate class in the API.

Implemented more of EcmaScript 5 strict mode.

Reduced the time it takes to make detailed heap snapshot.

Added a number of commands to the ARM simulator and enhanced the ARM disassembler.


git-svn-id: http://v8.googlecode.com/svn/trunk@7322 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index d5c3f53..950cf31 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -45,7 +45,7 @@
     : Assembler(buffer, size),
       generating_stub_(false),
       allow_stub_calls_(true),
-      code_object_(Heap::undefined_value()) {
+      code_object_(HEAP->undefined_value()) {
 }
 
 
@@ -152,7 +152,7 @@
 #ifdef ENABLE_DEBUGGER_SUPPORT
 void MacroAssembler::DebugBreak() {
   Set(eax, Immediate(0));
-  mov(ebx, Immediate(ExternalReference(Runtime::kDebugBreak)));
+  mov(ebx, Immediate(ExternalReference(Runtime::kDebugBreak, isolate())));
   CEntryStub ces(1);
   call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
 }
@@ -231,7 +231,7 @@
 
 
 void MacroAssembler::FCmp() {
-  if (CpuFeatures::IsSupported(CMOV)) {
+  if (Isolate::Current()->cpu_features()->IsSupported(CMOV)) {
     fucomip();
     ffree(0);
     fincstp();
@@ -250,7 +250,7 @@
   test(object, Immediate(kSmiTagMask));
   j(zero, &ok);
   cmp(FieldOperand(object, HeapObject::kMapOffset),
-      Factory::heap_number_map());
+      FACTORY->heap_number_map());
   Assert(equal, "Operand not a number");
   bind(&ok);
 }
@@ -286,7 +286,7 @@
   push(Immediate(Smi::FromInt(type)));
   push(Immediate(CodeObject()));
   if (emit_debug_code()) {
-    cmp(Operand(esp, 0), Immediate(Factory::undefined_value()));
+    cmp(Operand(esp, 0), Immediate(FACTORY->undefined_value()));
     Check(not_equal, "code object not properly patched");
   }
 }
@@ -316,8 +316,10 @@
   push(Immediate(CodeObject()));  // Accessed from ExitFrame::code_slot.
 
   // Save the frame pointer and the context in top.
-  ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
-  ExternalReference context_address(Top::k_context_address);
+  ExternalReference c_entry_fp_address(Isolate::k_c_entry_fp_address,
+                                       isolate());
+  ExternalReference context_address(Isolate::k_context_address,
+                                    isolate());
   mov(Operand::StaticVariable(c_entry_fp_address), ebp);
   mov(Operand::StaticVariable(context_address), esi);
 }
@@ -339,7 +341,7 @@
   }
 
   // Get the required frame alignment for the OS.
-  static const int kFrameAlignment = OS::ActivationFrameAlignment();
+  const int kFrameAlignment = OS::ActivationFrameAlignment();
   if (kFrameAlignment > 0) {
     ASSERT(IsPowerOf2(kFrameAlignment));
     and_(esp, -kFrameAlignment);
@@ -358,7 +360,8 @@
   mov(edi, Operand(eax));
   lea(esi, Operand(ebp, eax, times_4, offset));
 
-  EnterExitFrameEpilogue(2, save_doubles);
+  // Reserve space for argc, argv and isolate.
+  EnterExitFrameEpilogue(3, save_doubles);
 }
 
 
@@ -394,14 +397,15 @@
 
 void MacroAssembler::LeaveExitFrameEpilogue() {
   // Restore current context from top and clear it in debug mode.
-  ExternalReference context_address(Top::k_context_address);
+  ExternalReference context_address(Isolate::k_context_address, isolate());
   mov(esi, Operand::StaticVariable(context_address));
 #ifdef DEBUG
   mov(Operand::StaticVariable(context_address), Immediate(0));
 #endif
 
   // Clear the top frame.
-  ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
+  ExternalReference c_entry_fp_address(Isolate::k_c_entry_fp_address,
+                                       isolate());
   mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0));
 }
 
@@ -435,15 +439,19 @@
     push(Immediate(0));  // NULL frame pointer.
   }
   // Save the current handler as the next handler.
-  push(Operand::StaticVariable(ExternalReference(Top::k_handler_address)));
+  push(Operand::StaticVariable(ExternalReference(Isolate::k_handler_address,
+                                                 isolate())));
   // Link this handler as the new current one.
-  mov(Operand::StaticVariable(ExternalReference(Top::k_handler_address)), esp);
+  mov(Operand::StaticVariable(ExternalReference(Isolate::k_handler_address,
+                                                isolate())),
+      esp);
 }
 
 
 void MacroAssembler::PopTryHandler() {
   ASSERT_EQ(0, StackHandlerConstants::kNextOffset);
-  pop(Operand::StaticVariable(ExternalReference(Top::k_handler_address)));
+  pop(Operand::StaticVariable(ExternalReference(Isolate::k_handler_address,
+                                                isolate())));
   add(Operand(esp), Immediate(StackHandlerConstants::kSize - kPointerSize));
 }
 
@@ -458,7 +466,8 @@
   }
 
   // Drop the sp to the top of the handler.
-  ExternalReference handler_address(Top::k_handler_address);
+  ExternalReference handler_address(Isolate::k_handler_address,
+                                    isolate());
   mov(esp, Operand::StaticVariable(handler_address));
 
   // Restore next handler and frame pointer, discard handler state.
@@ -494,7 +503,8 @@
   }
 
   // Drop sp to the top stack handler.
-  ExternalReference handler_address(Top::k_handler_address);
+  ExternalReference handler_address(Isolate::k_handler_address,
+                                    isolate());
   mov(esp, Operand::StaticVariable(handler_address));
 
   // Unwind the handlers until the ENTRY handler is found.
@@ -516,12 +526,15 @@
 
   if (type == OUT_OF_MEMORY) {
     // Set external caught exception to false.
-    ExternalReference external_caught(Top::k_external_caught_exception_address);
+    ExternalReference external_caught(
+        Isolate::k_external_caught_exception_address,
+        isolate());
     mov(eax, false);
     mov(Operand::StaticVariable(external_caught), eax);
 
     // Set pending exception and eax to out of memory exception.
-    ExternalReference pending_exception(Top::k_pending_exception_address);
+    ExternalReference pending_exception(Isolate::k_pending_exception_address,
+                                        isolate());
     mov(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException()));
     mov(Operand::StaticVariable(pending_exception), eax);
   }
@@ -564,7 +577,7 @@
     push(scratch);
     // Read the first word and compare to global_context_map.
     mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
-    cmp(scratch, Factory::global_context_map());
+    cmp(scratch, FACTORY->global_context_map());
     Check(equal, "JSGlobalObject::global_context should be a global context.");
     pop(scratch);
   }
@@ -585,13 +598,13 @@
 
   // Check the context is a global context.
   if (emit_debug_code()) {
-    cmp(holder_reg, Factory::null_value());
+    cmp(holder_reg, FACTORY->null_value());
     Check(not_equal, "JSGlobalProxy::context() should not be null.");
 
     push(holder_reg);
     // Read the first word and compare to global_context_map(),
     mov(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset));
-    cmp(holder_reg, Factory::global_context_map());
+    cmp(holder_reg, FACTORY->global_context_map());
     Check(equal, "JSGlobalObject::global_context should be a global context.");
     pop(holder_reg);
   }
@@ -611,7 +624,7 @@
                                              Register scratch,
                                              AllocationFlags flags) {
   ExternalReference new_space_allocation_top =
-      ExternalReference::new_space_allocation_top_address();
+      ExternalReference::new_space_allocation_top_address(isolate());
 
   // Just return if allocation top is already known.
   if ((flags & RESULT_CONTAINS_TOP) != 0) {
@@ -643,7 +656,7 @@
   }
 
   ExternalReference new_space_allocation_top =
-      ExternalReference::new_space_allocation_top_address();
+      ExternalReference::new_space_allocation_top_address(isolate());
 
   // Update new top. Use scratch if available.
   if (scratch.is(no_reg)) {
@@ -683,7 +696,7 @@
 
   // Calculate new top and bail out if new space is exhausted.
   ExternalReference new_space_allocation_limit =
-      ExternalReference::new_space_allocation_limit_address();
+      ExternalReference::new_space_allocation_limit_address(isolate());
 
   if (!top_reg.is(result)) {
     mov(top_reg, result);
@@ -737,7 +750,7 @@
 
   // Calculate new top and bail out if new space is exhausted.
   ExternalReference new_space_allocation_limit =
-      ExternalReference::new_space_allocation_limit_address();
+      ExternalReference::new_space_allocation_limit_address(isolate());
 
   // We assume that element_count*element_size + header_size does not
   // overflow.
@@ -783,7 +796,7 @@
 
   // Calculate new top and bail out if new space is exhausted.
   ExternalReference new_space_allocation_limit =
-      ExternalReference::new_space_allocation_limit_address();
+      ExternalReference::new_space_allocation_limit_address(isolate());
   if (!object_size.is(result_end)) {
     mov(result_end, object_size);
   }
@@ -804,7 +817,7 @@
 
 void MacroAssembler::UndoAllocationInNewSpace(Register object) {
   ExternalReference new_space_allocation_top =
-      ExternalReference::new_space_allocation_top_address();
+      ExternalReference::new_space_allocation_top_address(isolate());
 
   // Make sure the object has no tag before resetting top.
   and_(Operand(object), Immediate(~kHeapObjectTagMask));
@@ -830,7 +843,7 @@
 
   // Set the map.
   mov(FieldOperand(result, HeapObject::kMapOffset),
-      Immediate(Factory::heap_number_map()));
+      Immediate(FACTORY->heap_number_map()));
 }
 
 
@@ -860,7 +873,7 @@
 
   // Set the map, length and hash field.
   mov(FieldOperand(result, HeapObject::kMapOffset),
-      Immediate(Factory::string_map()));
+      Immediate(FACTORY->string_map()));
   mov(scratch1, length);
   SmiTag(scratch1);
   mov(FieldOperand(result, String::kLengthOffset), scratch1);
@@ -895,7 +908,7 @@
 
   // Set the map, length and hash field.
   mov(FieldOperand(result, HeapObject::kMapOffset),
-      Immediate(Factory::ascii_string_map()));
+      Immediate(FACTORY->ascii_string_map()));
   mov(scratch1, length);
   SmiTag(scratch1);
   mov(FieldOperand(result, String::kLengthOffset), scratch1);
@@ -921,7 +934,7 @@
 
   // Set the map, length and hash field.
   mov(FieldOperand(result, HeapObject::kMapOffset),
-      Immediate(Factory::ascii_string_map()));
+      Immediate(FACTORY->ascii_string_map()));
   mov(FieldOperand(result, String::kLengthOffset),
       Immediate(Smi::FromInt(length)));
   mov(FieldOperand(result, String::kHashFieldOffset),
@@ -943,7 +956,7 @@
 
   // Set the map. The other fields are left uninitialized.
   mov(FieldOperand(result, HeapObject::kMapOffset),
-      Immediate(Factory::cons_string_map()));
+      Immediate(FACTORY->cons_string_map()));
 }
 
 
@@ -961,7 +974,7 @@
 
   // Set the map. The other fields are left uninitialized.
   mov(FieldOperand(result, HeapObject::kMapOffset),
-      Immediate(Factory::cons_ascii_string_map()));
+      Immediate(FACTORY->cons_ascii_string_map()));
 }
 
 
@@ -1079,7 +1092,7 @@
   // If the prototype or initial map is the hole, don't return it and
   // simply miss the cache instead. This will allow us to allocate a
   // prototype object on-demand in the runtime system.
-  cmp(Operand(result), Immediate(Factory::the_hole_value()));
+  cmp(Operand(result), Immediate(FACTORY->the_hole_value()));
   j(equal, miss, not_taken);
 
   // If the function does not have an initial map, we're done.
@@ -1145,7 +1158,7 @@
   if (num_arguments > 0) {
     add(Operand(esp), Immediate(num_arguments * kPointerSize));
   }
-  mov(eax, Immediate(Factory::undefined_value()));
+  mov(eax, Immediate(FACTORY->undefined_value()));
 }
 
 
@@ -1174,9 +1187,9 @@
 
 
 void MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) {
-  Runtime::Function* function = Runtime::FunctionForId(id);
+  const Runtime::Function* function = Runtime::FunctionForId(id);
   Set(eax, Immediate(function->nargs));
-  mov(ebx, Immediate(ExternalReference(function)));
+  mov(ebx, Immediate(ExternalReference(function, isolate())));
   CEntryStub ces(1);
   ces.SaveDoubles();
   CallStub(&ces);
@@ -1189,7 +1202,8 @@
 }
 
 
-void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
+void MacroAssembler::CallRuntime(const Runtime::Function* f,
+                                 int num_arguments) {
   // If the expected number of arguments of the runtime function is
   // constant, we check that the actual number of arguments match the
   // expectation.
@@ -1203,19 +1217,19 @@
   // should remove this need and make the runtime routine entry code
   // smarter.
   Set(eax, Immediate(num_arguments));
-  mov(ebx, Immediate(ExternalReference(f)));
+  mov(ebx, Immediate(ExternalReference(f, isolate())));
   CEntryStub ces(1);
   CallStub(&ces);
 }
 
 
-MaybeObject* MacroAssembler::TryCallRuntime(Runtime::Function* f,
+MaybeObject* MacroAssembler::TryCallRuntime(const Runtime::Function* f,
                                             int num_arguments) {
   if (f->nargs >= 0 && f->nargs != num_arguments) {
     IllegalOperation(num_arguments);
     // Since we did not call the stub, there was no allocation failure.
     // Return some non-failure object.
-    return Heap::undefined_value();
+    return HEAP->undefined_value();
   }
 
   // TODO(1236192): Most runtime routines don't need the number of
@@ -1223,7 +1237,7 @@
   // should remove this need and make the runtime routine entry code
   // smarter.
   Set(eax, Immediate(num_arguments));
-  mov(ebx, Immediate(ExternalReference(f)));
+  mov(ebx, Immediate(ExternalReference(f, isolate())));
   CEntryStub ces(1);
   return TryCallStub(&ces);
 }
@@ -1265,7 +1279,9 @@
 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
                                      int num_arguments,
                                      int result_size) {
-  TailCallExternalReference(ExternalReference(fid), num_arguments, result_size);
+  TailCallExternalReference(ExternalReference(fid, isolate()),
+                            num_arguments,
+                            result_size);
 }
 
 
@@ -1273,7 +1289,7 @@
                                                 int num_arguments,
                                                 int result_size) {
   return TryTailCallExternalReference(
-      ExternalReference(fid), num_arguments, result_size);
+      ExternalReference(fid, isolate()), num_arguments, result_size);
 }
 
 
@@ -1373,9 +1389,9 @@
 
   // Check if the function scheduled an exception.
   ExternalReference scheduled_exception_address =
-      ExternalReference::scheduled_exception_address();
+      ExternalReference::scheduled_exception_address(isolate());
   cmp(Operand::StaticVariable(scheduled_exception_address),
-      Immediate(Factory::the_hole_value()));
+      Immediate(isolate()->factory()->the_hole_value()));
   j(not_equal, &promote_scheduled_exception, not_taken);
   LeaveApiExitFrame();
   ret(stack_space * kPointerSize);
@@ -1387,14 +1403,17 @@
   }
   bind(&empty_handle);
   // It was zero; the result is undefined.
-  mov(eax, Factory::undefined_value());
+  mov(eax, FACTORY->undefined_value());
   jmp(&prologue);
 
   // HandleScope limit has changed. Delete allocated extensions.
+  ExternalReference delete_extensions =
+      ExternalReference::delete_handle_scope_extensions(isolate());
   bind(&delete_allocated_handles);
   mov(Operand::StaticVariable(limit_address), edi);
   mov(edi, eax);
-  mov(eax, Immediate(ExternalReference::delete_handle_scope_extensions()));
+  mov(Operand(esp, 0), Immediate(ExternalReference::isolate_address()));
+  mov(eax, Immediate(delete_extensions));
   call(Operand(eax));
   mov(eax, edi);
   jmp(&leave_exit_frame);
@@ -1467,7 +1486,8 @@
 
   if (!definitely_matches) {
     Handle<Code> adaptor =
-        Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
+        Handle<Code>(Isolate::Current()->builtins()->builtin(
+            Builtins::ArgumentsAdaptorTrampoline));
     if (!code_constant.is_null()) {
       mov(edx, Immediate(code_constant));
       add(Operand(edx), Immediate(Code::kHeaderSize - kHeapObjectTag));
@@ -1645,7 +1665,7 @@
   mov(map, FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
   if (emit_debug_code()) {
     Label ok, fail;
-    CheckMap(map, Factory::meta_map(), &fail, false);
+    CheckMap(map, FACTORY->meta_map(), &fail, false);
     jmp(&ok);
     bind(&fail);
     Abort("Global functions must have initial map");
@@ -1795,10 +1815,10 @@
   if (emit_debug_code()) {
     Label ok;
     cmp(FieldOperand(elements, HeapObject::kMapOffset),
-        Immediate(Factory::fixed_array_map()));
+        Immediate(FACTORY->fixed_array_map()));
     j(equal, &ok);
     cmp(FieldOperand(elements, HeapObject::kMapOffset),
-        Immediate(Factory::fixed_cow_array_map()));
+        Immediate(FACTORY->fixed_cow_array_map()));
     j(equal, &ok);
     Abort("JSObject with fast elements map has slow elements");
     bind(&ok);
@@ -1863,7 +1883,7 @@
   if (emit_debug_code()) AbortIfSmi(reg);
   if (!info.IsNumber()) {
     cmp(FieldOperand(reg, HeapObject::kMapOffset),
-        Factory::heap_number_map());
+        FACTORY->heap_number_map());
     j(not_equal, on_not_number);
   }
 }
@@ -1968,6 +1988,9 @@
 
 
 void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) {
+  // Reserve space for Isolate address which is always passed as last parameter
+  num_arguments += 1;
+
   int frameAlignment = OS::ActivationFrameAlignment();
   if (frameAlignment != 0) {
     // Make stack end at alignment and make room for num_arguments words
@@ -1993,6 +2016,11 @@
 
 void MacroAssembler::CallCFunction(Register function,
                                    int num_arguments) {
+  // Pass current isolate address as additional parameter.
+  mov(Operand(esp, num_arguments * kPointerSize),
+      Immediate(ExternalReference::isolate_address()));
+  num_arguments += 1;
+
   // Check stack alignment.
   if (emit_debug_code()) {
     CheckStackAlignment();