Contribution of PowerPC port (continuation of 422063005) - uplevel
authormichael_dawson <michael_dawson@ca.ibm.com>
Wed, 11 Mar 2015 08:49:27 +0000 (01:49 -0700)
committerCommit bot <commit-bot@chromium.org>
Wed, 11 Mar 2015 08:49:33 +0000 (08:49 +0000)
Contribution of PowerPC port (continuation of 422063005,
817143002,866843003, and 901083004). This patch updates
the ppc directories to make them current with changes in
common code as of today.

We had to exclude the test test-serialize/SerializeInternalReference
until we agree on the right way to add those changes for PPC as
outlined in the description in the google doc provided earlier.

We also had to exclude a couple of other tests due to new
failures seen since the last uplevel.  We excluded as opposed
to waiting until we could investigate to maximize the chance
of getting PPC compiling in the google repos before new
breaking changes are made.

I'll note that before applying any of our changes the
mozilla part of quickcheck was already broken when using
the lastest repo content so I had to run without that

modified:   src/compiler/ppc/code-generator-ppc.cc
modified:   src/compiler/ppc/instruction-codes-ppc.h
modified:   src/compiler/ppc/instruction-selector-ppc.cc
modified:   src/ic/ppc/handler-compiler-ppc.cc
modified:   src/ic/ppc/ic-compiler-ppc.cc
modified:   src/ppc/assembler-ppc-inl.h
modified:   src/ppc/assembler-ppc.cc
modified:   src/ppc/assembler-ppc.h
modified:   src/ppc/builtins-ppc.cc
modified:   src/ppc/code-stubs-ppc.cc
modified:   src/ppc/codegen-ppc.cc
modified:   src/ppc/full-codegen-ppc.cc
modified:   src/ppc/lithium-codegen-ppc.cc
modified:   src/ppc/macro-assembler-ppc.cc
modified:   src/ppc/macro-assembler-ppc.h
modified:   test/cctest/cctest.status

R=danno@chromium.org, svenpanne@chromium.org

BUG=

Review URL: https://codereview.chromium.org/994533004

Cr-Commit-Position: refs/heads/master@{#27125}

17 files changed:
src/compiler/ppc/code-generator-ppc.cc
src/compiler/ppc/instruction-codes-ppc.h
src/compiler/ppc/instruction-selector-ppc.cc
src/ic/ppc/handler-compiler-ppc.cc
src/ic/ppc/ic-compiler-ppc.cc
src/ppc/assembler-ppc-inl.h
src/ppc/assembler-ppc.cc
src/ppc/assembler-ppc.h
src/ppc/builtins-ppc.cc
src/ppc/code-stubs-ppc.cc
src/ppc/codegen-ppc.cc
src/ppc/full-codegen-ppc.cc
src/ppc/lithium-codegen-ppc.cc
src/ppc/macro-assembler-ppc.cc
src/ppc/macro-assembler-ppc.h
test/cctest/cctest.status
test/mjsunit/mjsunit.status

index d1889fb426ec002a06a65ca52bf0a4dc0bc8f3c8..8ac9c6114b598a9631f848066462c34a1d3773e7 100644 (file)
@@ -903,6 +903,32 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
       __ Move(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
       DCHECK_EQ(LeaveRC, i.OutputRCBit());
       break;
+    case kPPC_Float64ExtractLowWord32:
+      __ MovDoubleLowToInt(i.OutputRegister(), i.InputDoubleRegister(0));
+      DCHECK_EQ(LeaveRC, i.OutputRCBit());
+      break;
+    case kPPC_Float64ExtractHighWord32:
+      __ MovDoubleHighToInt(i.OutputRegister(), i.InputDoubleRegister(0));
+      DCHECK_EQ(LeaveRC, i.OutputRCBit());
+      break;
+    case kPPC_Float64InsertLowWord32:
+      __ InsertDoubleLow(i.OutputDoubleRegister(), i.InputRegister(1), r0);
+      DCHECK_EQ(LeaveRC, i.OutputRCBit());
+      break;
+    case kPPC_Float64InsertHighWord32:
+      __ InsertDoubleHigh(i.OutputDoubleRegister(), i.InputRegister(1), r0);
+      DCHECK_EQ(LeaveRC, i.OutputRCBit());
+      break;
+    case kPPC_Float64Construct:
+#if V8_TARGET_ARCH_PPC64
+      __ MovInt64ComponentsToDouble(i.OutputDoubleRegister(),
+                                    i.InputRegister(0), i.InputRegister(1), r0);
+#else
+      __ MovInt64ToDouble(i.OutputDoubleRegister(), i.InputRegister(0),
+                          i.InputRegister(1));
+#endif
+      DCHECK_EQ(LeaveRC, i.OutputRCBit());
+      break;
     case kPPC_LoadWordU8:
       ASSEMBLE_LOAD_INTEGER(lbz, lbzx);
       break;
index 715a904fef44deedc072b54de022f37db37969c6..f2475c9b698d79cc6f1bc19480688650625da618 100644 (file)
@@ -84,6 +84,11 @@ namespace compiler {
   V(PPC_Float64ToInt32)            \
   V(PPC_Float64ToUint32)           \
   V(PPC_Float64ToFloat32)          \
+  V(PPC_Float64ExtractLowWord32)   \
+  V(PPC_Float64ExtractHighWord32)  \
+  V(PPC_Float64InsertLowWord32)    \
+  V(PPC_Float64InsertHighWord32)   \
+  V(PPC_Float64Construct)          \
   V(PPC_LoadWordS8)                \
   V(PPC_LoadWordU8)                \
   V(PPC_LoadWordS16)               \
index bed80ed2ce4e87dfd3e289aa53d5a6ea00f67fa3..56d683479b882d9eff945dc7be803cd44c40714a 100644 (file)
@@ -925,6 +925,21 @@ void InstructionSelector::VisitFloat64Add(Node* node) {
 
 void InstructionSelector::VisitFloat64Sub(Node* node) {
   // TODO(mbrandy): detect multiply-subtract
+  PPCOperandGenerator g(this);
+  Float64BinopMatcher m(node);
+  if (m.left().IsMinusZero() && m.right().IsFloat64RoundDown() &&
+      CanCover(m.node(), m.right().node())) {
+    if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat64Sub &&
+        CanCover(m.right().node(), m.right().InputAt(0))) {
+      Float64BinopMatcher mright0(m.right().InputAt(0));
+      if (mright0.left().IsMinusZero()) {
+        // -floor(-x) = ceil(x)
+        Emit(kPPC_CeilFloat64, g.DefineAsRegister(node),
+             g.UseRegister(mright0.right().node()));
+        return;
+      }
+    }
+  }
   VisitRRRFloat64(this, node, kPPC_SubFloat64);
 }
 
@@ -953,16 +968,11 @@ void InstructionSelector::VisitFloat64Sqrt(Node* node) {
 }
 
 
-void InstructionSelector::VisitFloat64Floor(Node* node) {
+void InstructionSelector::VisitFloat64RoundDown(Node* node) {
   VisitRRFloat64(this, kPPC_FloorFloat64, node);
 }
 
 
-void InstructionSelector::VisitFloat64Ceil(Node* node) {
-  VisitRRFloat64(this, kPPC_CeilFloat64, node);
-}
-
-
 void InstructionSelector::VisitFloat64RoundTruncate(Node* node) {
   VisitRRFloat64(this, kPPC_TruncateFloat64, node);
 }
@@ -1111,19 +1121,9 @@ static void VisitWordCompareZero(InstructionSelector* selector, Node* user,
         cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
         return VisitWord32Compare(selector, value, cont);
 #if V8_TARGET_ARCH_PPC64
-      case IrOpcode::kWord64Equal: {
-        // Combine with comparisons against 0 by simply inverting the
-        // continuation.
-        Int64BinopMatcher m(value);
-        if (m.right().Is(0)) {
-          user = value;
-          value = m.left().node();
-          cont->Negate();
-          continue;
-        }
+      case IrOpcode::kWord64Equal:
         cont->OverwriteAndNegateIfEqual(kEqual);
         return VisitWord64Compare(selector, value, cont);
-      }
       case IrOpcode::kInt64LessThan:
         cont->OverwriteAndNegateIfEqual(kSignedLessThan);
         return VisitWord64Compare(selector, value, cont);
@@ -1436,11 +1436,56 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
 }
 
 
+void InstructionSelector::VisitFloat64ExtractLowWord32(Node* node) {
+  PPCOperandGenerator g(this);
+  Emit(kPPC_Float64ExtractLowWord32, g.DefineAsRegister(node),
+       g.UseRegister(node->InputAt(0)));
+}
+
+
+void InstructionSelector::VisitFloat64ExtractHighWord32(Node* node) {
+  PPCOperandGenerator g(this);
+  Emit(kPPC_Float64ExtractHighWord32, g.DefineAsRegister(node),
+       g.UseRegister(node->InputAt(0)));
+}
+
+
+void InstructionSelector::VisitFloat64InsertLowWord32(Node* node) {
+  PPCOperandGenerator g(this);
+  Node* left = node->InputAt(0);
+  Node* right = node->InputAt(1);
+  if (left->opcode() == IrOpcode::kFloat64InsertHighWord32 &&
+      CanCover(node, left)) {
+    left = left->InputAt(1);
+    Emit(kPPC_Float64Construct, g.DefineAsRegister(node), g.UseRegister(left),
+         g.UseRegister(right));
+    return;
+  }
+  Emit(kPPC_Float64InsertLowWord32, g.DefineSameAsFirst(node),
+       g.UseRegister(left), g.UseRegister(right));
+}
+
+
+void InstructionSelector::VisitFloat64InsertHighWord32(Node* node) {
+  PPCOperandGenerator g(this);
+  Node* left = node->InputAt(0);
+  Node* right = node->InputAt(1);
+  if (left->opcode() == IrOpcode::kFloat64InsertLowWord32 &&
+      CanCover(node, left)) {
+    left = left->InputAt(1);
+    Emit(kPPC_Float64Construct, g.DefineAsRegister(node), g.UseRegister(right),
+         g.UseRegister(left));
+    return;
+  }
+  Emit(kPPC_Float64InsertHighWord32, g.DefineSameAsFirst(node),
+       g.UseRegister(left), g.UseRegister(right));
+}
+
+
 // static
 MachineOperatorBuilder::Flags
 InstructionSelector::SupportedMachineOperatorFlags() {
-  return MachineOperatorBuilder::kFloat64Floor |
-         MachineOperatorBuilder::kFloat64Ceil |
+  return MachineOperatorBuilder::kFloat64RoundDown |
          MachineOperatorBuilder::kFloat64RoundTruncate |
          MachineOperatorBuilder::kFloat64RoundTiesAway;
   // We omit kWord32ShiftIsSafe as s[rl]w use 0x3f as a mask rather than 0x1f.
index 4e8cbe1edb27c97786fcb3ad08ad591b0ff74976..55f93a556f7ac3e928617a6e65182ff937b72e6c 100644 (file)
@@ -427,6 +427,16 @@ Register PropertyHandlerCompiler::CheckPrototypes(
   if (receiver_map->IsJSGlobalObjectMap()) {
     current = isolate()->global_object();
   }
+  // Check access rights to the global object.  This has to happen after
+  // the map check so that we know that the object is actually a global
+  // object.
+  // This allows us to install generated handlers for accesses to the
+  // global proxy (as opposed to using slow ICs). See corresponding code
+  // in LookupForRead().
+  if (receiver_map->IsJSGlobalProxyMap()) {
+    __ CheckAccessGlobalProxy(reg, scratch2, miss);
+  }
+
   Handle<JSObject> prototype = Handle<JSObject>::null();
   Handle<Map> current_map = receiver_map;
   Handle<Map> holder_map(holder()->map());
@@ -461,23 +471,14 @@ Register PropertyHandlerCompiler::CheckPrototypes(
     } else {
       Register map_reg = scratch1;
       __ LoadP(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
-      if (depth != 1 || check == CHECK_ALL_MAPS) {
-        Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
-        __ CmpWeakValue(map_reg, cell, scratch2);
-        __ bne(miss);
-      }
 
-      // Check access rights to the global object.  This has to happen after
-      // the map check so that we know that the object is actually a global
-      // object.
-      // This allows us to install generated handlers for accesses to the
-      // global proxy (as opposed to using slow ICs). See corresponding code
-      // in LookupForRead().
-      if (current_map->IsJSGlobalProxyMap()) {
-        __ CheckAccessGlobalProxy(reg, scratch2, miss);
-      } else if (current_map->IsJSGlobalObjectMap()) {
+      if (current_map->IsJSGlobalObjectMap()) {
         GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
                                   name, scratch2, miss);
+      } else if (depth != 1 || check == CHECK_ALL_MAPS) {
+        Handle<WeakCell> cell = Map::WeakCellForMap(current_map);
+        __ CmpWeakValue(map_reg, cell, scratch2);
+        __ bne(miss);
       }
 
       reg = holder_reg;  // From now on the object will be in holder_reg.
@@ -501,13 +502,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
     __ bne(miss);
   }
 
-  // Perform security check for access to the global object.
-  DCHECK(current_map->IsJSGlobalProxyMap() ||
-         !current_map->is_access_check_needed());
-  if (current_map->IsJSGlobalProxyMap()) {
-    __ CheckAccessGlobalProxy(reg, scratch1, miss);
-  }
-
   // Return the register containing the holder.
   return reg;
 }
index 5c5d1c3e3c6862e3a26b7228c1d8090d41607e53..9f33a59e7b8a1830aebbc5ad734b2d972bb7cad9 100644 (file)
@@ -74,11 +74,14 @@ Handle<Code> PropertyICCompiler::CompilePolymorphic(MapHandleList* maps,
       number_of_handled_maps++;
       Handle<WeakCell> cell = Map::WeakCellForMap(map);
       __ CmpWeakValue(map_reg, cell, scratch2());
+      Label next;
+      __ bne(&next);
       if (map->instance_type() == HEAP_NUMBER_TYPE) {
         DCHECK(!number_case.is_unused());
         __ bind(&number_case);
       }
-      __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, eq);
+      __ Jump(handlers->at(current), RelocInfo::CODE_TARGET);
+      __ bind(&next);
     }
   }
   DCHECK(number_of_handled_maps != 0);
index 86bb6db435b379335cc020586eeb582007c5d136..e05d38468f979095e901c5263e02e3cb5a1cbbe7 100644 (file)
@@ -51,10 +51,41 @@ bool CpuFeatures::SupportsCrankshaft() { return true; }
 
 
 void RelocInfo::apply(intptr_t delta, ICacheFlushMode icache_flush_mode) {
-  if (IsInternalReference(rmode_) || IsInternalReferenceEncoded(rmode_)) {
-    // absolute code pointer inside code object moves with the code object.
-    Assembler::RelocateInternalReference(pc_, delta, 0, rmode_,
-                                         icache_flush_mode);
+  // absolute code pointer inside code object moves with the code object.
+  if (IsInternalReference(rmode_)) {
+    // Jump table entry
+    Address target = Memory::Address_at(pc_);
+    Memory::Address_at(pc_) = target + delta;
+  } else {
+    // mov sequence
+    DCHECK(IsInternalReferenceEncoded(rmode_));
+    Address target = Assembler::target_address_at(pc_, host_);
+    Assembler::set_target_address_at(pc_, host_, target + delta,
+                                     icache_flush_mode);
+  }
+}
+
+
+Address RelocInfo::target_internal_reference() {
+  if (IsInternalReference(rmode_)) {
+    // Jump table entry
+    return Memory::Address_at(pc_);
+  } else {
+    // mov sequence
+    DCHECK(IsInternalReferenceEncoded(rmode_));
+    return Assembler::target_address_at(pc_, host_);
+  }
+}
+
+
+void RelocInfo::set_target_internal_reference(Address target) {
+  if (IsInternalReference(rmode_)) {
+    // Jump table entry
+    Memory::Address_at(pc_) = target;
+  } else {
+    // mov sequence
+    DCHECK(IsInternalReferenceEncoded(rmode_));
+    Assembler::set_target_address_at(pc_, host_, target, SKIP_ICACHE_FLUSH);
   }
 }
 
@@ -160,18 +191,6 @@ Address RelocInfo::target_external_reference() {
 }
 
 
-Address RelocInfo::target_internal_reference() {
-  DCHECK(rmode_ == INTERNAL_REFERENCE);
-  return Memory::Address_at(pc_);
-}
-
-
-void RelocInfo::set_target_internal_reference(Address target) {
-  DCHECK(rmode_ == INTERNAL_REFERENCE);
-  Memory::Address_at(pc_) = target;
-}
-
-
 Address RelocInfo::target_runtime_entry(Assembler* origin) {
   DCHECK(IsRuntimeEntry(rmode_));
   return target_address();
index 671133f998eb465d942a241b042559fe761a9cf5..d87e1b19f1c18ffe4737fd5110a6c50368a8361a 100644 (file)
@@ -217,11 +217,12 @@ Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
   trampoline_emitted_ = FLAG_force_long_branches;
   unbound_labels_count_ = 0;
   ClearRecordedAstId();
+  relocations_.reserve(128);
 }
 
 
 void Assembler::GetCode(CodeDesc* desc) {
-  reloc_info_writer.Finish();
+  EmitRelocations();
 
   // Set up code descriptor.
   desc->buffer = buffer_;
@@ -378,8 +379,9 @@ const int kEndOfChain = -4;
 // Dummy opcodes for unbound label mov instructions or jump table entries.
 enum {
   kUnboundMovLabelOffsetOpcode = 0 << 26,
-  kUnboundMovLabelAddrOpcode = 1 << 26,
-  kUnboundJumpTableEntryOpcode = 2 << 26
+  kUnboundAddLabelOffsetOpcode = 1 << 26,
+  kUnboundMovLabelAddrOpcode = 2 << 26,
+  kUnboundJumpTableEntryOpcode = 3 << 26
 };
 
 
@@ -398,6 +400,7 @@ int Assembler::target_at(int pos) {
       link &= ~(kAAMask | kLKMask);  // discard AA|LK bits if present
       break;
     case kUnboundMovLabelOffsetOpcode:
+    case kUnboundAddLabelOffsetOpcode:
     case kUnboundMovLabelAddrOpcode:
     case kUnboundJumpTableEntryOpcode:
       link = SIGN_EXT_IMM26(instr & kImm26Mask);
@@ -454,22 +457,31 @@ void Assembler::target_at_put(int pos, int target_pos) {
       patcher.masm()->bitwise_mov32(dst, offset);
       break;
     }
+    case kUnboundAddLabelOffsetOpcode: {
+      // dst = base + position + immediate
+      Instr operands = instr_at(pos + kInstrSize);
+      Register dst = Register::from_code((operands >> 21) & 0x1f);
+      Register base = Register::from_code((operands >> 16) & 0x1f);
+      int32_t offset = target_pos + SIGN_EXT_IMM16(operands & kImm16Mask);
+      CodePatcher patcher(reinterpret_cast<byte*>(buffer_ + pos), 2,
+                          CodePatcher::DONT_FLUSH);
+      patcher.masm()->bitwise_add32(dst, base, offset);
+      break;
+    }
     case kUnboundMovLabelAddrOpcode: {
       // Load the address of the label in a register.
       Register dst = Register::from_code(instr_at(pos + kInstrSize));
-      intptr_t addr = reinterpret_cast<uintptr_t>(buffer_ + target_pos);
       CodePatcher patcher(reinterpret_cast<byte*>(buffer_ + pos),
                           kMovInstructions, CodePatcher::DONT_FLUSH);
-      AddBoundInternalReferenceLoad(pos);
-      patcher.masm()->bitwise_mov(dst, addr);
+      // Keep internal references relative until EmitRelocations.
+      patcher.masm()->bitwise_mov(dst, target_pos);
       break;
     }
     case kUnboundJumpTableEntryOpcode: {
-      intptr_t addr = reinterpret_cast<uintptr_t>(buffer_ + target_pos);
       CodePatcher patcher(reinterpret_cast<byte*>(buffer_ + pos),
                           kPointerSize / kInstrSize, CodePatcher::DONT_FLUSH);
-      AddBoundInternalReference(pos);
-      patcher.masm()->emit_ptr(addr);
+      // Keep internal references relative until EmitRelocations.
+      patcher.masm()->emit_ptr(target_pos);
       break;
     }
     default:
@@ -490,6 +502,7 @@ int Assembler::max_reach_from(int pos) {
     case BCX:
       return 16;
     case kUnboundMovLabelOffsetOpcode:
+    case kUnboundAddLabelOffsetOpcode:
     case kUnboundMovLabelAddrOpcode:
     case kUnboundJumpTableEntryOpcode:
       return 0;  // no limit on reach
@@ -1487,37 +1500,6 @@ void Assembler::function_descriptor() {
 }
 
 
-void Assembler::RelocateInternalReference(Address pc, intptr_t delta,
-                                          Address code_start,
-                                          RelocInfo::Mode rmode,
-                                          ICacheFlushMode icache_flush_mode) {
-  if (RelocInfo::IsInternalReference(rmode)) {
-    // Jump table entry
-    DCHECK(delta || code_start);
-    uintptr_t* entry = reinterpret_cast<uintptr_t*>(pc);
-    if (delta) {
-      *entry += delta;
-    } else {
-      // remove when serializer properly supports internal references
-      *entry = reinterpret_cast<uintptr_t>(code_start) + 3 * kPointerSize;
-    }
-  } else {
-    // mov sequence
-    DCHECK(delta || code_start);
-    DCHECK(RelocInfo::IsInternalReferenceEncoded(rmode));
-    ConstantPoolArray* constant_pool = NULL;
-    Address addr;
-    if (delta) {
-      addr = target_address_at(pc, constant_pool) + delta;
-    } else {
-      // remove when serializer properly supports internal references
-      addr = code_start;
-    }
-    set_target_address_at(pc, constant_pool, addr, icache_flush_mode);
-  }
-}
-
-
 void Assembler::EnsureSpaceFor(int space_needed) {
   if (buffer_space() <= (kGap + space_needed)) {
     GrowBuffer(space_needed);
@@ -1544,11 +1526,11 @@ bool Operand::must_output_reloc_info(const Assembler* assembler) const {
 // and only use the generic version when we require a fixed sequence
 void Assembler::mov(Register dst, const Operand& src) {
   intptr_t value = src.immediate();
+  bool relocatable = src.must_output_reloc_info(this);
   bool canOptimize;
-  RelocInfo rinfo(pc_, src.rmode_, value, NULL);
 
-  canOptimize = !(src.must_output_reloc_info(this) ||
-                  (is_trampoline_pool_blocked() && !is_int16(value)));
+  canOptimize =
+      !(relocatable || (is_trampoline_pool_blocked() && !is_int16(value)));
 
   if (canOptimize) {
     if (is_int16(value)) {
@@ -1586,8 +1568,8 @@ void Assembler::mov(Register dst, const Operand& src) {
   }
 
   DCHECK(!canOptimize);
-  if (src.must_output_reloc_info(this)) {
-    RecordRelocInfo(rinfo);
+  if (relocatable) {
+    RecordRelocInfo(src.rmode_);
   }
   bitwise_mov(dst, value);
 }
@@ -1625,6 +1607,21 @@ void Assembler::bitwise_mov32(Register dst, int32_t value) {
 }
 
 
+void Assembler::bitwise_add32(Register dst, Register src, int32_t value) {
+  BlockTrampolinePoolScope block_trampoline_pool(this);
+  if (is_int16(value)) {
+    addi(dst, src, Operand(value));
+    nop();
+  } else {
+    int hi_word = static_cast<int>(value >> 16);
+    int lo_word = static_cast<int>(value & 0xffff);
+    if (lo_word & 0x8000) hi_word++;
+    addis(dst, src, Operand(SIGN_EXT_IMM16(hi_word)));
+    addic(dst, dst, Operand(SIGN_EXT_IMM16(lo_word)));
+  }
+}
+
+
 void Assembler::mov_label_offset(Register dst, Label* label) {
   int position = link(label);
   if (label->is_bound()) {
@@ -1652,18 +1649,37 @@ void Assembler::mov_label_offset(Register dst, Label* label) {
 }
 
 
+void Assembler::add_label_offset(Register dst, Register base, Label* label,
+                                 int delta) {
+  int position = link(label);
+  if (label->is_bound()) {
+    // dst = base + position + delta
+    position += delta;
+    bitwise_add32(dst, base, position);
+  } else {
+    // Encode internal reference to unbound label. We use a dummy opcode
+    // such that it won't collide with any opcode that might appear in the
+    // label's chain.  Encode the operands in the 2nd instruction.
+    int link = position - pc_offset();
+    DCHECK_EQ(0, link & 3);
+    link >>= 2;
+    DCHECK(is_int26(link));
+    DCHECK(is_int16(delta));
+
+    BlockTrampolinePoolScope block_trampoline_pool(this);
+    emit(kUnboundAddLabelOffsetOpcode | (link & kImm26Mask));
+    emit(dst.code() * B21 | base.code() * B16 | (delta & kImm16Mask));
+  }
+}
+
+
 void Assembler::mov_label_addr(Register dst, Label* label) {
   CheckBuffer();
   RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
   int position = link(label);
   if (label->is_bound()) {
-    // CheckBuffer() is called too frequently. This will pre-grow
-    // the buffer if needed to avoid spliting the relocation and instructions
-    EnsureSpaceFor(kMovInstructions * kInstrSize);
-
-    intptr_t addr = reinterpret_cast<uintptr_t>(buffer_ + position);
-    AddBoundInternalReferenceLoad(pc_offset());
-    bitwise_mov(dst, addr);
+    // Keep internal references relative until EmitRelocations.
+    bitwise_mov(dst, position);
   } else {
     // Encode internal reference to unbound label. We use a dummy opcode
     // such that it won't collide with any opcode that might appear in the
@@ -1692,13 +1708,8 @@ void Assembler::emit_label_addr(Label* label) {
   RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
   int position = link(label);
   if (label->is_bound()) {
-    // CheckBuffer() is called too frequently. This will pre-grow
-    // the buffer if needed to avoid spliting the relocation and entry.
-    EnsureSpaceFor(kPointerSize);
-
-    intptr_t addr = reinterpret_cast<uintptr_t>(buffer_ + position);
-    AddBoundInternalReference(pc_offset());
-    emit_ptr(addr);
+    // Keep internal references relative until EmitRelocations.
+    emit_ptr(position);
   } else {
     // Encode internal reference to unbound label. We use a dummy opcode
     // such that it won't collide with any opcode that might appear in the
@@ -2218,15 +2229,9 @@ void Assembler::GrowBuffer(int needed) {
   reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta,
                                reloc_info_writer.last_pc() + pc_delta);
 
-  // Relocate internal references
-  for (int pos : internal_reference_positions_) {
-    RelocateInternalReference(buffer_ + pos, pc_delta, 0,
-                              RelocInfo::INTERNAL_REFERENCE);
-  }
-  for (int pos : internal_reference_load_positions_) {
-    RelocateInternalReference(buffer_ + pos, pc_delta, 0,
-                              RelocInfo::INTERNAL_REFERENCE_ENCODED);
-  }
+  // Nothing else to do here since we keep all internal references and
+  // deferred relocation entries relative to the buffer (until
+  // EmitRelocations).
 }
 
 
@@ -2251,13 +2256,20 @@ void Assembler::emit_ptr(intptr_t data) {
 }
 
 
+void Assembler::emit_double(double value) {
+  CheckBuffer();
+  *reinterpret_cast<double*>(pc_) = value;
+  pc_ += sizeof(double);
+}
+
+
 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
-  RelocInfo rinfo(pc_, rmode, data, NULL);
+  DeferredRelocInfo rinfo(pc_offset(), rmode, data);
   RecordRelocInfo(rinfo);
 }
 
 
-void Assembler::RecordRelocInfo(const RelocInfo& rinfo) {
+void Assembler::RecordRelocInfo(const DeferredRelocInfo& rinfo) {
   if (rinfo.rmode() >= RelocInfo::JS_RETURN &&
       rinfo.rmode() <= RelocInfo::DEBUG_BREAK_SLOT) {
     // Adjust code for new modes.
@@ -2273,16 +2285,38 @@ void Assembler::RecordRelocInfo(const RelocInfo& rinfo) {
         return;
       }
     }
-    DCHECK(buffer_space() >= kMaxRelocSize);  // too late to grow buffer here
     if (rinfo.rmode() == RelocInfo::CODE_TARGET_WITH_ID) {
-      RelocInfo reloc_info_with_ast_id(rinfo.pc(), rinfo.rmode(),
-                                       RecordedAstId().ToInt(), NULL);
+      DeferredRelocInfo reloc_info_with_ast_id(rinfo.position(), rinfo.rmode(),
+                                               RecordedAstId().ToInt());
       ClearRecordedAstId();
-      reloc_info_writer.Write(&reloc_info_with_ast_id);
+      relocations_.push_back(reloc_info_with_ast_id);
     } else {
-      reloc_info_writer.Write(&rinfo);
+      relocations_.push_back(rinfo);
+    }
+  }
+}
+
+
+void Assembler::EmitRelocations() {
+  EnsureSpaceFor(relocations_.size() * kMaxRelocSize);
+
+  for (std::vector<DeferredRelocInfo>::iterator it = relocations_.begin();
+       it != relocations_.end(); it++) {
+    RelocInfo::Mode rmode = it->rmode();
+    RelocInfo rinfo(buffer_ + it->position(), rmode, it->data(), NULL);
+
+    // Fix up internal references now that they are guaranteed to be bound.
+    if (RelocInfo::IsInternalReference(rmode) ||
+        RelocInfo::IsInternalReferenceEncoded(rmode)) {
+      intptr_t pos =
+          reinterpret_cast<intptr_t>(rinfo.target_internal_reference());
+      rinfo.set_target_internal_reference(buffer_ + pos);
     }
+
+    reloc_info_writer.Write(&rinfo);
   }
+
+  reloc_info_writer.Finish();
 }
 
 
index 27af916db4e59c9ce4acd8c078c5549d772cba5b..9676cbb59f17d4bbd7f9c1507dc5bd7f2d60e259 100644 (file)
@@ -518,6 +518,23 @@ class MemOperand BASE_EMBEDDED {
 };
 
 
+class DeferredRelocInfo {
+ public:
+  DeferredRelocInfo() {}
+  DeferredRelocInfo(int position, RelocInfo::Mode rmode, intptr_t data)
+      : position_(position), rmode_(rmode), data_(data) {}
+
+  int position() const { return position_; }
+  RelocInfo::Mode rmode() const { return rmode_; }
+  intptr_t data() const { return data_; }
+
+ private:
+  int position_;
+  RelocInfo::Mode rmode_;
+  intptr_t data_;
+};
+
+
 class Assembler : public AssemblerBase {
  public:
   // Create an assembler. Instructions and relocation information are emitted
@@ -990,11 +1007,16 @@ class Assembler : public AssemblerBase {
   void mov(Register dst, const Operand& src);
   void bitwise_mov(Register dst, intptr_t value);
   void bitwise_mov32(Register dst, int32_t value);
+  void bitwise_add32(Register dst, Register src, int32_t value);
 
   // Load the position of the label relative to the generated code object
   // pointer in a register.
   void mov_label_offset(Register dst, Label* label);
 
+  // dst = base + label position + delta
+  void add_label_offset(Register dst, Register base, Label* label,
+                        int delta = 0);
+
   // Load the address of the label in a register and associate with an
   // internal reference relocation.
   void mov_label_addr(Register dst, Label* label);
@@ -1212,6 +1234,7 @@ class Assembler : public AssemblerBase {
   void db(uint8_t data);
   void dd(uint32_t data);
   void emit_ptr(intptr_t data);
+  void emit_double(double data);
 
   PositionsRecorder* positions_recorder() { return &positions_recorder_; }
 
@@ -1260,9 +1283,6 @@ class Assembler : public AssemblerBase {
   // The code currently calls CheckBuffer() too often. This has the side
   // effect of randomly growing the buffer in the middle of multi-instruction
   // sequences.
-  // MacroAssembler::LoadConstantPoolPointerRegister() includes a relocation
-  // and multiple instructions. We cannot grow the buffer until the
-  // relocation and all of the instructions are written.
   //
   // This function allows outside callers to check and grow the buffer
   void EnsureSpaceFor(int space_needed);
@@ -1273,17 +1293,7 @@ class Assembler : public AssemblerBase {
   // Generate the constant pool for the generated code.
   void PopulateConstantPool(ConstantPoolArray* constant_pool);
 
-  static void RelocateInternalReference(
-      Address pc, intptr_t delta, Address code_start, RelocInfo::Mode rmode,
-      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
-
-  void AddBoundInternalReference(int position) {
-    internal_reference_positions_.push_back(position);
-  }
-
-  void AddBoundInternalReferenceLoad(int position) {
-    internal_reference_load_positions_.push_back(position);
-  }
+  void EmitRelocations();
 
  protected:
   // Relocation for a type-recording IC has the AST id added to it.  This
@@ -1301,7 +1311,7 @@ class Assembler : public AssemblerBase {
 
   // Record reloc info for current pc_
   void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
-  void RecordRelocInfo(const RelocInfo& rinfo);
+  void RecordRelocInfo(const DeferredRelocInfo& rinfo);
 
   // Block the emission of the trampoline pool before pc_offset.
   void BlockTrampolinePoolBefore(int pc_offset) {
@@ -1340,12 +1350,7 @@ class Assembler : public AssemblerBase {
   // Each relocation is encoded as a variable size value
   static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
   RelocInfoWriter reloc_info_writer;
-
-  // Internal reference positions, required for (potential) patching in
-  // GrowBuffer(); contains only those internal references whose labels
-  // are already bound.
-  std::deque<int> internal_reference_positions_;
-  std::deque<int> internal_reference_load_positions_;
+  std::vector<DeferredRelocInfo> relocations_;
 
   // The bound position, before this we cannot do instruction elimination.
   int last_bound_pos_;
index 56b386cf6c536ffb500114ecd26910e0622862ad..bbb3688292f55668e34dca226713538b979dc7c5 100644 (file)
@@ -125,6 +125,7 @@ void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
     __ Assert(eq, kUnexpectedInitialMapForArrayFunction);
   }
 
+  __ mr(r6, r4);
   // Run the native code for the Array function called as a normal function.
   // tail call a stub
   __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
@@ -921,7 +922,9 @@ static void CallCompileOptimized(MacroAssembler* masm, bool concurrent) {
   // Push function as parameter to the runtime call.
   __ Push(r4, r4);
   // Whether to compile in a background thread.
-  __ Push(masm->isolate()->factory()->ToBoolean(concurrent));
+  __ LoadRoot(
+      r0, concurrent ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex);
+  __ push(r0);
 
   __ CallRuntime(Runtime::kCompileOptimized, 2);
   // Restore receiver.
index d88077aefe1a9ddfd3798904b312747aaf9fd119..635a7fc9e6b0e067e348e94d2617bc68cf31b4cd 100644 (file)
@@ -995,6 +995,60 @@ void CEntryStub::GenerateAheadOfTime(Isolate* isolate) {
 }
 
 
+static void ThrowPendingException(MacroAssembler* masm) {
+  Isolate* isolate = masm->isolate();
+
+  ExternalReference pending_handler_context_address(
+      Isolate::kPendingHandlerContextAddress, isolate);
+  ExternalReference pending_handler_code_address(
+      Isolate::kPendingHandlerCodeAddress, isolate);
+  ExternalReference pending_handler_offset_address(
+      Isolate::kPendingHandlerOffsetAddress, isolate);
+  ExternalReference pending_handler_fp_address(
+      Isolate::kPendingHandlerFPAddress, isolate);
+  ExternalReference pending_handler_sp_address(
+      Isolate::kPendingHandlerSPAddress, isolate);
+
+  // Ask the runtime for help to determine the handler. This will set r3 to
+  // contain the current pending exception, don't clobber it.
+  ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate);
+  {
+    FrameScope scope(masm, StackFrame::MANUAL);
+    __ PrepareCallCFunction(3, 0, r3);
+    __ li(r3, Operand::Zero());
+    __ li(r4, Operand::Zero());
+    __ mov(r5, Operand(ExternalReference::isolate_address(isolate)));
+    __ CallCFunction(find_handler, 3);
+  }
+
+  // Retrieve the handler context, SP and FP.
+  __ mov(cp, Operand(pending_handler_context_address));
+  __ LoadP(cp, MemOperand(cp));
+  __ mov(sp, Operand(pending_handler_sp_address));
+  __ LoadP(sp, MemOperand(sp));
+  __ mov(fp, Operand(pending_handler_fp_address));
+  __ LoadP(fp, MemOperand(fp));
+
+  // If the handler is a JS frame, restore the context to the frame.
+  // (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp
+  // or cp.
+  Label skip;
+  __ cmpi(cp, Operand::Zero());
+  __ beq(&skip);
+  __ StoreP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
+  __ bind(&skip);
+
+  // Compute the handler entry address and jump to it.
+  __ mov(r4, Operand(pending_handler_code_address));
+  __ LoadP(r4, MemOperand(r4));
+  __ mov(r5, Operand(pending_handler_offset_address));
+  __ LoadP(r5, MemOperand(r5));
+  __ addi(r4, r4, Operand(Code::kHeaderSize - kHeapObjectTag));  // Code start
+  __ add(ip, r4, r5);
+  __ Jump(ip);
+}
+
+
 void CEntryStub::Generate(MacroAssembler* masm) {
   // Called from JavaScript; parameters are on stack as if calling JS function.
   // r3: number of arguments including receiver
@@ -1070,11 +1124,22 @@ void CEntryStub::Generate(MacroAssembler* masm) {
   // know where the return address is. The CEntryStub is unmovable, so
   // we can store the address on the stack to be able to find it again and
   // we never have to restore it, because it will not change.
-  Label after_call;
-  __ mov_label_addr(r0, &after_call);
-  __ StoreP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize));
-  __ Call(target);
-  __ bind(&after_call);
+  // Compute the return address in lr to return to after the jump below. Pc is
+  // already at '+ 8' from the current instruction but return is after three
+  // instructions so add another 4 to pc to get the return address.
+  {
+    Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm);
+    Label here;
+    __ b(&here, SetLK);
+    __ bind(&here);
+    __ mflr(r8);
+
+    // Constant used below is dependent on size of Call() macro instructions
+    __ addi(r0, r8, Operand(20));
+
+    __ StoreP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize));
+    __ Call(target);
+  }
 
 #if !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
   // If return value is on the stack, pop it to registers.
@@ -1099,13 +1164,13 @@ void CEntryStub::Generate(MacroAssembler* masm) {
   __ CompareRoot(r3, Heap::kExceptionRootIndex);
   __ beq(&exception_returned);
 
-  ExternalReference pending_exception_address(Isolate::kPendingExceptionAddress,
-                                              isolate());
-
   // Check that there is no pending exception, otherwise we
   // should have returned the exception sentinel.
   if (FLAG_debug_code) {
     Label okay;
+    ExternalReference pending_exception_address(
+        Isolate::kPendingExceptionAddress, isolate());
+
     __ mov(r5, Operand(pending_exception_address));
     __ LoadP(r5, MemOperand(r5));
     __ CompareRoot(r5, Heap::kTheHoleValueRootIndex);
@@ -1126,25 +1191,7 @@ void CEntryStub::Generate(MacroAssembler* masm) {
   // Handling of exception.
   __ bind(&exception_returned);
 
-  // Retrieve the pending exception.
-  __ mov(r5, Operand(pending_exception_address));
-  __ LoadP(r3, MemOperand(r5));
-
-  // Clear the pending exception.
-  __ LoadRoot(r6, Heap::kTheHoleValueRootIndex);
-  __ StoreP(r6, MemOperand(r5));
-
-  // Special handling of termination exceptions which are uncatchable
-  // by javascript code.
-  Label throw_termination_exception;
-  __ CompareRoot(r3, Heap::kTerminationExceptionRootIndex);
-  __ beq(&throw_termination_exception);
-
-  // Handle normal exception.
-  __ Throw(r3);
-
-  __ bind(&throw_termination_exception);
-  __ ThrowUncatchable(r3);
+  ThrowPendingException(masm);
 }
 
 
@@ -2364,18 +2411,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
   __ cmp(r3, r4);
   __ beq(&runtime);
 
-  __ StoreP(r4, MemOperand(r5, 0));  // Clear pending exception.
-
-  // Check if the exception is a termination. If so, throw as uncatchable.
-  __ CompareRoot(r3, Heap::kTerminationExceptionRootIndex);
-
-  Label termination_exception;
-  __ beq(&termination_exception);
-
-  __ Throw(r3);
-
-  __ bind(&termination_exception);
-  __ ThrowUncatchable(r3);
+  // For exception, throw the exception again.
+  __ EnterExitFrame(false);
+  ThrowPendingException(masm);
 
   __ bind(&failure);
   // For failure and exception return null.
@@ -2843,6 +2881,7 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) {
   __ bne(&miss);
 
   __ mr(r5, r7);
+  __ mr(r6, r4);
   ArrayConstructorStub stub(masm->isolate(), arg_count());
   __ TailCallStub(&stub);
 
@@ -4822,6 +4861,7 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) {
   //  -- r3 : argc (only if argument_count() == ANY)
   //  -- r4 : constructor
   //  -- r5 : AllocationSite or undefined
+  //  -- r6 : original constructor
   //  -- sp[0] : return address
   //  -- sp[4] : last argument
   // -----------------------------------
@@ -4842,6 +4882,10 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) {
     __ AssertUndefinedOrAllocationSite(r5, r7);
   }
 
+  Label subclassing;
+  __ cmp(r6, r4);
+  __ bne(&subclassing);
+
   Label no_info;
   // Get the elements kind and case on that.
   __ CompareRoot(r5, Heap::kUndefinedValueRootIndex);
@@ -4855,6 +4899,27 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) {
 
   __ bind(&no_info);
   GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES);
+
+  __ bind(&subclassing);
+  __ push(r4);
+  __ push(r6);
+
+  // Adjust argc.
+  switch (argument_count()) {
+    case ANY:
+    case MORE_THAN_ONE:
+      __ addi(r3, r3, Operand(2));
+      break;
+    case NONE:
+      __ li(r3, Operand(2));
+      break;
+    case ONE:
+      __ li(r3, Operand(3));
+      break;
+  }
+
+  __ JumpToExternalReference(
+      ExternalReference(Runtime::kArrayConstructorWithSubclassing, isolate()));
 }
 
 
@@ -5017,7 +5082,6 @@ static void CallApiFunctionAndReturn(MacroAssembler* masm,
   }
 
   Label promote_scheduled_exception;
-  Label exception_handled;
   Label delete_allocated_handles;
   Label leave_exit_frame;
   Label return_value_loaded;
@@ -5039,15 +5103,8 @@ static void CallApiFunctionAndReturn(MacroAssembler* masm,
   __ cmp(r15, r0);
   __ bne(&delete_allocated_handles);
 
-  // Check if the function scheduled an exception.
+  // Leave the API exit frame.
   __ bind(&leave_exit_frame);
-  __ LoadRoot(r14, Heap::kTheHoleValueRootIndex);
-  __ mov(r15, Operand(ExternalReference::scheduled_exception_address(isolate)));
-  __ LoadP(r15, MemOperand(r15));
-  __ cmp(r14, r15);
-  __ bne(&promote_scheduled_exception);
-  __ bind(&exception_handled);
-
   bool restore_context = context_restore_operand != NULL;
   if (restore_context) {
     __ LoadP(cp, *context_restore_operand);
@@ -5059,15 +5116,19 @@ static void CallApiFunctionAndReturn(MacroAssembler* masm,
     __ mov(r14, Operand(stack_space));
   }
   __ LeaveExitFrame(false, r14, !restore_context, stack_space_operand != NULL);
+
+  // Check if the function scheduled an exception.
+  __ LoadRoot(r14, Heap::kTheHoleValueRootIndex);
+  __ mov(r15, Operand(ExternalReference::scheduled_exception_address(isolate)));
+  __ LoadP(r15, MemOperand(r15));
+  __ cmp(r14, r15);
+  __ bne(&promote_scheduled_exception);
+
   __ blr();
 
+  // Re-throw by promoting a scheduled exception.
   __ bind(&promote_scheduled_exception);
-  {
-    FrameScope frame(masm, StackFrame::INTERNAL);
-    __ CallExternalReference(
-        ExternalReference(Runtime::kPromoteScheduledException, isolate), 0);
-  }
-  __ jmp(&exception_handled);
+  __ TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1);
 
   // HandleScope limit has changed. Delete allocated extensions.
   __ bind(&delete_allocated_handles);
index 93d32c2bc6ce81edf0aaf6ff152b2b8eca3cd8b9..c0398aebed5480af97955f9d0525bbf85172230c 100644 (file)
@@ -646,9 +646,9 @@ void Code::GetCodeAgeAndParity(Isolate* isolate, byte* sequence, Age* age,
     *age = kNoAgeCodeAge;
     *parity = NO_MARKING_PARITY;
   } else {
-    ConstantPoolArray* constant_pool = NULL;
-    Address target_address = Assembler::target_address_at(
-        sequence + kCodeAgingTargetDelta, constant_pool);
+    Code* code = NULL;
+    Address target_address =
+        Assembler::target_address_at(sequence + kCodeAgingTargetDelta, code);
     Code* stub = GetCodeFromTargetAddress(target_address);
     GetCodeAgeAndParity(stub, age, parity);
   }
index 586492835d4f1e8cfae66fb452760e4a313feb62..f4ad9400304f29f6ce1bfdf86f1a88b47d414505 100644 (file)
@@ -1482,7 +1482,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
         __ mov(VectorLoadICDescriptor::SlotRegister(),
                Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
       }
-      CallLoadIC(CONTEXTUAL);
+      CallGlobalLoadIC(var->name());
       context()->Plug(r3);
       break;
     }
@@ -2566,6 +2566,16 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
     }
     __ push(scratch);
     EmitPropertyKey(property, lit->GetIdForProperty(i));
+
+    // The static prototype property is read only. We handle the non computed
+    // property name case in the parser. Since this is the only case where we
+    // need to check for an own read only property we special case this so we do
+    // not need to do this for every property.
+    if (property->is_static() && property->is_computed_name()) {
+      __ CallRuntime(Runtime::kThrowIfStaticPrototype, 1);
+      __ push(r3);
+    }
+
     VisitForStackValue(value);
     EmitSetHomeObjectIfNeeded(value, 2);
 
@@ -2709,25 +2719,6 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) {
     __ LoadP(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand());
     CallStoreIC();
 
-  } else if (op == Token::INIT_CONST_LEGACY) {
-    // Const initializers need a write barrier.
-    DCHECK(!var->IsParameter());  // No const parameters.
-    if (var->IsLookupSlot()) {
-      __ push(r3);
-      __ mov(r3, Operand(var->name()));
-      __ Push(cp, r3);  // Context and name.
-      __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3);
-    } else {
-      DCHECK(var->IsStackAllocated() || var->IsContextSlot());
-      Label skip;
-      MemOperand location = VarOperand(var, r4);
-      __ LoadP(r5, location);
-      __ CompareRoot(r5, Heap::kTheHoleValueRootIndex);
-      __ bne(&skip);
-      EmitStoreToStackLocalOrContextSlot(var, location);
-      __ bind(&skip);
-    }
-
   } else if (var->mode() == LET && op != Token::INIT_LET) {
     // Non-initializing assignment to let variable needs a write barrier.
     DCHECK(!var->IsLookupSlot());
@@ -2744,6 +2735,21 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) {
     __ bind(&assign);
     EmitStoreToStackLocalOrContextSlot(var, location);
 
+  } else if (var->mode() == CONST && op != Token::INIT_CONST) {
+    // Assignment to const variable needs a write barrier.
+    DCHECK(!var->IsLookupSlot());
+    DCHECK(var->IsStackAllocated() || var->IsContextSlot());
+    Label const_error;
+    MemOperand location = VarOperand(var, r4);
+    __ LoadP(r6, location);
+    __ CompareRoot(r6, Heap::kTheHoleValueRootIndex);
+    __ bne(&const_error);
+    __ mov(r6, Operand(var->name()));
+    __ push(r6);
+    __ CallRuntime(Runtime::kThrowReferenceError, 1);
+    __ bind(&const_error);
+    __ CallRuntime(Runtime::kThrowConstAssignError, 0);
+
   } else if (!var->is_const_mode() || op == Token::INIT_CONST) {
     if (var->IsLookupSlot()) {
       // Assignment to var.
@@ -2765,8 +2771,32 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) {
       }
       EmitStoreToStackLocalOrContextSlot(var, location);
     }
-  } else if (IsSignallingAssignmentToConst(var, op, language_mode())) {
-    __ CallRuntime(Runtime::kThrowConstAssignError, 0);
+  } else if (op == Token::INIT_CONST_LEGACY) {
+    // Const initializers need a write barrier.
+    DCHECK(var->mode() == CONST_LEGACY);
+    DCHECK(!var->IsParameter());  // No const parameters.
+    if (var->IsLookupSlot()) {
+      __ push(r3);
+      __ mov(r3, Operand(var->name()));
+      __ Push(cp, r3);  // Context and name.
+      __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3);
+    } else {
+      DCHECK(var->IsStackAllocated() || var->IsContextSlot());
+      Label skip;
+      MemOperand location = VarOperand(var, r4);
+      __ LoadP(r5, location);
+      __ CompareRoot(r5, Heap::kTheHoleValueRootIndex);
+      __ bne(&skip);
+      EmitStoreToStackLocalOrContextSlot(var, location);
+      __ bind(&skip);
+    }
+
+  } else {
+    DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT_CONST_LEGACY);
+    if (is_strict(language_mode())) {
+      __ CallRuntime(Runtime::kThrowConstAssignError, 0);
+    }
+    // Silently ignore store in sloppy mode.
   }
 }
 
@@ -2893,7 +2923,8 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
     }
     // Push undefined as receiver. This is patched in the method prologue if it
     // is a sloppy mode method.
-    __ Push(isolate()->factory()->undefined_value());
+    __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
+    __ push(r0);
   } else {
     // Load the function from the receiver.
     DCHECK(callee->IsProperty());
@@ -2902,8 +2933,8 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
     EmitNamedPropertyLoad(callee->AsProperty());
     PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
     // Push the target function under the receiver.
-    __ LoadP(ip, MemOperand(sp, 0));
-    __ push(ip);
+    __ LoadP(r0, MemOperand(sp, 0));
+    __ push(r0);
     __ StoreP(r3, MemOperand(sp, kPointerSize));
   }
 
@@ -4218,6 +4249,8 @@ void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
   }
 
   __ bind(&args_set_up);
+  __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
+
   CallConstructStub stub(isolate(), SUPER_CONSTRUCTOR_CALL);
   __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL);
 
index e7b2ac55115ac7687dfa97e249b381db0d0f3f43..706ab20520a06355ef307f8b6a0996137d52b3fb 100644 (file)
@@ -337,49 +337,37 @@ bool LCodeGen::GenerateJumpTable() {
 
       if (table_entry->needs_frame) {
         DCHECK(!info()->saves_caller_doubles());
-        if (needs_frame.is_bound()) {
-          __ b(&needs_frame);
-        } else {
-          __ bind(&needs_frame);
-          Comment(";;; call deopt with frame");
-          // This variant of deopt can only be used with stubs. Since we don't
-          // have a function pointer to install in the stack frame that we're
-          // building, install a special marker there instead.
-          DCHECK(info()->IsStub());
-          __ LoadSmiLiteral(ip, Smi::FromInt(StackFrame::STUB));
-          __ PushFixedFrame(ip);
-          __ addi(fp, sp,
-                  Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
-          __ bind(&call_deopt_entry);
-          // Add the base address to the offset previously loaded in
-          // entry_offset.
-          __ mov(ip, Operand(ExternalReference::ForDeoptEntry(base)));
-          __ add(ip, entry_offset, ip);
-          __ Call(ip);
-        }
+        Comment(";;; call deopt with frame");
+        __ PushFixedFrame();
+        __ b(&needs_frame, SetLK);
       } else {
-        // The last entry can fall through into `call_deopt_entry`, avoiding a
-        // branch.
-        bool need_branch = ((i + 1) != length) || call_deopt_entry.is_bound();
-
-        if (need_branch) __ b(&call_deopt_entry);
+        __ b(&call_deopt_entry, SetLK);
       }
     }
 
-    if (!call_deopt_entry.is_bound()) {
-      Comment(";;; call deopt");
-      __ bind(&call_deopt_entry);
+    if (needs_frame.is_linked()) {
+      __ bind(&needs_frame);
+      // This variant of deopt can only be used with stubs. Since we don't
+      // have a function pointer to install in the stack frame that we're
+      // building, install a special marker there instead.
+      DCHECK(info()->IsStub());
+      __ LoadSmiLiteral(ip, Smi::FromInt(StackFrame::STUB));
+      __ push(ip);
+      __ addi(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
+    }
 
-      if (info()->saves_caller_doubles()) {
-        DCHECK(info()->IsStub());
-        RestoreCallerDoubles();
-      }
+    Comment(";;; call deopt");
+    __ bind(&call_deopt_entry);
 
-      // Add the base address to the offset previously loaded in entry_offset.
-      __ mov(ip, Operand(ExternalReference::ForDeoptEntry(base)));
-      __ add(ip, entry_offset, ip);
-      __ Call(ip);
+    if (info()->saves_caller_doubles()) {
+      DCHECK(info()->IsStub());
+      RestoreCallerDoubles();
     }
+
+    // Add the base address to the offset previously loaded in entry_offset.
+    __ mov(ip, Operand(ExternalReference::ForDeoptEntry(base)));
+    __ add(ip, entry_offset, ip);
+    __ Jump(ip);
   }
 
   // The deoptimization jump table is the last part of the instruction
index 7a6228be88295c6c484df7d94243af12f87b0254..54e40f767129e937b20a0423e65f1af4984eee39 100644 (file)
@@ -1089,20 +1089,16 @@ void MacroAssembler::DebugBreak() {
 void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
                                     int handler_index) {
   // Adjust this code if not the case.
-  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
+  STATIC_ASSERT(StackHandlerConstants::kSize == 3 * kPointerSize);
   STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
-  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
-  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
-  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
-  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
+  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize);
+  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 2 * kPointerSize);
 
-  // For the JSEntry handler, we must preserve r1-r7, r0,r8-r15 are available.
+  // For the JSEntry handler, we must preserve r1-r7, r0,r8-r12 are available.
   // We want the stack to look like
   // sp -> NextOffset
-  //       CodeObject
   //       state
   //       context
-  //       frame pointer
 
   // Link the current handler as the next handler.
   mov(r8, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
@@ -1111,22 +1107,15 @@ void MacroAssembler::PushTryHandler(StackHandler::Kind kind,
   // Set this new handler as the current one.
   StoreP(sp, MemOperand(r8));
 
-  if (kind == StackHandler::JS_ENTRY) {
-    li(r8, Operand::Zero());  // NULL frame pointer.
-    StoreP(r8, MemOperand(sp, StackHandlerConstants::kFPOffset));
-    LoadSmiLiteral(r8, Smi::FromInt(0));  // Indicates no context.
-    StoreP(r8, MemOperand(sp, StackHandlerConstants::kContextOffset));
-  } else {
-    // still not sure if fp is right
-    StoreP(fp, MemOperand(sp, StackHandlerConstants::kFPOffset));
-    StoreP(cp, MemOperand(sp, StackHandlerConstants::kContextOffset));
-  }
   unsigned state = StackHandler::IndexField::encode(handler_index) |
                    StackHandler::KindField::encode(kind);
   LoadIntLiteral(r8, state);
+
+  if (kind == StackHandler::JS_ENTRY) {
+    LoadSmiLiteral(cp, Smi::FromInt(0));  // Indicates no context.
+  }
   StoreP(r8, MemOperand(sp, StackHandlerConstants::kStateOffset));
-  mov(r8, Operand(CodeObject()));
-  StoreP(r8, MemOperand(sp, StackHandlerConstants::kCodeOffset));
+  StoreP(cp, MemOperand(sp, StackHandlerConstants::kContextOffset));
 }
 
 
@@ -1139,107 +1128,6 @@ void MacroAssembler::PopTryHandler() {
 }
 
 
-// PPC - make use of ip as a temporary register
-void MacroAssembler::JumpToHandlerEntry() {
-// Compute the handler entry address and jump to it.  The handler table is
-// a fixed array of (smi-tagged) code offsets.
-// r3 = exception, r4 = code object, r5 = state.
-  LoadP(r6, FieldMemOperand(r4, Code::kHandlerTableOffset));  // Handler table.
-  addi(r4, r4, Operand(Code::kHeaderSize - kHeapObjectTag));  // Code start.
-  addi(r6, r6, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
-  srwi(r5, r5, Operand(StackHandler::kKindWidth));  // Handler index.
-  slwi(ip, r5, Operand(kPointerSizeLog2));
-  add(ip, r6, ip);
-  LoadP(r5, MemOperand(ip));  // Smi-tagged offset.
-  SmiUntag(ip, r5);
-  add(ip, r4, ip);
-  Jump(ip);
-}
-
-
-void MacroAssembler::Throw(Register value) {
-  // Adjust this code if not the case.
-  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
-  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
-  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
-  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
-  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
-  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
-  Label skip;
-
-  // The exception is expected in r3.
-  if (!value.is(r3)) {
-    mr(r3, value);
-  }
-  // Drop the stack pointer to the top of the top handler.
-  mov(r6, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
-  LoadP(sp, MemOperand(r6));
-  // Restore the next handler.
-  pop(r5);
-  StoreP(r5, MemOperand(r6));
-
-  // Get the code object (r4) and state (r5).  Restore the context and frame
-  // pointer.
-  pop(r4);
-  pop(r5);
-  pop(cp);
-  pop(fp);
-
-  // If the handler is a JS frame, restore the context to the frame.
-  // (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp
-  // or cp.
-  cmpi(cp, Operand::Zero());
-  beq(&skip);
-  StoreP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
-  bind(&skip);
-
-  JumpToHandlerEntry();
-}
-
-
-void MacroAssembler::ThrowUncatchable(Register value) {
-  // Adjust this code if not the case.
-  STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
-  STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize);
-  STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize);
-  STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize);
-  STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize);
-  STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize);
-
-  // The exception is expected in r3.
-  if (!value.is(r3)) {
-    mr(r3, value);
-  }
-  // Drop the stack pointer to the top of the top stack handler.
-  mov(r6, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
-  LoadP(sp, MemOperand(r6));
-
-  // Unwind the handlers until the ENTRY handler is found.
-  Label fetch_next, check_kind;
-  b(&check_kind);
-  bind(&fetch_next);
-  LoadP(sp, MemOperand(sp, StackHandlerConstants::kNextOffset));
-
-  bind(&check_kind);
-  STATIC_ASSERT(StackHandler::JS_ENTRY == 0);
-  LoadP(r5, MemOperand(sp, StackHandlerConstants::kStateOffset));
-  andi(r0, r5, Operand(StackHandler::KindField::kMask));
-  bne(&fetch_next, cr0);
-
-  // Set the top handler address to next handler past the top ENTRY handler.
-  pop(r5);
-  StoreP(r5, MemOperand(r6));
-  // Get the code object (r4) and state (r5).  Clear the context and frame
-  // pointer (0 was saved in the handler).
-  pop(r4);
-  pop(r5);
-  pop(cp);
-  pop(fp);
-
-  JumpToHandlerEntry();
-}
-
-
 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
                                             Register scratch, Label* miss) {
   Label same_contexts;
@@ -3961,6 +3849,46 @@ void MacroAssembler::MovInt64ComponentsToDouble(DoubleRegister dst,
 #endif
 
 
+void MacroAssembler::InsertDoubleLow(DoubleRegister dst, Register src,
+                                     Register scratch) {
+#if V8_TARGET_ARCH_PPC64
+  if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
+    mffprd(scratch, dst);
+    rldimi(scratch, src, 0, 32);
+    mtfprd(dst, scratch);
+    return;
+  }
+#endif
+
+  subi(sp, sp, Operand(kDoubleSize));
+  stfd(dst, MemOperand(sp));
+  stw(src, MemOperand(sp, Register::kMantissaOffset));
+  nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
+  lfd(dst, MemOperand(sp));
+  addi(sp, sp, Operand(kDoubleSize));
+}
+
+
+void MacroAssembler::InsertDoubleHigh(DoubleRegister dst, Register src,
+                                      Register scratch) {
+#if V8_TARGET_ARCH_PPC64
+  if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
+    mffprd(scratch, dst);
+    rldimi(scratch, src, 32, 0);
+    mtfprd(dst, scratch);
+    return;
+  }
+#endif
+
+  subi(sp, sp, Operand(kDoubleSize));
+  stfd(dst, MemOperand(sp));
+  stw(src, MemOperand(sp, Register::kExponentOffset));
+  nop(GROUP_ENDING_NOP);  // LHS/RAW optimization
+  lfd(dst, MemOperand(sp));
+  addi(sp, sp, Operand(kDoubleSize));
+}
+
+
 void MacroAssembler::MovDoubleLowToInt(Register dst, DoubleRegister src) {
 #if V8_TARGET_ARCH_PPC64
   if (CpuFeatures::IsSupported(FPR_GPR_MOV)) {
index b9bb7f582576b3914c20ef2815985e7c350ef25c..fc569706ecb2ddf486da1dbff10556fdd2389b22 100644 (file)
@@ -377,8 +377,9 @@ class MacroAssembler : public Assembler {
   void Prologue(bool code_pre_aging, int prologue_offset = 0);
 
   // Enter exit frame.
-  // stack_space - extra stack space, used for alignment before call to C.
-  void EnterExitFrame(bool save_doubles, int stack_space = 0);
+  // stack_space - extra stack space, used for parameters before call to C.
+  // At least one slot (for the return address) should be provided.
+  void EnterExitFrame(bool save_doubles, int stack_space = 1);
 
   // Leave the current exit frame. Expects the return value in r0.
   // Expect the number of values, pushed prior to the exit frame, to
@@ -462,6 +463,8 @@ class MacroAssembler : public Assembler {
   void MovInt64ComponentsToDouble(DoubleRegister dst, Register src_hi,
                                   Register src_lo, Register scratch);
 #endif
+  void InsertDoubleLow(DoubleRegister dst, Register src, Register scratch);
+  void InsertDoubleHigh(DoubleRegister dst, Register src, Register scratch);
   void MovDoubleLowToInt(Register dst, DoubleRegister src);
   void MovDoubleHighToInt(Register dst, DoubleRegister src);
   void MovDoubleToInt64(
@@ -548,13 +551,6 @@ class MacroAssembler : public Assembler {
   // Must preserve the result register.
   void PopTryHandler();
 
-  // Passes thrown value to the handler of top of the try handler chain.
-  void Throw(Register value);
-
-  // Propagates an uncatchable exception to the top of the current JS stack's
-  // handler chain.
-  void ThrowUncatchable(Register value);
-
   // ---------------------------------------------------------------------------
   // Inline caching support
 
@@ -1484,10 +1480,6 @@ class MacroAssembler : public Assembler {
   inline void GetMarkBits(Register addr_reg, Register bitmap_reg,
                           Register mask_reg);
 
-  // Helper for throwing exceptions.  Compute a handler address and jump to
-  // it.  See the implementation for register usage.
-  void JumpToHandlerEntry();
-
   static const RegList kSafepointSavedRegisters;
   static const int kNumSafepointSavedRegisters;
 
index e681d7d31d5ba2c1cf381a5babe5c2df8031ed47..489d6f97e04ef798b509fe32ab1f14d5906dc084 100644 (file)
   'test-api/Threading2': [SKIP],
   'test-api/ExternalArrays': [SKIP],
 
-  # isses to be investigated
+  # issues to be investigated based on latest uplevel
   'test-run-machops/RunWord64EqualInBranchP': [SKIP],
+  'test-deoptimization/DeoptimizeCompare': [SKIP],
+
+  # will not pass until we agree/implement changes to serializce.cc
+  'test-serialize/SerializeInternalReference': [SKIP],
 
 }],  # 'arch == ppc64 and simulator_run == True'
 ]
index 2bed45d9f874328e3470723ee31e83f976fa0744..ac1024fdeeb45ba006ac65acef14b87efd5ae097 100644 (file)
   'regress/regress-1132': [SKIP],
   'asm/embenchen/box2d': [SKIP],
 
-  # issues to be investigate4d
+  # issues to be investigated based on latest uplevel
   'es6/collections': [SKIP],
+  'debug-references': [SKIP],
 }],  # 'arch == ppc and simulator_run == True'
 ]