| Index: src/ppc/assembler-ppc.h | 
| diff --git a/src/ppc/assembler-ppc.h b/src/ppc/assembler-ppc.h | 
| index bcc2d8f6b627c6157f233187d81d56fd7550cdb5..fb56852bb5b5c254d82662f910f0b1c5265f90dc 100644 | 
| --- a/src/ppc/assembler-ppc.h | 
| +++ b/src/ppc/assembler-ppc.h | 
| @@ -108,7 +108,8 @@ struct Register { | 
| static const int kAllocatableLowRangeBegin = 3; | 
| static const int kAllocatableLowRangeEnd = 10; | 
| static const int kAllocatableHighRangeBegin = 14; | 
| -  static const int kAllocatableHighRangeEnd = 28; | 
| +  static const int kAllocatableHighRangeEnd = | 
| +      FLAG_enable_embedded_constant_pool ? 27 : 28; | 
| static const int kAllocatableContext = 30; | 
|  | 
| static const int kNumAllocatableLow = | 
| @@ -177,6 +178,10 @@ struct Register { | 
| "r28", | 
| "cp", | 
| }; | 
| +    if (FLAG_enable_embedded_constant_pool && | 
| +        (index == kMaxNumAllocatableRegisters - 2)) { | 
| +      return names[index + 1]; | 
| +    } | 
| return names[index]; | 
| } | 
|  | 
| @@ -184,7 +189,7 @@ struct Register { | 
| 1 << 3 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 8 | 1 << 9 | 1 << 10 | | 
| 1 << 14 | 1 << 15 | 1 << 16 | 1 << 17 | 1 << 18 | 1 << 19 | 1 << 20 | | 
| 1 << 21 | 1 << 22 | 1 << 23 | 1 << 24 | 1 << 25 | 1 << 26 | 1 << 27 | | 
| -      1 << 28 | 1 << 30; | 
| +      (FLAG_enable_embedded_constant_pool ? 0 : 1 << 28) | 1 << 30; | 
|  | 
| static Register from_code(int code) { | 
| Register r = {code}; | 
| @@ -242,7 +247,7 @@ const int kRegister_r24_Code = 24; | 
| const int kRegister_r25_Code = 25; | 
| const int kRegister_r26_Code = 26; | 
| const int kRegister_r27_Code = 27; | 
| -const int kRegister_r28_Code = 28; | 
| +const int kRegister_r28_Code = 28;  // constant pool pointer | 
| const int kRegister_r29_Code = 29;  // roots array pointer | 
| const int kRegister_r30_Code = 30;  // context pointer | 
| const int kRegister_fp_Code = 31;   // frame pointer | 
| @@ -286,6 +291,7 @@ const Register fp = {kRegister_fp_Code}; | 
| // Give alias names to registers | 
| const Register cp = {kRegister_r30_Code};  // JavaScript context pointer | 
| const Register kRootRegister = {kRegister_r29_Code};  // Roots array pointer. | 
| +const Register kConstantPoolRegister = {kRegister_r28_Code};  // Constant pool | 
|  | 
| // Double word FP register. | 
| struct DoubleRegister { | 
| @@ -595,20 +601,36 @@ class Assembler : public AssemblerBase { | 
| // The high 8 bits are set to zero. | 
| void label_at_put(Label* L, int at_offset); | 
|  | 
| +  INLINE(static bool IsConstantPoolLoadStart( | 
| +      Address pc, ConstantPoolEntry::Access* access = nullptr)); | 
| +  INLINE(static bool IsConstantPoolLoadEnd( | 
| +      Address pc, ConstantPoolEntry::Access* access = nullptr)); | 
| +  INLINE(static int GetConstantPoolOffset(Address pc, | 
| +                                          ConstantPoolEntry::Access access, | 
| +                                          ConstantPoolEntry::Type type)); | 
| +  INLINE(void PatchConstantPoolAccessInstruction( | 
| +      int pc_offset, int offset, ConstantPoolEntry::Access access, | 
| +      ConstantPoolEntry::Type type)); | 
| + | 
| +  // Return the address in the constant pool of the code target address used by | 
| +  // the branch/call instruction at pc, or the object in a mov. | 
| +  INLINE(static Address target_constant_pool_address_at( | 
| +      Address pc, Address constant_pool, ConstantPoolEntry::Access access, | 
| +      ConstantPoolEntry::Type type)); | 
| + | 
| // Read/Modify the code target address in the branch/call instruction at pc. | 
| -  INLINE(static Address target_address_at(Address pc, | 
| -                                          ConstantPoolArray* constant_pool)); | 
| +  INLINE(static Address target_address_at(Address pc, Address constant_pool)); | 
| INLINE(static void set_target_address_at( | 
| -      Address pc, ConstantPoolArray* constant_pool, Address target, | 
| +      Address pc, Address constant_pool, Address target, | 
| ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)); | 
| INLINE(static Address target_address_at(Address pc, Code* code)) { | 
| -    ConstantPoolArray* constant_pool = NULL; | 
| +    Address constant_pool = code ? code->constant_pool() : NULL; | 
| return target_address_at(pc, constant_pool); | 
| } | 
| INLINE(static void set_target_address_at( | 
| Address pc, Code* code, Address target, | 
| ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)) { | 
| -    ConstantPoolArray* constant_pool = NULL; | 
| +    Address constant_pool = code ? code->constant_pool() : NULL; | 
| set_target_address_at(pc, constant_pool, target, icache_flush_mode); | 
| } | 
|  | 
| @@ -646,12 +668,21 @@ class Assembler : public AssemblerBase { | 
|  | 
| // Number of instructions to load an address via a mov sequence. | 
| #if V8_TARGET_ARCH_PPC64 | 
| -  static const int kMovInstructions = 5; | 
| +  static const int kMovInstructionsConstantPool = 1; | 
| +  static const int kMovInstructionsNoConstantPool = 5; | 
| +#if defined(V8_PPC_TAGGING_OPT) | 
| +  static const int kTaggedLoadInstructions = 1; | 
| +#else | 
| static const int kTaggedLoadInstructions = 2; | 
| +#endif | 
| #else | 
| -  static const int kMovInstructions = 2; | 
| +  static const int kMovInstructionsConstantPool = 1; | 
| +  static const int kMovInstructionsNoConstantPool = 2; | 
| static const int kTaggedLoadInstructions = 1; | 
| #endif | 
| +  static const int kMovInstructions = FLAG_enable_embedded_constant_pool | 
| +                                          ? kMovInstructionsConstantPool | 
| +                                          : kMovInstructionsNoConstantPool; | 
|  | 
| // Distance between the instruction referring to the address of the call | 
| // target and the return address. | 
| @@ -682,13 +713,15 @@ class Assembler : public AssemblerBase { | 
|  | 
| // This is the length of the BreakLocation::SetDebugBreakAtReturn() | 
| // code patch FIXED_SEQUENCE | 
| -  static const int kJSReturnSequenceInstructions = kMovInstructions + 3; | 
| +  static const int kJSReturnSequenceInstructions = | 
| +      kMovInstructionsNoConstantPool + 3; | 
| static const int kJSReturnSequenceLength = | 
| kJSReturnSequenceInstructions * kInstrSize; | 
|  | 
| // This is the length of the code sequence from SetDebugBreakAtSlot() | 
| // FIXED_SEQUENCE | 
| -  static const int kDebugBreakSlotInstructions = kMovInstructions + 2; | 
| +  static const int kDebugBreakSlotInstructions = | 
| +      kMovInstructionsNoConstantPool + 2; | 
| static const int kDebugBreakSlotLength = | 
| kDebugBreakSlotInstructions * kInstrSize; | 
|  | 
| @@ -1201,6 +1234,23 @@ class Assembler : public AssemblerBase { | 
| DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope); | 
| }; | 
|  | 
| +  // Class for scoping disabling constant pool entry merging | 
| +  class BlockConstantPoolEntrySharingScope { | 
| +   public: | 
| +    explicit BlockConstantPoolEntrySharingScope(Assembler* assem) | 
| +        : assem_(assem) { | 
| +      assem_->StartBlockConstantPoolEntrySharing(); | 
| +    } | 
| +    ~BlockConstantPoolEntrySharingScope() { | 
| +      assem_->EndBlockConstantPoolEntrySharing(); | 
| +    } | 
| + | 
| +   private: | 
| +    Assembler* assem_; | 
| + | 
| +    DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstantPoolEntrySharingScope); | 
| +  }; | 
| + | 
| // Debugging | 
|  | 
| // Mark address of the ExitJSFrame code. | 
| @@ -1237,8 +1287,8 @@ class Assembler : public AssemblerBase { | 
| // for inline tables, e.g., jump-tables. | 
| void db(uint8_t data); | 
| void dd(uint32_t data); | 
| -  void emit_ptr(intptr_t data); | 
| -  void emit_double(double data); | 
| +  void dq(uint64_t data); | 
| +  void dp(uintptr_t data); | 
|  | 
| PositionsRecorder* positions_recorder() { return &positions_recorder_; } | 
|  | 
| @@ -1284,6 +1334,19 @@ class Assembler : public AssemblerBase { | 
| void BlockTrampolinePoolFor(int instructions); | 
| void CheckTrampolinePool(); | 
|  | 
| +  // For mov.  Return the number of actual instructions required to | 
| +  // load the operand into a register.  This can be anywhere from | 
| +  // one (constant pool small section) to five instructions (full | 
| +  // 64-bit sequence). | 
| +  // | 
| +  // The value returned is only valid as long as no entries are added to the | 
| +  // constant pool between this call and the actual instruction being emitted. | 
| +  int instructions_required_for_mov(Register dst, const Operand& src) const; | 
| + | 
| +  // Decide between using the constant pool vs. a mov immediate sequence. | 
| +  bool use_constant_pool_for_mov(Register dst, const Operand& src, | 
| +                                 bool canOptimize) const; | 
| + | 
| // The code currently calls CheckBuffer() too often. This has the side | 
| // effect of randomly growing the buffer in the middle of multi-instruction | 
| // sequences. | 
| @@ -1291,11 +1354,16 @@ class Assembler : public AssemblerBase { | 
| // This function allows outside callers to check and grow the buffer | 
| void EnsureSpaceFor(int space_needed); | 
|  | 
| -  // Allocate a constant pool of the correct size for the generated code. | 
| -  Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate); | 
| +  int EmitConstantPool() { return constant_pool_builder_.Emit(this); } | 
|  | 
| -  // Generate the constant pool for the generated code. | 
| -  void PopulateConstantPool(ConstantPoolArray* constant_pool); | 
| +  bool ConstantPoolAccessIsInOverflow() const { | 
| +    return constant_pool_builder_.NextAccess(ConstantPoolEntry::INTPTR) == | 
| +           ConstantPoolEntry::OVERFLOWED; | 
| +  } | 
| + | 
| +  Label* ConstantPoolPosition() { | 
| +    return constant_pool_builder_.EmittedPosition(); | 
| +  } | 
|  | 
| void EmitRelocations(); | 
|  | 
| @@ -1315,7 +1383,16 @@ class Assembler : public AssemblerBase { | 
|  | 
| // Record reloc info for current pc_ | 
| void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); | 
| -  void RecordRelocInfo(const DeferredRelocInfo& rinfo); | 
| +  ConstantPoolEntry::Access ConstantPoolAddEntry(RelocInfo::Mode rmode, | 
| +                                                 intptr_t value) { | 
| +    bool sharing_ok = RelocInfo::IsNone(rmode) || | 
| +                      !(serializer_enabled() || rmode < RelocInfo::CELL || | 
| +                        is_constant_pool_entry_sharing_blocked()); | 
| +    return constant_pool_builder_.AddEntry(pc_offset(), value, sharing_ok); | 
| +  } | 
| +  ConstantPoolEntry::Access ConstantPoolAddEntry(double value) { | 
| +    return constant_pool_builder_.AddEntry(pc_offset(), value); | 
| +  } | 
|  | 
| // Block the emission of the trampoline pool before pc_offset. | 
| void BlockTrampolinePoolBefore(int pc_offset) { | 
| @@ -1329,6 +1406,16 @@ class Assembler : public AssemblerBase { | 
| return trampoline_pool_blocked_nesting_ > 0; | 
| } | 
|  | 
| +  void StartBlockConstantPoolEntrySharing() { | 
| +    constant_pool_entry_sharing_blocked_nesting_++; | 
| +  } | 
| +  void EndBlockConstantPoolEntrySharing() { | 
| +    constant_pool_entry_sharing_blocked_nesting_--; | 
| +  } | 
| +  bool is_constant_pool_entry_sharing_blocked() const { | 
| +    return constant_pool_entry_sharing_blocked_nesting_ > 0; | 
| +  } | 
| + | 
| bool has_exception() const { return internal_trampoline_exception_; } | 
|  | 
| bool is_trampoline_emitted() const { return trampoline_emitted_; } | 
| @@ -1350,6 +1437,9 @@ class Assembler : public AssemblerBase { | 
| int trampoline_pool_blocked_nesting_;  // Block emission if this is not zero. | 
| int no_trampoline_pool_before_;  // Block emission before this pc offset. | 
|  | 
| +  // Do not share constant pool entries. | 
| +  int constant_pool_entry_sharing_blocked_nesting_; | 
| + | 
| // Relocation info generation | 
| // Each relocation is encoded as a variable size value | 
| static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; | 
| @@ -1359,6 +1449,8 @@ class Assembler : public AssemblerBase { | 
| // The bound position, before this we cannot do instruction elimination. | 
| int last_bound_pos_; | 
|  | 
| +  ConstantPoolBuilder constant_pool_builder_; | 
| + | 
| // Code emission | 
| inline void CheckBuffer(); | 
| void GrowBuffer(int needed = 0); | 
|  |