Avoid handle dereference during graph optimization.
authoryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 23 Jan 2013 13:52:00 +0000 (13:52 +0000)
committeryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 23 Jan 2013 13:52:00 +0000 (13:52 +0000)
With parallel recompilation enabled, objects made accessible by handles may
have changed between graph construction and graph optimization. Therefore
we must not assume that information on those objects remain the same between
those two phases. To police this, we forbid handle dereferencing during
graph optimization.
Exceptions to this rule are:
 - Dereferencing the handle to obtain the raw location of the object. This
   is safe since parallel recompilation acquires RelocationLock
 - Some places that dereference the handle for a type check. These are checked
   to be safe on a case-by-case basis.

R=jkummerow@chromium.org
BUG=

Review URL: https://chromiumcodereview.appspot.com/12049012

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13475 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

19 files changed:
src/arm/lithium-arm.cc
src/arm/lithium-arm.h
src/arm/lithium-codegen-arm.cc
src/compiler.cc
src/compiler.h
src/handles-inl.h
src/handles.h
src/hydrogen-instructions.cc
src/hydrogen-instructions.h
src/hydrogen.cc
src/hydrogen.h
src/ia32/lithium-codegen-ia32.cc
src/ia32/lithium-ia32.cc
src/ia32/lithium-ia32.h
src/isolate.cc
src/isolate.h
src/x64/lithium-codegen-x64.cc
src/x64/lithium-x64.cc
src/x64/lithium-x64.h

index 2400bf0..fb8f0d7 100644 (file)
@@ -2098,9 +2098,7 @@ LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
 
 LInstruction* LChunkBuilder::DoTransitionElementsKind(
     HTransitionElementsKind* instr) {
-  ElementsKind from_kind = instr->original_map()->elements_kind();
-  ElementsKind to_kind = instr->transitioned_map()->elements_kind();
-  if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
+  if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
     LOperand* object = UseRegister(instr->object());
     LOperand* new_map_reg = TempRegister();
     LTransitionElementsKind* result =
@@ -2355,8 +2353,8 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
                                                instr->arguments_count(),
                                                instr->function(),
                                                undefined,
-                                               instr->call_kind(),
-                                               instr->inlining_kind());
+                                               instr->inlining_kind(),
+                                               instr->undefined_receiver());
   if (instr->arguments_var() != NULL) {
     inner->Bind(instr->arguments_var(), graph()->GetArgumentsObject());
   }
index 1ca2562..9cc9a66 100644 (file)
@@ -2054,6 +2054,8 @@ class LTransitionElementsKind: public LTemplateInstruction<1, 1, 2> {
 
   Handle<Map> original_map() { return hydrogen()->original_map(); }
   Handle<Map> transitioned_map() { return hydrogen()->transitioned_map(); }
+  ElementsKind from_kind() { return hydrogen()->from_kind(); }
+  ElementsKind to_kind() { return hydrogen()->to_kind(); }
 };
 
 
index 38015b4..fc59839 100644 (file)
@@ -818,8 +818,7 @@ void LCodeGen::DeoptimizeIf(Condition cc, LEnvironment* environment) {
 
   ASSERT(FLAG_deopt_every_n_times < 2);  // Other values not supported on ARM.
 
-  if (FLAG_deopt_every_n_times == 1 &&
-      info_->shared_info()->opt_count() == id) {
+  if (FLAG_deopt_every_n_times == 1 && info_->opt_count() == id) {
     __ Jump(entry, RelocInfo::RUNTIME_ENTRY);
     return;
   }
@@ -4508,8 +4507,8 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
 
   Handle<Map> from_map = instr->original_map();
   Handle<Map> to_map = instr->transitioned_map();
-  ElementsKind from_kind = from_map->elements_kind();
-  ElementsKind to_kind = to_map->elements_kind();
+  ElementsKind from_kind = instr->from_kind();
+  ElementsKind to_kind = instr->to_kind();
 
   Label not_applicable;
   __ ldr(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset));
index 84ea9c6..3bd00a9 100644 (file)
@@ -101,6 +101,7 @@ void CompilationInfo::Initialize(Isolate* isolate, Mode mode, Zone* zone) {
   deferred_handles_ = NULL;
   code_stub_ = NULL;
   prologue_offset_ = kPrologueOffsetNotSet;
+  opt_count_ = shared_info().is_null() ? 0 : shared_info()->opt_count();
   if (mode == STUB) {
     mode_ = STUB;
     return;
@@ -285,7 +286,7 @@ OptimizingCompiler::Status OptimizingCompiler::CreateGraph() {
   // the optimizing compiler.
   const int kMaxOptCount =
       FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000;
-  if (info()->shared_info()->opt_count() > kMaxOptCount) {
+  if (info()->opt_count() > kMaxOptCount) {
     info()->set_bailout_reason("optimized too many times");
     return AbortOptimization();
   }
@@ -394,6 +395,7 @@ OptimizingCompiler::Status OptimizingCompiler::CreateGraph() {
 OptimizingCompiler::Status OptimizingCompiler::OptimizeGraph() {
   AssertNoAllocation no_gc;
   NoHandleAllocation no_handles;
+  NoHandleDereference no_deref;
 
   ASSERT(last_status() == SUCCEEDED);
   Timer t(this, &time_taken_to_optimize_);
index 6d374d9..9315a50 100644 (file)
@@ -79,6 +79,7 @@ class CompilationInfo {
   ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
   Handle<Context> context() const { return context_; }
   BailoutId osr_ast_id() const { return osr_ast_id_; }
+  int opt_count() const { return opt_count_; }
   int num_parameters() const;
   int num_heap_slots() const;
   Code::Flags flags() const;
@@ -326,6 +327,10 @@ class CompilationInfo {
 
   int prologue_offset_;
 
+  // A copy of shared_info()->opt_count() to avoid handle deref
+  // during graph optimization.
+  int opt_count_;
+
   DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
 };
 
index 1307986..c084fb9 100644 (file)
@@ -63,9 +63,18 @@ template <typename T>
 inline T* Handle<T>::operator*() const {
   ASSERT(location_ != NULL);
   ASSERT(reinterpret_cast<Address>(*location_) != kHandleZapValue);
+  SLOW_ASSERT(ISOLATE->allow_handle_deref());
   return *BitCast<T**>(location_);
 }
 
+template <typename T>
+inline T** Handle<T>::location() const {
+  ASSERT(location_ == NULL ||
+         reinterpret_cast<Address>(*location_) != kZapValue);
+  SLOW_ASSERT(ISOLATE->allow_handle_deref());
+  return location_;
+}
+
 
 HandleScope::HandleScope() {
   Isolate* isolate = Isolate::Current();
@@ -175,6 +184,38 @@ inline NoHandleAllocation::~NoHandleAllocation() {
     data->level = level_;
   }
 }
+
+
+NoHandleDereference::NoHandleDereference() {
+  // The guard is set on a per-isolate basis, so it affects all threads.
+  // That's why we can only use it when running without parallel recompilation.
+  if (FLAG_parallel_recompilation) return;
+  Isolate* isolate = Isolate::Current();
+  old_state_ = isolate->allow_handle_deref();
+  isolate->set_allow_handle_deref(false);
+}
+
+
+NoHandleDereference::~NoHandleDereference() {
+  if (FLAG_parallel_recompilation) return;
+  Isolate::Current()->set_allow_handle_deref(old_state_);
+}
+
+
+AllowHandleDereference::AllowHandleDereference() {
+  // The guard is set on a per-isolate basis, so it affects all threads.
+  // That's why we can only use it when running without parallel recompilation.
+  if (FLAG_parallel_recompilation) return;
+  Isolate* isolate = Isolate::Current();
+  old_state_ = isolate->allow_handle_deref();
+  isolate->set_allow_handle_deref(true);
+}
+
+
+AllowHandleDereference::~AllowHandleDereference() {
+  if (FLAG_parallel_recompilation) return;
+  Isolate::Current()->set_allow_handle_deref(old_state_);
+}
 #endif
 
 
index 684f4ca..7efb252 100644 (file)
@@ -58,25 +58,21 @@ class Handle {
     a = b;  // Fake assignment to enforce type checks.
     USE(a);
 #endif
-    location_ = reinterpret_cast<T**>(handle.location());
+    location_ = reinterpret_cast<T**>(handle.location_);
   }
 
   INLINE(T* operator ->() const) { return operator*(); }
 
   // Check if this handle refers to the exact same object as the other handle.
   bool is_identical_to(const Handle<T> other) const {
-    return operator*() == *other;
+    return *location_ == *other.location_;
   }
 
   // Provides the C++ dereference operator.
   INLINE(T* operator*() const);
 
   // Returns the address to where the raw pointer is stored.
-  T** location() const {
-    ASSERT(location_ == NULL ||
-           reinterpret_cast<Address>(*location_) != kZapValue);
-    return location_;
-  }
+  INLINE(T** location() const);
 
   template <class S> static Handle<T> cast(Handle<S> that) {
     T::cast(*that);
@@ -92,6 +88,9 @@ class Handle {
 
  private:
   T** location_;
+
+  // Handles of different classes are allowed to access each other's location_.
+  template<class S> friend class Handle;
 };
 
 
@@ -339,6 +338,34 @@ class NoHandleAllocation BASE_EMBEDDED {
 #endif
 };
 
+
+class NoHandleDereference BASE_EMBEDDED {
+ public:
+#ifndef DEBUG
+  NoHandleDereference() {}
+  ~NoHandleDereference() {}
+#else
+  inline NoHandleDereference();
+  inline ~NoHandleDereference();
+ private:
+  bool old_state_;
+#endif
+};
+
+
+class AllowHandleDereference BASE_EMBEDDED {
+ public:
+#ifndef DEBUG
+  AllowHandleDereference() {}
+  ~AllowHandleDereference() {}
+#else
+  inline AllowHandleDereference();
+  inline ~AllowHandleDereference();
+ private:
+  bool old_state_;
+#endif
+};
+
 } }  // namespace v8::internal
 
 #endif  // V8_HANDLES_H_
index fc6c3c5..f951b35 100644 (file)
@@ -342,6 +342,10 @@ const char* HType::ToString() {
 
 
 HType HType::TypeFromValue(Handle<Object> value) {
+  // Handle dereferencing is safe here: an object's type as checked below
+  // never changes.
+  AllowHandleDereference allow_handle_deref;
+
   HType result = HType::Tagged();
   if (value->IsSmi()) {
     result = HType::Smi();
@@ -1119,10 +1123,11 @@ HValue* HCheckInstanceType::Canonicalize() {
       value()->type().IsString()) {
     return NULL;
   }
-  if (check_ == IS_SYMBOL &&
-      value()->IsConstant() &&
-      HConstant::cast(value())->handle()->IsSymbol()) {
-    return NULL;
+
+  if (check_ == IS_SYMBOL && value()->IsConstant()) {
+    // Dereferencing is safe here: a symbol cannot become a non-symbol.
+    AllowHandleDereference allow_handle_deref;
+    if (HConstant::cast(value())->handle()->IsSymbol()) return NULL;
   }
   return this;
 }
@@ -1555,6 +1560,8 @@ HConstant::HConstant(Handle<Object> handle, Representation r)
     : handle_(handle),
       has_int32_value_(false),
       has_double_value_(false) {
+  // Dereferencing here is safe: the value of a number object does not change.
+  AllowHandleDereference allow_handle_deref;
   SetFlag(kUseGVN);
   if (handle_->IsNumber()) {
     double n = handle_->Number();
@@ -1633,12 +1640,14 @@ bool HConstant::ToBoolean() {
     double v = DoubleValue();
     return v != 0 && !isnan(v);
   }
-  Handle<Object> literal = handle();
-  if (literal->IsTrue()) return true;
-  if (literal->IsFalse()) return false;
-  if (literal->IsUndefined()) return false;
-  if (literal->IsNull()) return false;
-  if (literal->IsString() && String::cast(*literal)->length() == 0) {
+  // Dereferencing is safe: singletons do not change and strings are
+  // immutable.
+  AllowHandleDereference allow_handle_deref;
+  if (handle_->IsTrue()) return true;
+  if (handle_->IsFalse()) return false;
+  if (handle_->IsUndefined()) return false;
+  if (handle_->IsNull()) return false;
+  if (handle_->IsString() && String::cast(*handle_)->length() == 0) {
     return false;
   }
   return true;
index 1a43f0f..7988d2f 100644 (file)
@@ -1496,18 +1496,18 @@ class HEnterInlined: public HTemplateInstruction<0> {
   HEnterInlined(Handle<JSFunction> closure,
                 int arguments_count,
                 FunctionLiteral* function,
-                CallKind call_kind,
                 InliningKind inlining_kind,
                 Variable* arguments_var,
-                ZoneList<HValue*>* arguments_values)
+                ZoneList<HValue*>* arguments_values,
+                bool undefined_receiver)
       : closure_(closure),
         arguments_count_(arguments_count),
         arguments_pushed_(false),
         function_(function),
-        call_kind_(call_kind),
         inlining_kind_(inlining_kind),
         arguments_var_(arguments_var),
-        arguments_values_(arguments_values) {
+        arguments_values_(arguments_values),
+        undefined_receiver_(undefined_receiver) {
   }
 
   virtual void PrintDataTo(StringStream* stream);
@@ -1517,8 +1517,8 @@ class HEnterInlined: public HTemplateInstruction<0> {
   bool arguments_pushed() const { return arguments_pushed_; }
   void set_arguments_pushed() { arguments_pushed_ = true; }
   FunctionLiteral* function() const { return function_; }
-  CallKind call_kind() const { return call_kind_; }
   InliningKind inlining_kind() const { return inlining_kind_; }
+  bool undefined_receiver() const { return undefined_receiver_; }
 
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::None();
@@ -1534,10 +1534,10 @@ class HEnterInlined: public HTemplateInstruction<0> {
   int arguments_count_;
   bool arguments_pushed_;
   FunctionLiteral* function_;
-  CallKind call_kind_;
   InliningKind inlining_kind_;
   Variable* arguments_var_;
   ZoneList<HValue*>* arguments_values_;
+  bool undefined_receiver_;
 };
 
 
@@ -2322,6 +2322,7 @@ class HCheckFunction: public HUnaryOperation {
       : HUnaryOperation(value), target_(function) {
     set_representation(Representation::Tagged());
     SetFlag(kUseGVN);
+    target_in_new_space_ = Isolate::Current()->heap()->InNewSpace(*function);
   }
 
   virtual Representation RequiredInputRepresentation(int index) {
@@ -2335,6 +2336,7 @@ class HCheckFunction: public HUnaryOperation {
 #endif
 
   Handle<JSFunction> target() const { return target_; }
+  bool target_in_new_space() const { return target_in_new_space_; }
 
   DECLARE_CONCRETE_INSTRUCTION(CheckFunction)
 
@@ -2346,6 +2348,7 @@ class HCheckFunction: public HUnaryOperation {
 
  private:
   Handle<JSFunction> target_;
+  bool target_in_new_space_;
 };
 
 
@@ -2475,6 +2478,8 @@ class HCheckPrototypeMaps: public HTemplateInstruction<0> {
 
   virtual intptr_t Hashcode() {
     ASSERT_ALLOCATION_DISABLED;
+    // Dereferencing to use the object's raw address for hashing is safe.
+    AllowHandleDereference allow_handle_deref;
     intptr_t hash = 0;
     for (int i = 0; i < prototypes_.length(); i++) {
       hash = 17 * hash + reinterpret_cast<intptr_t>(*prototypes_[i]);
@@ -2692,15 +2697,16 @@ class HConstant: public HTemplateInstruction<0> {
     Heap* heap = HEAP;
     // We should have handled minus_zero_value and nan_value in the
     // has_double_value_ clause above.
+    // Dereferencing is safe to compare against singletons.
+    AllowHandleDereference allow_handle_deref;
     ASSERT(*handle_ != heap->minus_zero_value());
     ASSERT(*handle_ != heap->nan_value());
-    if (*handle_ == heap->undefined_value()) return true;
-    if (*handle_ == heap->null_value()) return true;
-    if (*handle_ == heap->true_value()) return true;
-    if (*handle_ == heap->false_value()) return true;
-    if (*handle_ == heap->the_hole_value()) return true;
-    if (*handle_ == heap->empty_string()) return true;
-    return false;
+    return *handle_ == heap->undefined_value() ||
+           *handle_ == heap->null_value() ||
+           *handle_ == heap->true_value() ||
+           *handle_ == heap->false_value() ||
+           *handle_ == heap->the_hole_value() ||
+           *handle_ == heap->empty_string();
   }
 
   virtual Representation RequiredInputRepresentation(int index) {
@@ -2752,6 +2758,8 @@ class HConstant: public HTemplateInstruction<0> {
       hash = static_cast<intptr_t>(BitCast<int64_t>(double_value_));
     } else {
       ASSERT(!handle_.is_null());
+      // Dereferencing to use the object's raw address for hashing is safe.
+      AllowHandleDereference allow_handle_deref;
       hash = reinterpret_cast<intptr_t>(*handle_);
     }
 
@@ -2779,7 +2787,7 @@ class HConstant: public HTemplateInstruction<0> {
     } else {
       ASSERT(!handle_.is_null());
       return !other_constant->handle_.is_null() &&
-          *handle_ == *other_constant->handle_;
+          handle_.is_identical_to(other_constant->handle_);
     }
   }
 
@@ -4013,13 +4021,15 @@ class HLoadGlobalCell: public HTemplateInstruction<0> {
     SetGVNFlag(kDependsOnGlobalVars);
   }
 
-  Handle<JSGlobalPropertyCell>  cell() const { return cell_; }
+  Handle<JSGlobalPropertyCell> cell() const { return cell_; }
   bool RequiresHoleCheck() const;
 
   virtual void PrintDataTo(StringStream* stream);
 
   virtual intptr_t Hashcode() {
     ASSERT_ALLOCATION_DISABLED;
+    // Dereferencing to use the object's raw address for hashing is safe.
+    AllowHandleDereference allow_handle_deref;
     return reinterpret_cast<intptr_t>(*cell_);
   }
 
@@ -4812,7 +4822,9 @@ class HTransitionElementsKind: public HTemplateInstruction<1> {
                           Handle<Map> original_map,
                           Handle<Map> transitioned_map)
       : original_map_(original_map),
-        transitioned_map_(transitioned_map) {
+        transitioned_map_(transitioned_map),
+        from_kind_(original_map->elements_kind()),
+        to_kind_(transitioned_map->elements_kind()) {
     SetOperandAt(0, object);
     SetFlag(kUseGVN);
     SetGVNFlag(kChangesElementsKind);
@@ -4834,6 +4846,8 @@ class HTransitionElementsKind: public HTemplateInstruction<1> {
   HValue* object() { return OperandAt(0); }
   Handle<Map> original_map() { return original_map_; }
   Handle<Map> transitioned_map() { return transitioned_map_; }
+  ElementsKind from_kind() { return from_kind_; }
+  ElementsKind to_kind() { return to_kind_; }
 
   virtual void PrintDataTo(StringStream* stream);
 
@@ -4849,6 +4863,8 @@ class HTransitionElementsKind: public HTemplateInstruction<1> {
  private:
   Handle<Map> original_map_;
   Handle<Map> transitioned_map_;
+  ElementsKind from_kind_;
+  ElementsKind to_kind_;
 };
 
 
index eb72a3d..6f7760c 100644 (file)
@@ -497,6 +497,8 @@ class ReachabilityAnalyzer BASE_EMBEDDED {
 
 
 void HGraph::Verify(bool do_full_verify) const {
+  // Allow dereferencing for debug mode verification.
+  AllowHandleDereference allow_handle_deref;
   for (int i = 0; i < blocks_.length(); i++) {
     HBasicBlock* block = blocks_.at(i);
 
@@ -2242,7 +2244,7 @@ void HGlobalValueNumberer::ProcessLoopBlock(
 
 
 bool HGlobalValueNumberer::AllowCodeMotion() {
-  return info()->shared_info()->opt_count() + 1 < FLAG_max_opt_count;
+  return info()->opt_count() + 1 < FLAG_max_opt_count;
 }
 
 
@@ -7221,13 +7223,15 @@ bool HOptimizedGraphBuilder::TryInline(CallKind call_kind,
       this, &target_info, &target_oracle, inlining_kind);
 
   HConstant* undefined = graph()->GetConstantUndefined();
+  bool undefined_receiver = HEnvironment::UseUndefinedReceiver(
+      target, function, call_kind, inlining_kind);
   HEnvironment* inner_env =
       environment()->CopyForInlining(target,
                                      arguments_count,
                                      function,
                                      undefined,
-                                     call_kind,
-                                     function_state()->inlining_kind());
+                                     function_state()->inlining_kind(),
+                                     undefined_receiver);
 #ifdef V8_TARGET_ARCH_IA32
   // IA32 only, overwrite the caller's context in the deoptimization
   // environment with the correct one.
@@ -7261,10 +7265,10 @@ bool HOptimizedGraphBuilder::TryInline(CallKind call_kind,
       new(zone()) HEnterInlined(target,
                                 arguments_count,
                                 function,
-                                call_kind,
                                 function_state()->inlining_kind(),
                                 function->scope()->arguments(),
-                                arguments_values);
+                                arguments_values,
+                                undefined_receiver);
   function_state()->set_entry(enter_inlined);
   AddInstruction(enter_inlined);
 
@@ -9886,8 +9890,8 @@ HEnvironment* HEnvironment::CopyForInlining(
     int arguments,
     FunctionLiteral* function,
     HConstant* undefined,
-    CallKind call_kind,
-    InliningKind inlining_kind) const {
+    InliningKind inlining_kind,
+    bool undefined_receiver) const {
   ASSERT(frame_type() == JS_FUNCTION);
 
   // Outer environment is a copy of this one without the arguments.
@@ -9928,8 +9932,7 @@ HEnvironment* HEnvironment::CopyForInlining(
   // If the function we are inlining is a strict mode function or a
   // builtin function, pass undefined as the receiver for function
   // calls (instead of the global receiver).
-  if ((target->shared()->native() || !function->is_classic_mode()) &&
-      call_kind == CALL_AS_FUNCTION && inlining_kind != CONSTRUCT_CALL_RETURN) {
+  if (undefined_receiver) {
     inner->SetValueAt(0, undefined);
   }
   inner->SetValueAt(arity + 1, LookupContext());
index faaffc3..4d66aef 100644 (file)
@@ -552,8 +552,16 @@ class HEnvironment: public ZoneObject {
                                 int arguments,
                                 FunctionLiteral* function,
                                 HConstant* undefined,
-                                CallKind call_kind,
-                                InliningKind inlining_kind) const;
+                                InliningKind inlining_kind,
+                                bool undefined_receiver) const;
+
+  static bool UseUndefinedReceiver(Handle<JSFunction> closure,
+                                   FunctionLiteral* function,
+                                   CallKind call_kind,
+                                   InliningKind inlining_kind) {
+    return (closure->shared()->native() || !function->is_classic_mode()) &&
+        call_kind == CALL_AS_FUNCTION && inlining_kind != CONSTRUCT_CALL_RETURN;
+  }
 
   HEnvironment* DiscardInlined(bool drop_extra) {
     HEnvironment* outer = outer_;
index ab2febb..fd4000b 100644 (file)
@@ -4309,8 +4309,8 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
 
   Handle<Map> from_map = instr->original_map();
   Handle<Map> to_map = instr->transitioned_map();
-  ElementsKind from_kind = from_map->elements_kind();
-  ElementsKind to_kind = to_map->elements_kind();
+  ElementsKind from_kind = instr->from_kind();
+  ElementsKind to_kind = instr->to_kind();
 
   Label not_applicable;
   bool is_simple_map_transition =
@@ -5072,7 +5072,7 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
 
 void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
   Handle<JSFunction> target = instr->hydrogen()->target();
-  if (isolate()->heap()->InNewSpace(*target)) {
+  if (instr->hydrogen()->target_in_new_space()) {
     Register reg = ToRegister(instr->value());
     Handle<JSGlobalPropertyCell> cell =
         isolate()->factory()->NewJSGlobalPropertyCell(target);
index 8bb5740..118aa1c 100644 (file)
@@ -1863,9 +1863,8 @@ LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
   // want the value in a register.  If the target gets promoted before we
   // emit code, we will still get the register but will do an immediate
   // compare instead of the cell compare.  This is safe.
-  LOperand* value = Isolate::Current()->heap()->InNewSpace(*instr->target())
-      ? UseRegisterAtStart(instr->value())
-      : UseAtStart(instr->value());
+  LOperand* value = instr->target_in_new_space()
+      ? UseRegisterAtStart(instr->value()) : UseAtStart(instr->value());
   return AssignEnvironment(new(zone()) LCheckFunction(value));
 }
 
@@ -2160,9 +2159,7 @@ LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
 
 LInstruction* LChunkBuilder::DoTransitionElementsKind(
     HTransitionElementsKind* instr) {
-  ElementsKind from_kind = instr->original_map()->elements_kind();
-  ElementsKind to_kind = instr->transitioned_map()->elements_kind();
-  if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
+  if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
     LOperand* object = UseRegister(instr->object());
     LOperand* new_map_reg = TempRegister();
     LOperand* temp_reg = TempRegister();
@@ -2451,8 +2448,8 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
                                                instr->arguments_count(),
                                                instr->function(),
                                                undefined,
-                                               instr->call_kind(),
-                                               instr->inlining_kind());
+                                               instr->inlining_kind(),
+                                               instr->undefined_receiver());
   if (instr->arguments_var() != NULL) {
     inner->Bind(instr->arguments_var(), graph()->GetArgumentsObject());
   }
index 2ccfd5d..7ef71d7 100644 (file)
@@ -2114,6 +2114,8 @@ class LTransitionElementsKind: public LTemplateInstruction<1, 1, 2> {
 
   Handle<Map> original_map() { return hydrogen()->original_map(); }
   Handle<Map> transitioned_map() { return hydrogen()->transitioned_map(); }
+  ElementsKind from_kind() { return hydrogen()->from_kind(); }
+  ElementsKind to_kind() { return hydrogen()->to_kind(); }
 };
 
 
index 8bcceab..0e59578 100644 (file)
@@ -1677,6 +1677,8 @@ Isolate::Isolate()
   memset(&js_spill_information_, 0, sizeof(js_spill_information_));
   memset(code_kind_statistics_, 0,
          sizeof(code_kind_statistics_[0]) * Code::NUMBER_OF_KINDS);
+
+  allow_handle_deref_ = true;
 #endif
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
index d43c451..286f674 100644 (file)
@@ -969,6 +969,9 @@ class Isolate {
   }
 
   int* code_kind_statistics() { return code_kind_statistics_; }
+
+  bool allow_handle_deref() { return allow_handle_deref_; }
+  void set_allow_handle_deref(bool allow) { allow_handle_deref_ = allow; }
 #endif
 
 #if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
@@ -1266,6 +1269,8 @@ class Isolate {
   HistogramInfo heap_histograms_[LAST_TYPE + 1];
   JSObject::SpillInformation js_spill_information_;
   int code_kind_statistics_[Code::NUMBER_OF_KINDS];
+
+  bool allow_handle_deref_;
 #endif
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
index 77557c5..cf192f4 100644 (file)
@@ -4132,8 +4132,8 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
 
   Handle<Map> from_map = instr->original_map();
   Handle<Map> to_map = instr->transitioned_map();
-  ElementsKind from_kind = from_map->elements_kind();
-  ElementsKind to_kind = to_map->elements_kind();
+  ElementsKind from_kind = instr->from_kind();
+  ElementsKind to_kind = instr->to_kind();
 
   Label not_applicable;
   __ Cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map);
index c31de81..fba2318 100644 (file)
@@ -2039,9 +2039,7 @@ LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
 
 LInstruction* LChunkBuilder::DoTransitionElementsKind(
     HTransitionElementsKind* instr) {
-  ElementsKind from_kind = instr->original_map()->elements_kind();
-  ElementsKind to_kind = instr->transitioned_map()->elements_kind();
-  if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
+  if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
     LOperand* object = UseRegister(instr->object());
     LOperand* new_map_reg = TempRegister();
     LOperand* temp_reg = TempRegister();
@@ -2299,8 +2297,8 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
                                                instr->arguments_count(),
                                                instr->function(),
                                                undefined,
-                                               instr->call_kind(),
-                                               instr->inlining_kind());
+                                               instr->inlining_kind(),
+                                               instr->undefined_receiver());
   if (instr->arguments_var() != NULL) {
     inner->Bind(instr->arguments_var(), graph()->GetArgumentsObject());
   }
index baa0d98..f518f4a 100644 (file)
@@ -1993,6 +1993,8 @@ class LTransitionElementsKind: public LTemplateInstruction<1, 1, 2> {
 
   Handle<Map> original_map() { return hydrogen()->original_map(); }
   Handle<Map> transitioned_map() { return hydrogen()->transitioned_map(); }
+  ElementsKind from_kind() { return hydrogen()->from_kind(); }
+  ElementsKind to_kind() { return hydrogen()->to_kind(); }
 };