| Index: src/ppc/code-stubs-ppc.cc
 | 
| diff --git a/src/ppc/code-stubs-ppc.cc b/src/ppc/code-stubs-ppc.cc
 | 
| index 2c65b44978dd7c7a8060b1164ac380392c0b6408..0226ffbf572e3710ee07e65fd40c86de0c540bc8 100644
 | 
| --- a/src/ppc/code-stubs-ppc.cc
 | 
| +++ b/src/ppc/code-stubs-ppc.cc
 | 
| @@ -157,7 +157,7 @@ void DoubleToIStub::Generate(MacroAssembler* masm) {
 | 
|  
 | 
|  // Test for overflow
 | 
|  #if V8_TARGET_ARCH_PPC64
 | 
| -    __ TestIfInt32(result_reg, scratch, r0);
 | 
| +    __ TestIfInt32(result_reg, r0);
 | 
|  #else
 | 
|      __ TestIfInt32(scratch, result_reg, r0);
 | 
|  #endif
 | 
| @@ -328,15 +328,20 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm, Label* slow,
 | 
|      // not (it's a NaN).  For <= and >= we need to load r0 with the failing
 | 
|      // value if it's a NaN.
 | 
|      if (cond != eq) {
 | 
| -      Label not_equal;
 | 
| -      __ bne(¬_equal);
 | 
| -      // All-zero means Infinity means equal.
 | 
| -      __ Ret();
 | 
| -      __ bind(¬_equal);
 | 
| -      if (cond == le) {
 | 
| -        __ li(r3, Operand(GREATER));  // NaN <= NaN should fail.
 | 
| +      if (CpuFeatures::IsSupported(ISELECT)) {
 | 
| +        __ li(r4, Operand((cond == le) ? GREATER : LESS));
 | 
| +        __ isel(eq, r3, r3, r4);
 | 
|        } else {
 | 
| -        __ li(r3, Operand(LESS));  // NaN >= NaN should fail.
 | 
| +        Label not_equal;
 | 
| +        __ bne(¬_equal);
 | 
| +        // All-zero means Infinity means equal.
 | 
| +        __ Ret();
 | 
| +        __ bind(¬_equal);
 | 
| +        if (cond == le) {
 | 
| +          __ li(r3, Operand(GREATER));  // NaN <= NaN should fail.
 | 
| +        } else {
 | 
| +          __ li(r3, Operand(LESS));  // NaN >= NaN should fail.
 | 
| +        }
 | 
|        }
 | 
|      }
 | 
|      __ Ret();
 | 
| @@ -571,7 +576,7 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
 | 
|    // If either is a Smi (we know that not both are), then they can only
 | 
|    // be strictly equal if the other is a HeapNumber.
 | 
|    STATIC_ASSERT(kSmiTag == 0);
 | 
| -  DCHECK_EQ(0, Smi::FromInt(0));
 | 
| +  DCHECK_EQ(static_cast<Smi*>(0), Smi::FromInt(0));
 | 
|    __ and_(r5, lhs, rhs);
 | 
|    __ JumpIfNotSmi(r5, ¬_smis);
 | 
|    // One operand is a smi.  EmitSmiNonsmiComparison generates code that can:
 | 
| @@ -592,16 +597,25 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
 | 
|  
 | 
|    Label nan, equal, less_than;
 | 
|    __ bunordered(&nan);
 | 
| -  __ beq(&equal);
 | 
| -  __ blt(&less_than);
 | 
| -  __ li(r3, Operand(GREATER));
 | 
| -  __ Ret();
 | 
| -  __ bind(&equal);
 | 
| -  __ li(r3, Operand(EQUAL));
 | 
| -  __ Ret();
 | 
| -  __ bind(&less_than);
 | 
| -  __ li(r3, Operand(LESS));
 | 
| -  __ Ret();
 | 
| +  if (CpuFeatures::IsSupported(ISELECT)) {
 | 
| +    DCHECK(EQUAL == 0);
 | 
| +    __ li(r4, Operand(GREATER));
 | 
| +    __ li(r5, Operand(LESS));
 | 
| +    __ isel(eq, r3, r0, r4);
 | 
| +    __ isel(lt, r3, r5, r3);
 | 
| +    __ Ret();
 | 
| +  } else {
 | 
| +    __ beq(&equal);
 | 
| +    __ blt(&less_than);
 | 
| +    __ li(r3, Operand(GREATER));
 | 
| +    __ Ret();
 | 
| +    __ bind(&equal);
 | 
| +    __ li(r3, Operand(EQUAL));
 | 
| +    __ Ret();
 | 
| +    __ bind(&less_than);
 | 
| +    __ li(r3, Operand(LESS));
 | 
| +    __ Ret();
 | 
| +  }
 | 
|  
 | 
|    __ bind(&nan);
 | 
|    // If one of the sides was a NaN then the v flag is set.  Load r3 with
 | 
| @@ -862,11 +876,16 @@ void MathPowStub::Generate(MacroAssembler* masm) {
 | 
|    __ ConvertIntToDouble(scratch2, double_result);
 | 
|  
 | 
|    // Get absolute value of exponent.
 | 
| -  Label positive_exponent;
 | 
|    __ cmpi(scratch, Operand::Zero());
 | 
| -  __ bge(&positive_exponent);
 | 
| -  __ neg(scratch, scratch);
 | 
| -  __ bind(&positive_exponent);
 | 
| +  if (CpuFeatures::IsSupported(ISELECT)) {
 | 
| +    __ neg(scratch2, scratch);
 | 
| +    __ isel(lt, scratch, scratch2, scratch);
 | 
| +  } else {
 | 
| +    Label positive_exponent;
 | 
| +    __ bge(&positive_exponent);
 | 
| +    __ neg(scratch, scratch);
 | 
| +    __ bind(&positive_exponent);
 | 
| +  }
 | 
|  
 | 
|    Label while_true, no_carry, loop_end;
 | 
|    __ bind(&while_true);
 | 
| @@ -937,11 +956,11 @@ bool CEntryStub::NeedsImmovableCode() { return true; }
 | 
|  
 | 
|  void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) {
 | 
|    CEntryStub::GenerateAheadOfTime(isolate);
 | 
| -  //  WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate);
 | 
|    StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
 | 
|    StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
 | 
|    ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
 | 
|    CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
 | 
| +  CreateWeakCellStub::GenerateAheadOfTime(isolate);
 | 
|    BinaryOpICStub::GenerateAheadOfTime(isolate);
 | 
|    StoreRegistersStateStub::GenerateAheadOfTime(isolate);
 | 
|    RestoreRegistersStateStub::GenerateAheadOfTime(isolate);
 | 
| @@ -1000,7 +1019,7 @@ void CEntryStub::Generate(MacroAssembler* masm) {
 | 
|    int arg_stack_space = 1;
 | 
|  
 | 
|  // PPC LINUX ABI:
 | 
| -#if V8_TARGET_ARCH_PPC64 && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
 | 
| +#if !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
 | 
|    // Pass buffer for return value on stack if necessary
 | 
|    if (result_size() > 1) {
 | 
|      DCHECK_EQ(2, result_size());
 | 
| @@ -1020,7 +1039,7 @@ void CEntryStub::Generate(MacroAssembler* masm) {
 | 
|    // Result returned in registers or stack, depending on result size and ABI.
 | 
|  
 | 
|    Register isolate_reg = r5;
 | 
| -#if V8_TARGET_ARCH_PPC64 && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
 | 
| +#if !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
 | 
|    if (result_size() > 1) {
 | 
|      // The return value is 16-byte non-scalar value.
 | 
|      // Use frame storage reserved by calling function to pass return
 | 
| @@ -1068,7 +1087,7 @@ void CEntryStub::Generate(MacroAssembler* masm) {
 | 
|      __ Call(target);
 | 
|    }
 | 
|  
 | 
| -#if V8_TARGET_ARCH_PPC64 && !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
 | 
| +#if !ABI_RETURNS_OBJECT_PAIRS_IN_REGS
 | 
|    // If return value is on the stack, pop it to registers.
 | 
|    if (result_size() > 1) {
 | 
|      __ LoadP(r4, MemOperand(r3, kPointerSize));
 | 
| @@ -1499,17 +1518,24 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
 | 
|        __ Push(r3, r4);
 | 
|        __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION);
 | 
|      }
 | 
| -    Label true_value, done;
 | 
| -    __ cmpi(r3, Operand::Zero());
 | 
| -    __ beq(&true_value);
 | 
| +    if (CpuFeatures::IsSupported(ISELECT)) {
 | 
| +      __ cmpi(r3, Operand::Zero());
 | 
| +      __ LoadRoot(r3, Heap::kTrueValueRootIndex);
 | 
| +      __ LoadRoot(r4, Heap::kFalseValueRootIndex);
 | 
| +      __ isel(eq, r3, r3, r4);
 | 
| +    } else {
 | 
| +      Label true_value, done;
 | 
| +      __ cmpi(r3, Operand::Zero());
 | 
| +      __ beq(&true_value);
 | 
|  
 | 
| -    __ LoadRoot(r3, Heap::kFalseValueRootIndex);
 | 
| -    __ b(&done);
 | 
| +      __ LoadRoot(r3, Heap::kFalseValueRootIndex);
 | 
| +      __ b(&done);
 | 
|  
 | 
| -    __ bind(&true_value);
 | 
| -    __ LoadRoot(r3, Heap::kTrueValueRootIndex);
 | 
| +      __ bind(&true_value);
 | 
| +      __ LoadRoot(r3, Heap::kTrueValueRootIndex);
 | 
|  
 | 
| -    __ bind(&done);
 | 
| +      __ bind(&done);
 | 
| +    }
 | 
|      __ Ret(HasArgsInRegisters() ? 0 : 2);
 | 
|    }
 | 
|  }
 | 
| @@ -1518,9 +1544,14 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
 | 
|  void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
 | 
|    Label miss;
 | 
|    Register receiver = LoadDescriptor::ReceiverRegister();
 | 
| -
 | 
| -  NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, r6,
 | 
| -                                                          r7, &miss);
 | 
| +  // Ensure that the vector and slot registers won't be clobbered before
 | 
| +  // calling the miss handler.
 | 
| +  DCHECK(!FLAG_vector_ics ||
 | 
| +         !AreAliased(r7, r8, VectorLoadICDescriptor::VectorRegister(),
 | 
| +                     VectorLoadICDescriptor::SlotRegister()));
 | 
| +
 | 
| +  NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, r7,
 | 
| +                                                          r8, &miss);
 | 
|    __ bind(&miss);
 | 
|    PropertyAccessCompiler::TailCallBuiltin(
 | 
|        masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC));
 | 
| @@ -1533,10 +1564,16 @@ void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
 | 
|  
 | 
|    Register receiver = LoadDescriptor::ReceiverRegister();
 | 
|    Register index = LoadDescriptor::NameRegister();
 | 
| -  Register scratch = r6;
 | 
| +  Register scratch = r8;
 | 
|    Register result = r3;
 | 
|    DCHECK(!scratch.is(receiver) && !scratch.is(index));
 | 
| +  DCHECK(!FLAG_vector_ics ||
 | 
| +         (!scratch.is(VectorLoadICDescriptor::VectorRegister()) &&
 | 
| +          result.is(VectorLoadICDescriptor::SlotRegister())));
 | 
|  
 | 
| +  // StringCharAtGenerator doesn't use the result register until it's passed
 | 
| +  // the different miss possibilities. If it did, we would have a conflict
 | 
| +  // when FLAG_vector_ics is true.
 | 
|    StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
 | 
|                                            &miss,  // When not a string.
 | 
|                                            &miss,  // When not a number.
 | 
| @@ -1673,11 +1710,15 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
 | 
|    // r4 = parameter count (tagged)
 | 
|    // r5 = argument count (tagged)
 | 
|    // Compute the mapped parameter count = min(r4, r5) in r4.
 | 
| -  Label skip;
 | 
|    __ cmp(r4, r5);
 | 
| -  __ blt(&skip);
 | 
| -  __ mr(r4, r5);
 | 
| -  __ bind(&skip);
 | 
| +  if (CpuFeatures::IsSupported(ISELECT)) {
 | 
| +    __ isel(lt, r4, r4, r5);
 | 
| +  } else {
 | 
| +    Label skip;
 | 
| +    __ blt(&skip);
 | 
| +    __ mr(r4, r5);
 | 
| +    __ bind(&skip);
 | 
| +  }
 | 
|  
 | 
|    __ bind(&try_allocate);
 | 
|  
 | 
| @@ -1686,15 +1727,21 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
 | 
|    const int kParameterMapHeaderSize =
 | 
|        FixedArray::kHeaderSize + 2 * kPointerSize;
 | 
|    // If there are no mapped parameters, we do not need the parameter_map.
 | 
| -  Label skip2, skip3;
 | 
|    __ CmpSmiLiteral(r4, Smi::FromInt(0), r0);
 | 
| -  __ bne(&skip2);
 | 
| -  __ li(r11, Operand::Zero());
 | 
| -  __ b(&skip3);
 | 
| -  __ bind(&skip2);
 | 
| -  __ SmiToPtrArrayOffset(r11, r4);
 | 
| -  __ addi(r11, r11, Operand(kParameterMapHeaderSize));
 | 
| -  __ bind(&skip3);
 | 
| +  if (CpuFeatures::IsSupported(ISELECT)) {
 | 
| +    __ SmiToPtrArrayOffset(r11, r4);
 | 
| +    __ addi(r11, r11, Operand(kParameterMapHeaderSize));
 | 
| +    __ isel(eq, r11, r0, r11);
 | 
| +  } else {
 | 
| +    Label skip2, skip3;
 | 
| +    __ bne(&skip2);
 | 
| +    __ li(r11, Operand::Zero());
 | 
| +    __ b(&skip3);
 | 
| +    __ bind(&skip2);
 | 
| +    __ SmiToPtrArrayOffset(r11, r4);
 | 
| +    __ addi(r11, r11, Operand(kParameterMapHeaderSize));
 | 
| +    __ bind(&skip3);
 | 
| +  }
 | 
|  
 | 
|    // 2. Backing store.
 | 
|    __ SmiToPtrArrayOffset(r7, r5);
 | 
| @@ -1718,14 +1765,20 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
 | 
|    __ LoadP(r7,
 | 
|             MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
 | 
|    __ LoadP(r7, FieldMemOperand(r7, GlobalObject::kNativeContextOffset));
 | 
| -  Label skip4, skip5;
 | 
|    __ cmpi(r4, Operand::Zero());
 | 
| -  __ bne(&skip4);
 | 
| -  __ LoadP(r7, MemOperand(r7, kNormalOffset));
 | 
| -  __ b(&skip5);
 | 
| -  __ bind(&skip4);
 | 
| -  __ LoadP(r7, MemOperand(r7, kAliasedOffset));
 | 
| -  __ bind(&skip5);
 | 
| +  if (CpuFeatures::IsSupported(ISELECT)) {
 | 
| +    __ LoadP(r11, MemOperand(r7, kNormalOffset));
 | 
| +    __ LoadP(r7, MemOperand(r7, kAliasedOffset));
 | 
| +    __ isel(eq, r7, r11, r7);
 | 
| +  } else {
 | 
| +    Label skip4, skip5;
 | 
| +    __ bne(&skip4);
 | 
| +    __ LoadP(r7, MemOperand(r7, kNormalOffset));
 | 
| +    __ b(&skip5);
 | 
| +    __ bind(&skip4);
 | 
| +    __ LoadP(r7, MemOperand(r7, kAliasedOffset));
 | 
| +    __ bind(&skip5);
 | 
| +  }
 | 
|  
 | 
|    // r3 = address of new object (tagged)
 | 
|    // r4 = mapped parameter count (tagged)
 | 
| @@ -1762,14 +1815,20 @@ void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
 | 
|    // r5 = argument count (tagged)
 | 
|    // r7 = address of parameter map or backing store (tagged)
 | 
|    // Initialize parameter map. If there are no mapped arguments, we're done.
 | 
| -  Label skip_parameter_map, skip6;
 | 
| +  Label skip_parameter_map;
 | 
|    __ CmpSmiLiteral(r4, Smi::FromInt(0), r0);
 | 
| -  __ bne(&skip6);
 | 
| -  // Move backing store address to r6, because it is
 | 
| -  // expected there when filling in the unmapped arguments.
 | 
| -  __ mr(r6, r7);
 | 
| -  __ b(&skip_parameter_map);
 | 
| -  __ bind(&skip6);
 | 
| +  if (CpuFeatures::IsSupported(ISELECT)) {
 | 
| +    __ isel(eq, r6, r7, r6);
 | 
| +    __ beq(&skip_parameter_map);
 | 
| +  } else {
 | 
| +    Label skip6;
 | 
| +    __ bne(&skip6);
 | 
| +    // Move backing store address to r6, because it is
 | 
| +    // expected there when filling in the unmapped arguments.
 | 
| +    __ mr(r6, r7);
 | 
| +    __ b(&skip_parameter_map);
 | 
| +    __ bind(&skip6);
 | 
| +  }
 | 
|  
 | 
|    __ LoadRoot(r9, Heap::kSloppyArgumentsElementsMapRootIndex);
 | 
|    __ StoreP(r9, FieldMemOperand(r7, FixedArray::kMapOffset), r0);
 | 
| @@ -2682,19 +2741,27 @@ void CallConstructStub::Generate(MacroAssembler* masm) {
 | 
|        // entry is at the feedback vector slot given by r6 + 1.
 | 
|        __ LoadP(r5, FieldMemOperand(r8, FixedArray::kHeaderSize + kPointerSize));
 | 
|      } else {
 | 
| -      Label feedback_register_initialized;
 | 
|        // Put the AllocationSite from the feedback vector into r5, or undefined.
 | 
|        __ LoadP(r5, FieldMemOperand(r8, FixedArray::kHeaderSize));
 | 
|        __ LoadP(r8, FieldMemOperand(r5, AllocationSite::kMapOffset));
 | 
|        __ CompareRoot(r8, Heap::kAllocationSiteMapRootIndex);
 | 
| -      __ beq(&feedback_register_initialized);
 | 
| -      __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
 | 
| -      __ bind(&feedback_register_initialized);
 | 
| +      if (CpuFeatures::IsSupported(ISELECT)) {
 | 
| +        __ LoadRoot(r8, Heap::kUndefinedValueRootIndex);
 | 
| +        __ isel(eq, r5, r5, r8);
 | 
| +      } else {
 | 
| +        Label feedback_register_initialized;
 | 
| +        __ beq(&feedback_register_initialized);
 | 
| +        __ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
 | 
| +        __ bind(&feedback_register_initialized);
 | 
| +      }
 | 
|      }
 | 
|  
 | 
|      __ AssertUndefinedOrAllocationSite(r5, r8);
 | 
|    }
 | 
|  
 | 
| +  // Pass function as original constructor.
 | 
| +  __ mr(r6, r4);
 | 
| +
 | 
|    // Jump to the function-specific construct stub.
 | 
|    Register jmp_reg = r7;
 | 
|    __ LoadP(jmp_reg, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset));
 | 
| @@ -2736,12 +2803,11 @@ static void EmitLoadTypeFeedbackVector(MacroAssembler* masm, Register vector) {
 | 
|  void CallIC_ArrayStub::Generate(MacroAssembler* masm) {
 | 
|    // r4 - function
 | 
|    // r6 - slot id
 | 
| +  // r5 - vector
 | 
|    Label miss;
 | 
|    int argc = arg_count();
 | 
|    ParameterCount actual(argc);
 | 
|  
 | 
| -  EmitLoadTypeFeedbackVector(masm, r5);
 | 
| -
 | 
|    __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r7);
 | 
|    __ cmp(r4, r7);
 | 
|    __ bne(&miss);
 | 
| @@ -2774,21 +2840,44 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) {
 | 
|  void CallICStub::Generate(MacroAssembler* masm) {
 | 
|    // r4 - function
 | 
|    // r6 - slot id (Smi)
 | 
| +  // r5 - vector
 | 
| +  const int with_types_offset =
 | 
| +      FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex);
 | 
| +  const int generic_offset =
 | 
| +      FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex);
 | 
|    Label extra_checks_or_miss, slow_start;
 | 
|    Label slow, non_function, wrap, cont;
 | 
|    Label have_js_function;
 | 
|    int argc = arg_count();
 | 
|    ParameterCount actual(argc);
 | 
|  
 | 
| -  EmitLoadTypeFeedbackVector(masm, r5);
 | 
| -
 | 
|    // The checks. First, does r4 match the recorded monomorphic target?
 | 
|    __ SmiToPtrArrayOffset(r7, r6);
 | 
|    __ add(r7, r5, r7);
 | 
|    __ LoadP(r7, FieldMemOperand(r7, FixedArray::kHeaderSize));
 | 
| -  __ cmp(r4, r7);
 | 
| +
 | 
| +  // We don't know that we have a weak cell. We might have a private symbol
 | 
| +  // or an AllocationSite, but the memory is safe to examine.
 | 
| +  // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to
 | 
| +  // FixedArray.
 | 
| +  // WeakCell::kValueOffset - contains a JSFunction or Smi(0)
 | 
| +  // Symbol::kHashFieldSlot - if the low bit is 1, then the hash is not
 | 
| +  // computed, meaning that it can't appear to be a pointer. If the low bit is
 | 
| +  // 0, then hash is computed, but the 0 bit prevents the field from appearing
 | 
| +  // to be a pointer.
 | 
| +  STATIC_ASSERT(WeakCell::kSize >= kPointerSize);
 | 
| +  STATIC_ASSERT(AllocationSite::kTransitionInfoOffset ==
 | 
| +                    WeakCell::kValueOffset &&
 | 
| +                WeakCell::kValueOffset == Symbol::kHashFieldSlot);
 | 
| +
 | 
| +  __ LoadP(r8, FieldMemOperand(r7, WeakCell::kValueOffset));
 | 
| +  __ cmp(r4, r8);
 | 
|    __ bne(&extra_checks_or_miss);
 | 
|  
 | 
| +  // The compare above could have been a SMI/SMI comparison. Guard against this
 | 
| +  // convincing us that we have a monomorphic JSFunction.
 | 
| +  __ JumpIfSmi(r4, &extra_checks_or_miss);
 | 
| +
 | 
|    __ bind(&have_js_function);
 | 
|    if (CallAsMethod()) {
 | 
|      EmitContinueIfStrictOrNative(masm, &cont);
 | 
| @@ -2813,38 +2902,74 @@ void CallICStub::Generate(MacroAssembler* masm) {
 | 
|    }
 | 
|  
 | 
|    __ bind(&extra_checks_or_miss);
 | 
| -  Label miss;
 | 
| +  Label uninitialized, miss;
 | 
|  
 | 
|    __ CompareRoot(r7, Heap::kmegamorphic_symbolRootIndex);
 | 
|    __ beq(&slow_start);
 | 
| +
 | 
| +  // The following cases attempt to handle MISS cases without going to the
 | 
| +  // runtime.
 | 
| +  if (FLAG_trace_ic) {
 | 
| +    __ b(&miss);
 | 
| +  }
 | 
| +
 | 
|    __ CompareRoot(r7, Heap::kuninitialized_symbolRootIndex);
 | 
| +  __ beq(&uninitialized);
 | 
| +
 | 
| +  // We are going megamorphic. If the feedback is a JSFunction, it is fine
 | 
| +  // to handle it here. More complex cases are dealt with in the runtime.
 | 
| +  __ AssertNotSmi(r7);
 | 
| +  __ CompareObjectType(r7, r8, r8, JS_FUNCTION_TYPE);
 | 
| +  __ bne(&miss);
 | 
| +  __ SmiToPtrArrayOffset(r7, r6);
 | 
| +  __ add(r7, r5, r7);
 | 
| +  __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex);
 | 
| +  __ StoreP(ip, FieldMemOperand(r7, FixedArray::kHeaderSize), r0);
 | 
| +  // We have to update statistics for runtime profiling.
 | 
| +  __ LoadP(r7, FieldMemOperand(r5, with_types_offset));
 | 
| +  __ SubSmiLiteral(r7, r7, Smi::FromInt(1), r0);
 | 
| +  __ StoreP(r7, FieldMemOperand(r5, with_types_offset), r0);
 | 
| +  __ LoadP(r7, FieldMemOperand(r5, generic_offset));
 | 
| +  __ AddSmiLiteral(r7, r7, Smi::FromInt(1), r0);
 | 
| +  __ StoreP(r7, FieldMemOperand(r5, generic_offset), r0);
 | 
| +  __ b(&slow_start);
 | 
| +
 | 
| +  __ bind(&uninitialized);
 | 
| +
 | 
| +  // We are going monomorphic, provided we actually have a JSFunction.
 | 
| +  __ JumpIfSmi(r4, &miss);
 | 
| +
 | 
| +  // Goto miss case if we do not have a function.
 | 
| +  __ CompareObjectType(r4, r7, r7, JS_FUNCTION_TYPE);
 | 
| +  __ bne(&miss);
 | 
| +
 | 
| +  // Make sure the function is not the Array() function, which requires special
 | 
| +  // behavior on MISS.
 | 
| +  __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, r7);
 | 
| +  __ cmp(r4, r7);
 | 
|    __ beq(&miss);
 | 
|  
 | 
| -  if (!FLAG_trace_ic) {
 | 
| -    // We are going megamorphic. If the feedback is a JSFunction, it is fine
 | 
| -    // to handle it here. More complex cases are dealt with in the runtime.
 | 
| -    __ AssertNotSmi(r7);
 | 
| -    __ CompareObjectType(r7, r8, r8, JS_FUNCTION_TYPE);
 | 
| -    __ bne(&miss);
 | 
| -    __ SmiToPtrArrayOffset(r7, r6);
 | 
| -    __ add(r7, r5, r7);
 | 
| -    __ LoadRoot(ip, Heap::kmegamorphic_symbolRootIndex);
 | 
| -    __ StoreP(ip, FieldMemOperand(r7, FixedArray::kHeaderSize), r0);
 | 
| -    // We have to update statistics for runtime profiling.
 | 
| -    const int with_types_offset =
 | 
| -        FixedArray::OffsetOfElementAt(TypeFeedbackVector::kWithTypesIndex);
 | 
| -    __ LoadP(r7, FieldMemOperand(r5, with_types_offset));
 | 
| -    __ SubSmiLiteral(r7, r7, Smi::FromInt(1), r0);
 | 
| -    __ StoreP(r7, FieldMemOperand(r5, with_types_offset), r0);
 | 
| -    const int generic_offset =
 | 
| -        FixedArray::OffsetOfElementAt(TypeFeedbackVector::kGenericCountIndex);
 | 
| -    __ LoadP(r7, FieldMemOperand(r5, generic_offset));
 | 
| -    __ AddSmiLiteral(r7, r7, Smi::FromInt(1), r0);
 | 
| -    __ StoreP(r7, FieldMemOperand(r5, generic_offset), r0);
 | 
| -    __ jmp(&slow_start);
 | 
| +  // Update stats.
 | 
| +  __ LoadP(r7, FieldMemOperand(r5, with_types_offset));
 | 
| +  __ AddSmiLiteral(r7, r7, Smi::FromInt(1), r0);
 | 
| +  __ StoreP(r7, FieldMemOperand(r5, with_types_offset), r0);
 | 
| +
 | 
| +  // Store the function. Use a stub since we need a frame for allocation.
 | 
| +  // r5 - vector
 | 
| +  // r6 - slot
 | 
| +  // r4 - function
 | 
| +  {
 | 
| +    FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
 | 
| +    CreateWeakCellStub create_stub(masm->isolate());
 | 
| +    __ Push(r4);
 | 
| +    __ CallStub(&create_stub);
 | 
| +    __ Pop(r4);
 | 
|    }
 | 
|  
 | 
| -  // We are here because tracing is on or we are going monomorphic.
 | 
| +  __ b(&have_js_function);
 | 
| +
 | 
| +  // We are here because tracing is on or we encountered a MISS case we can't
 | 
| +  // handle here.
 | 
|    __ bind(&miss);
 | 
|    GenerateMiss(masm);
 | 
|  
 | 
| @@ -2862,25 +2987,20 @@ void CallICStub::Generate(MacroAssembler* masm) {
 | 
|  
 | 
|  
 | 
|  void CallICStub::GenerateMiss(MacroAssembler* masm) {
 | 
| -  // Get the receiver of the function from the stack; 1 ~ return address.
 | 
| -  __ LoadP(r7, MemOperand(sp, (arg_count() + 1) * kPointerSize), r0);
 | 
| +  FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
 | 
|  
 | 
| -  {
 | 
| -    FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
 | 
| -
 | 
| -    // Push the receiver and the function and feedback info.
 | 
| -    __ Push(r7, r4, r5, r6);
 | 
| +  // Push the function and feedback info.
 | 
| +  __ Push(r4, r5, r6);
 | 
|  
 | 
| -    // Call the entry.
 | 
| -    IC::UtilityId id = GetICState() == DEFAULT ? IC::kCallIC_Miss
 | 
| -                                               : IC::kCallIC_Customization_Miss;
 | 
| +  // Call the entry.
 | 
| +  IC::UtilityId id = GetICState() == DEFAULT ? IC::kCallIC_Miss
 | 
| +                                             : IC::kCallIC_Customization_Miss;
 | 
|  
 | 
| -    ExternalReference miss = ExternalReference(IC_Utility(id), masm->isolate());
 | 
| -    __ CallExternalReference(miss, 4);
 | 
| +  ExternalReference miss = ExternalReference(IC_Utility(id), masm->isolate());
 | 
| +  __ CallExternalReference(miss, 3);
 | 
|  
 | 
| -    // Move result to r4 and exit the internal frame.
 | 
| -    __ mr(r4, r3);
 | 
| -  }
 | 
| +  // Move result to r4 and exit the internal frame.
 | 
| +  __ mr(r4, r3);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -3268,6 +3388,49 @@ void SubStringStub::Generate(MacroAssembler* masm) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| +void ToNumberStub::Generate(MacroAssembler* masm) {
 | 
| +  // The ToNumber stub takes one argument in r3.
 | 
| +  Label not_smi;
 | 
| +  __ JumpIfNotSmi(r3, ¬_smi);
 | 
| +  __ blr();
 | 
| +  __ bind(¬_smi);
 | 
| +
 | 
| +  Label not_heap_number;
 | 
| +  __ LoadP(r4, FieldMemOperand(r3, HeapObject::kMapOffset));
 | 
| +  __ lbz(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
 | 
| +  // r3: object
 | 
| +  // r4: instance type.
 | 
| +  __ cmpi(r4, Operand(HEAP_NUMBER_TYPE));
 | 
| +  __ bne(¬_heap_number);
 | 
| +  __ blr();
 | 
| +  __ bind(¬_heap_number);
 | 
| +
 | 
| +  Label not_string, slow_string;
 | 
| +  __ cmpli(r4, Operand(FIRST_NONSTRING_TYPE));
 | 
| +  __ bge(¬_string);
 | 
| +  // Check if string has a cached array index.
 | 
| +  __ lwz(r5, FieldMemOperand(r3, String::kHashFieldOffset));
 | 
| +  __ And(r0, r5, Operand(String::kContainsCachedArrayIndexMask), SetRC);
 | 
| +  __ bne(&slow_string, cr0);
 | 
| +  __ IndexFromHash(r5, r3);
 | 
| +  __ blr();
 | 
| +  __ bind(&slow_string);
 | 
| +  __ push(r3);  // Push argument.
 | 
| +  __ TailCallRuntime(Runtime::kStringToNumber, 1, 1);
 | 
| +  __ bind(¬_string);
 | 
| +
 | 
| +  Label not_oddball;
 | 
| +  __ cmpi(r4, Operand(ODDBALL_TYPE));
 | 
| +  __ bne(¬_oddball);
 | 
| +  __ LoadP(r3, FieldMemOperand(r3, Oddball::kToNumberOffset));
 | 
| +  __ blr();
 | 
| +  __ bind(¬_oddball);
 | 
| +
 | 
| +  __ push(r3);  // Push argument.
 | 
| +  __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_FUNCTION);
 | 
| +}
 | 
| +
 | 
| +
 | 
|  void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm,
 | 
|                                                     Register left,
 | 
|                                                     Register right,
 | 
| @@ -3308,15 +3471,20 @@ void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm,
 | 
|  void StringHelper::GenerateCompareFlatOneByteStrings(
 | 
|      MacroAssembler* masm, Register left, Register right, Register scratch1,
 | 
|      Register scratch2, Register scratch3) {
 | 
| -  Label skip, result_not_equal, compare_lengths;
 | 
| +  Label result_not_equal, compare_lengths;
 | 
|    // Find minimum length and length difference.
 | 
|    __ LoadP(scratch1, FieldMemOperand(left, String::kLengthOffset));
 | 
|    __ LoadP(scratch2, FieldMemOperand(right, String::kLengthOffset));
 | 
|    __ sub(scratch3, scratch1, scratch2, LeaveOE, SetRC);
 | 
|    Register length_delta = scratch3;
 | 
| -  __ ble(&skip, cr0);
 | 
| -  __ mr(scratch1, scratch2);
 | 
| -  __ bind(&skip);
 | 
| +  if (CpuFeatures::IsSupported(ISELECT)) {
 | 
| +    __ isel(gt, scratch1, scratch2, scratch1, cr0);
 | 
| +  } else {
 | 
| +    Label skip;
 | 
| +    __ ble(&skip, cr0);
 | 
| +    __ mr(scratch1, scratch2);
 | 
| +    __ bind(&skip);
 | 
| +  }
 | 
|    Register min_length = scratch1;
 | 
|    STATIC_ASSERT(kSmiTag == 0);
 | 
|    __ cmpi(min_length, Operand::Zero());
 | 
| @@ -3335,15 +3503,23 @@ void StringHelper::GenerateCompareFlatOneByteStrings(
 | 
|    __ bind(&result_not_equal);
 | 
|    // Conditionally update the result based either on length_delta or
 | 
|    // the last comparion performed in the loop above.
 | 
| -  Label less_equal, equal;
 | 
| -  __ ble(&less_equal);
 | 
| -  __ LoadSmiLiteral(r3, Smi::FromInt(GREATER));
 | 
| -  __ Ret();
 | 
| -  __ bind(&less_equal);
 | 
| -  __ beq(&equal);
 | 
| -  __ LoadSmiLiteral(r3, Smi::FromInt(LESS));
 | 
| -  __ bind(&equal);
 | 
| -  __ Ret();
 | 
| +  if (CpuFeatures::IsSupported(ISELECT)) {
 | 
| +    __ li(r4, Operand(GREATER));
 | 
| +    __ li(r5, Operand(LESS));
 | 
| +    __ isel(eq, r3, r0, r4);
 | 
| +    __ isel(lt, r3, r5, r3);
 | 
| +    __ Ret();
 | 
| +  } else {
 | 
| +    Label less_equal, equal;
 | 
| +    __ ble(&less_equal);
 | 
| +    __ LoadSmiLiteral(r3, Smi::FromInt(GREATER));
 | 
| +    __ Ret();
 | 
| +    __ bind(&less_equal);
 | 
| +    __ beq(&equal);
 | 
| +    __ LoadSmiLiteral(r3, Smi::FromInt(LESS));
 | 
| +    __ bind(&equal);
 | 
| +    __ Ret();
 | 
| +  }
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -3511,17 +3687,26 @@ void CompareICStub::GenerateNumbers(MacroAssembler* masm) {
 | 
|    __ bunordered(&unordered);
 | 
|  
 | 
|    // Return a result of -1, 0, or 1, based on status bits.
 | 
| -  __ beq(&equal);
 | 
| -  __ blt(&less_than);
 | 
| -  //  assume greater than
 | 
| -  __ li(r3, Operand(GREATER));
 | 
| -  __ Ret();
 | 
| -  __ bind(&equal);
 | 
| -  __ li(r3, Operand(EQUAL));
 | 
| -  __ Ret();
 | 
| -  __ bind(&less_than);
 | 
| -  __ li(r3, Operand(LESS));
 | 
| -  __ Ret();
 | 
| +  if (CpuFeatures::IsSupported(ISELECT)) {
 | 
| +    DCHECK(EQUAL == 0);
 | 
| +    __ li(r4, Operand(GREATER));
 | 
| +    __ li(r5, Operand(LESS));
 | 
| +    __ isel(eq, r3, r0, r4);
 | 
| +    __ isel(lt, r3, r5, r3);
 | 
| +    __ Ret();
 | 
| +  } else {
 | 
| +    __ beq(&equal);
 | 
| +    __ blt(&less_than);
 | 
| +    //  assume greater than
 | 
| +    __ li(r3, Operand(GREATER));
 | 
| +    __ Ret();
 | 
| +    __ bind(&equal);
 | 
| +    __ li(r3, Operand(EQUAL));
 | 
| +    __ Ret();
 | 
| +    __ bind(&less_than);
 | 
| +    __ li(r3, Operand(LESS));
 | 
| +    __ Ret();
 | 
| +  }
 | 
|  
 | 
|    __ bind(&unordered);
 | 
|    __ bind(&generic_stub);
 | 
| @@ -3735,13 +3920,15 @@ void CompareICStub::GenerateObjects(MacroAssembler* masm) {
 | 
|  
 | 
|  void CompareICStub::GenerateKnownObjects(MacroAssembler* masm) {
 | 
|    Label miss;
 | 
| +  Handle<WeakCell> cell = Map::WeakCellForMap(known_map_);
 | 
|    __ and_(r5, r4, r3);
 | 
|    __ JumpIfSmi(r5, &miss);
 | 
| +  __ GetWeakValue(r7, cell);
 | 
|    __ LoadP(r5, FieldMemOperand(r3, HeapObject::kMapOffset));
 | 
|    __ LoadP(r6, FieldMemOperand(r4, HeapObject::kMapOffset));
 | 
| -  __ Cmpi(r5, Operand(known_map_), r0);
 | 
| +  __ cmp(r5, r7);
 | 
|    __ bne(&miss);
 | 
| -  __ Cmpi(r6, Operand(known_map_), r0);
 | 
| +  __ cmp(r6, r7);
 | 
|    __ bne(&miss);
 | 
|  
 | 
|    __ sub(r3, r3, r4);
 | 
| @@ -3825,7 +4012,7 @@ void NameDictionaryLookupStub::GenerateNegativeLookup(
 | 
|      __ and_(index, index, ip);
 | 
|  
 | 
|      // Scale the index by multiplying by the entry size.
 | 
| -    DCHECK(NameDictionary::kEntrySize == 3);
 | 
| +    STATIC_ASSERT(NameDictionary::kEntrySize == 3);
 | 
|      __ ShiftLeftImm(ip, index, Operand(1));
 | 
|      __ add(index, index, ip);  // index *= 3.
 | 
|  
 | 
| @@ -4014,7 +4201,6 @@ void NameDictionaryLookupStub::Generate(MacroAssembler* masm) {
 | 
|      __ ShiftLeftImm(scratch, index, Operand(1));
 | 
|      __ add(index, index, scratch);  // index *= 3.
 | 
|  
 | 
| -    DCHECK_EQ(kSmiTagSize, 1);
 | 
|      __ ShiftLeftImm(scratch, index, Operand(kPointerSizeLog2));
 | 
|      __ add(index, dictionary, scratch);
 | 
|      __ LoadP(entry_key, FieldMemOperand(index, kElementsStartOffset));
 | 
| @@ -4335,6 +4521,20 @@ void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| +void CallICTrampolineStub::Generate(MacroAssembler* masm) {
 | 
| +  EmitLoadTypeFeedbackVector(masm, r5);
 | 
| +  CallICStub stub(isolate(), state());
 | 
| +  __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void CallIC_ArrayTrampolineStub::Generate(MacroAssembler* masm) {
 | 
| +  EmitLoadTypeFeedbackVector(masm, r5);
 | 
| +  CallIC_ArrayStub stub(isolate(), state());
 | 
| +  __ Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
 | 
| +}
 | 
| +
 | 
| +
 | 
|  void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) {
 | 
|    if (masm->isolate()->function_entry_hook() != NULL) {
 | 
|      PredictableCodeSizeScope predictable(masm,
 | 
| @@ -4711,12 +4911,167 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void CallApiFunctionStub::Generate(MacroAssembler* masm) {
 | 
| +static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
 | 
| +  return ref0.address() - ref1.address();
 | 
| +}
 | 
| +
 | 
| +
 | 
| +// Calls an API function.  Allocates HandleScope, extracts returned value
 | 
| +// from handle and propagates exceptions.  Restores context.  stack_space
 | 
| +// - space to be unwound on exit (includes the call JS arguments space and
 | 
| +// the additional space allocated for the fast call).
 | 
| +static void CallApiFunctionAndReturn(MacroAssembler* masm,
 | 
| +                                     Register function_address,
 | 
| +                                     ExternalReference thunk_ref,
 | 
| +                                     int stack_space,
 | 
| +                                     MemOperand* stack_space_operand,
 | 
| +                                     MemOperand return_value_operand,
 | 
| +                                     MemOperand* context_restore_operand) {
 | 
| +  Isolate* isolate = masm->isolate();
 | 
| +  ExternalReference next_address =
 | 
| +      ExternalReference::handle_scope_next_address(isolate);
 | 
| +  const int kNextOffset = 0;
 | 
| +  const int kLimitOffset = AddressOffset(
 | 
| +      ExternalReference::handle_scope_limit_address(isolate), next_address);
 | 
| +  const int kLevelOffset = AddressOffset(
 | 
| +      ExternalReference::handle_scope_level_address(isolate), next_address);
 | 
| +
 | 
| +  // Additional parameter is the address of the actual callback.
 | 
| +  DCHECK(function_address.is(r4) || function_address.is(r5));
 | 
| +  Register scratch = r6;
 | 
| +
 | 
| +  __ mov(scratch, Operand(ExternalReference::is_profiling_address(isolate)));
 | 
| +  __ lbz(scratch, MemOperand(scratch, 0));
 | 
| +  __ cmpi(scratch, Operand::Zero());
 | 
| +
 | 
| +  if (CpuFeatures::IsSupported(ISELECT)) {
 | 
| +    __ mov(scratch, Operand(thunk_ref));
 | 
| +    __ isel(eq, scratch, function_address, scratch);
 | 
| +  } else {
 | 
| +    Label profiler_disabled;
 | 
| +    Label end_profiler_check;
 | 
| +    __ beq(&profiler_disabled);
 | 
| +    __ mov(scratch, Operand(thunk_ref));
 | 
| +    __ b(&end_profiler_check);
 | 
| +    __ bind(&profiler_disabled);
 | 
| +    __ mr(scratch, function_address);
 | 
| +    __ bind(&end_profiler_check);
 | 
| +  }
 | 
| +
 | 
| +  // Allocate HandleScope in callee-save registers.
 | 
| +  // r17 - next_address
 | 
| +  // r14 - next_address->kNextOffset
 | 
| +  // r15 - next_address->kLimitOffset
 | 
| +  // r16 - next_address->kLevelOffset
 | 
| +  __ mov(r17, Operand(next_address));
 | 
| +  __ LoadP(r14, MemOperand(r17, kNextOffset));
 | 
| +  __ LoadP(r15, MemOperand(r17, kLimitOffset));
 | 
| +  __ lwz(r16, MemOperand(r17, kLevelOffset));
 | 
| +  __ addi(r16, r16, Operand(1));
 | 
| +  __ stw(r16, MemOperand(r17, kLevelOffset));
 | 
| +
 | 
| +  if (FLAG_log_timer_events) {
 | 
| +    FrameScope frame(masm, StackFrame::MANUAL);
 | 
| +    __ PushSafepointRegisters();
 | 
| +    __ PrepareCallCFunction(1, r3);
 | 
| +    __ mov(r3, Operand(ExternalReference::isolate_address(isolate)));
 | 
| +    __ CallCFunction(ExternalReference::log_enter_external_function(isolate),
 | 
| +                     1);
 | 
| +    __ PopSafepointRegisters();
 | 
| +  }
 | 
| +
 | 
| +  // Native call returns to the DirectCEntry stub which redirects to the
 | 
| +  // return address pushed on stack (could have moved after GC).
 | 
| +  // DirectCEntry stub itself is generated early and never moves.
 | 
| +  DirectCEntryStub stub(isolate);
 | 
| +  stub.GenerateCall(masm, scratch);
 | 
| +
 | 
| +  if (FLAG_log_timer_events) {
 | 
| +    FrameScope frame(masm, StackFrame::MANUAL);
 | 
| +    __ PushSafepointRegisters();
 | 
| +    __ PrepareCallCFunction(1, r3);
 | 
| +    __ mov(r3, Operand(ExternalReference::isolate_address(isolate)));
 | 
| +    __ CallCFunction(ExternalReference::log_leave_external_function(isolate),
 | 
| +                     1);
 | 
| +    __ PopSafepointRegisters();
 | 
| +  }
 | 
| +
 | 
| +  Label promote_scheduled_exception;
 | 
| +  Label exception_handled;
 | 
| +  Label delete_allocated_handles;
 | 
| +  Label leave_exit_frame;
 | 
| +  Label return_value_loaded;
 | 
| +
 | 
| +  // load value from ReturnValue
 | 
| +  __ LoadP(r3, return_value_operand);
 | 
| +  __ bind(&return_value_loaded);
 | 
| +  // No more valid handles (the result handle was the last one). Restore
 | 
| +  // previous handle scope.
 | 
| +  __ StoreP(r14, MemOperand(r17, kNextOffset));
 | 
| +  if (__ emit_debug_code()) {
 | 
| +    __ lwz(r4, MemOperand(r17, kLevelOffset));
 | 
| +    __ cmp(r4, r16);
 | 
| +    __ Check(eq, kUnexpectedLevelAfterReturnFromApiCall);
 | 
| +  }
 | 
| +  __ subi(r16, r16, Operand(1));
 | 
| +  __ stw(r16, MemOperand(r17, kLevelOffset));
 | 
| +  __ LoadP(r0, MemOperand(r17, kLimitOffset));
 | 
| +  __ cmp(r15, r0);
 | 
| +  __ bne(&delete_allocated_handles);
 | 
| +
 | 
| +  // Check if the function scheduled an exception.
 | 
| +  __ 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);
 | 
| +  }
 | 
| +  // LeaveExitFrame expects unwind space to be in a register.
 | 
| +  if (stack_space_operand != NULL) {
 | 
| +    __ lwz(r14, *stack_space_operand);
 | 
| +  } else {
 | 
| +    __ mov(r14, Operand(stack_space));
 | 
| +  }
 | 
| +  __ LeaveExitFrame(false, r14, !restore_context, stack_space_operand != NULL);
 | 
| +  __ blr();
 | 
| +
 | 
| +  __ bind(&promote_scheduled_exception);
 | 
| +  {
 | 
| +    FrameScope frame(masm, StackFrame::INTERNAL);
 | 
| +    __ CallExternalReference(
 | 
| +        ExternalReference(Runtime::kPromoteScheduledException, isolate), 0);
 | 
| +  }
 | 
| +  __ jmp(&exception_handled);
 | 
| +
 | 
| +  // HandleScope limit has changed. Delete allocated extensions.
 | 
| +  __ bind(&delete_allocated_handles);
 | 
| +  __ StoreP(r15, MemOperand(r17, kLimitOffset));
 | 
| +  __ mr(r14, r3);
 | 
| +  __ PrepareCallCFunction(1, r15);
 | 
| +  __ mov(r3, Operand(ExternalReference::isolate_address(isolate)));
 | 
| +  __ CallCFunction(ExternalReference::delete_handle_scope_extensions(isolate),
 | 
| +                   1);
 | 
| +  __ mr(r3, r14);
 | 
| +  __ b(&leave_exit_frame);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +static void CallApiFunctionStubHelper(MacroAssembler* masm,
 | 
| +                                      const ParameterCount& argc,
 | 
| +                                      bool return_first_arg,
 | 
| +                                      bool call_data_undefined) {
 | 
|    // ----------- S t a t e -------------
 | 
|    //  -- r3                  : callee
 | 
|    //  -- r7                  : call_data
 | 
|    //  -- r5                  : holder
 | 
|    //  -- r4                  : api_function_address
 | 
| +  //  -- r6                  : number of arguments if argc is a register
 | 
|    //  -- cp                  : context
 | 
|    //  --
 | 
|    //  -- sp[0]               : last argument
 | 
| @@ -4731,10 +5086,6 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) {
 | 
|    Register api_function_address = r4;
 | 
|    Register context = cp;
 | 
|  
 | 
| -  int argc = this->argc();
 | 
| -  bool is_store = this->is_store();
 | 
| -  bool call_data_undefined = this->call_data_undefined();
 | 
| -
 | 
|    typedef FunctionCallbackArguments FCA;
 | 
|  
 | 
|    STATIC_ASSERT(FCA::kContextSaveIndex == 6);
 | 
| @@ -4746,6 +5097,8 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) {
 | 
|    STATIC_ASSERT(FCA::kHolderIndex == 0);
 | 
|    STATIC_ASSERT(FCA::kArgsLength == 7);
 | 
|  
 | 
| +  DCHECK(argc.is_immediate() || r3.is(argc.reg()));
 | 
| +
 | 
|    // context save
 | 
|    __ push(context);
 | 
|    // load context from callee
 | 
| @@ -4766,7 +5119,7 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) {
 | 
|    // return value default
 | 
|    __ push(scratch);
 | 
|    // isolate
 | 
| -  __ mov(scratch, Operand(ExternalReference::isolate_address(isolate())));
 | 
| +  __ mov(scratch, Operand(ExternalReference::isolate_address(masm->isolate())));
 | 
|    __ push(scratch);
 | 
|    // holder
 | 
|    __ push(holder);
 | 
| @@ -4782,6 +5135,8 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) {
 | 
|    //    [0] space for DirectCEntryStub's LR save
 | 
|    //    [1-4] FunctionCallbackInfo
 | 
|    const int kApiStackSpace = 5;
 | 
| +  const int kFunctionCallbackInfoOffset =
 | 
| +      (kStackFrameExtraParamSlot + 1) * kPointerSize;
 | 
|  
 | 
|    FrameScope frame_scope(masm, StackFrame::MANUAL);
 | 
|    __ EnterExitFrame(false, kApiStackSpace);
 | 
| @@ -4789,38 +5144,73 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) {
 | 
|    DCHECK(!api_function_address.is(r3) && !scratch.is(r3));
 | 
|    // r3 = FunctionCallbackInfo&
 | 
|    // Arguments is after the return address.
 | 
| -  __ addi(r3, sp, Operand((kStackFrameExtraParamSlot + 1) * kPointerSize));
 | 
| +  __ addi(r3, sp, Operand(kFunctionCallbackInfoOffset));
 | 
|    // FunctionCallbackInfo::implicit_args_
 | 
|    __ StoreP(scratch, MemOperand(r3, 0 * kPointerSize));
 | 
| -  // FunctionCallbackInfo::values_
 | 
| -  __ addi(ip, scratch, Operand((FCA::kArgsLength - 1 + argc) * kPointerSize));
 | 
| -  __ StoreP(ip, MemOperand(r3, 1 * kPointerSize));
 | 
| -  // FunctionCallbackInfo::length_ = argc
 | 
| -  __ li(ip, Operand(argc));
 | 
| -  __ stw(ip, MemOperand(r3, 2 * kPointerSize));
 | 
| -  // FunctionCallbackInfo::is_construct_call = 0
 | 
| -  __ li(ip, Operand::Zero());
 | 
| -  __ stw(ip, MemOperand(r3, 2 * kPointerSize + kIntSize));
 | 
| -
 | 
| -  const int kStackUnwindSpace = argc + FCA::kArgsLength + 1;
 | 
| +  if (argc.is_immediate()) {
 | 
| +    // FunctionCallbackInfo::values_
 | 
| +    __ addi(ip, scratch,
 | 
| +            Operand((FCA::kArgsLength - 1 + argc.immediate()) * kPointerSize));
 | 
| +    __ StoreP(ip, MemOperand(r3, 1 * kPointerSize));
 | 
| +    // FunctionCallbackInfo::length_ = argc
 | 
| +    __ li(ip, Operand(argc.immediate()));
 | 
| +    __ stw(ip, MemOperand(r3, 2 * kPointerSize));
 | 
| +    // FunctionCallbackInfo::is_construct_call_ = 0
 | 
| +    __ li(ip, Operand::Zero());
 | 
| +    __ stw(ip, MemOperand(r3, 2 * kPointerSize + kIntSize));
 | 
| +  } else {
 | 
| +    __ ShiftLeftImm(ip, argc.reg(), Operand(kPointerSizeLog2));
 | 
| +    __ addi(ip, ip, Operand((FCA::kArgsLength - 1) * kPointerSize));
 | 
| +    // FunctionCallbackInfo::values_
 | 
| +    __ add(r0, scratch, ip);
 | 
| +    __ StoreP(r0, MemOperand(r3, 1 * kPointerSize));
 | 
| +    // FunctionCallbackInfo::length_ = argc
 | 
| +    __ stw(argc.reg(), MemOperand(r3, 2 * kPointerSize));
 | 
| +    // FunctionCallbackInfo::is_construct_call_
 | 
| +    __ stw(ip, MemOperand(r3, 2 * kPointerSize + kIntSize));
 | 
| +  }
 | 
| +
 | 
|    ExternalReference thunk_ref =
 | 
| -      ExternalReference::invoke_function_callback(isolate());
 | 
| +      ExternalReference::invoke_function_callback(masm->isolate());
 | 
|  
 | 
|    AllowExternalCallThatCantCauseGC scope(masm);
 | 
|    MemOperand context_restore_operand(
 | 
|        fp, (2 + FCA::kContextSaveIndex) * kPointerSize);
 | 
|    // Stores return the first js argument
 | 
|    int return_value_offset = 0;
 | 
| -  if (is_store) {
 | 
| +  if (return_first_arg) {
 | 
|      return_value_offset = 2 + FCA::kArgsLength;
 | 
|    } else {
 | 
|      return_value_offset = 2 + FCA::kReturnValueOffset;
 | 
|    }
 | 
|    MemOperand return_value_operand(fp, return_value_offset * kPointerSize);
 | 
| +  int stack_space = 0;
 | 
| +  MemOperand is_construct_call_operand =
 | 
| +      MemOperand(sp, kFunctionCallbackInfoOffset + 2 * kPointerSize + kIntSize);
 | 
| +  MemOperand* stack_space_operand = &is_construct_call_operand;
 | 
| +  if (argc.is_immediate()) {
 | 
| +    stack_space = argc.immediate() + FCA::kArgsLength + 1;
 | 
| +    stack_space_operand = NULL;
 | 
| +  }
 | 
| +  CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space,
 | 
| +                           stack_space_operand, return_value_operand,
 | 
| +                           &context_restore_operand);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void CallApiFunctionStub::Generate(MacroAssembler* masm) {
 | 
| +  bool call_data_undefined = this->call_data_undefined();
 | 
| +  CallApiFunctionStubHelper(masm, ParameterCount(r6), false,
 | 
| +                            call_data_undefined);
 | 
| +}
 | 
| +
 | 
|  
 | 
| -  __ CallApiFunctionAndReturn(api_function_address, thunk_ref,
 | 
| -                              kStackUnwindSpace, return_value_operand,
 | 
| -                              &context_restore_operand);
 | 
| +void CallApiAccessorStub::Generate(MacroAssembler* masm) {
 | 
| +  bool is_store = this->is_store();
 | 
| +  int argc = this->argc();
 | 
| +  bool call_data_undefined = this->call_data_undefined();
 | 
| +  CallApiFunctionStubHelper(masm, ParameterCount(argc), is_store,
 | 
| +                            call_data_undefined);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -4878,9 +5268,9 @@ void CallApiGetterStub::Generate(MacroAssembler* masm) {
 | 
|  
 | 
|    ExternalReference thunk_ref =
 | 
|        ExternalReference::invoke_accessor_getter_callback(isolate());
 | 
| -  __ CallApiFunctionAndReturn(api_function_address, thunk_ref,
 | 
| -                              kStackUnwindSpace,
 | 
| -                              MemOperand(fp, 6 * kPointerSize), NULL);
 | 
| +  CallApiFunctionAndReturn(masm, api_function_address, thunk_ref,
 | 
| +                           kStackUnwindSpace, NULL,
 | 
| +                           MemOperand(fp, 6 * kPointerSize), NULL);
 | 
|  }
 | 
|  
 | 
|  
 | 
| 
 |