Commit cbc05640 authored by mbrandy's avatar mbrandy Committed by Commit bot

PPC: [for-in] Sanitize for-in optimizations and fix bailout points.

Port f48bf12f

Original commit message:
    The PrepareId bailout location was used incorrectly in Crankshaft and,
    as it turns out, is not required anyway (once you do it right). Also
    there was some premature optimization going on with the CheckEnumCache
    (trying to load null from roots only once), plus we can be smarter about
    the null/undefined check anyway.

    The idea behind this changes is to prepare unification of the two
    different ForInPrepare implementations that we now have, with the end
    result being that we only use the new implementation that was recently
    added for the interpreter.

R=bmeurer@chromium.org, joransiu@ca.ibm.com, jyan@ca.ibm.com, michael_dawson@ca.ibm.com
BUG=v8:3650
LOG=n

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

Cr-Commit-Position: refs/heads/master@{#33447}
parent f1cd428d
......@@ -5720,17 +5720,8 @@ void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
__ TestIfSmi(r3, r0);
DeoptimizeIf(eq, instr, Deoptimizer::kSmi, cr0);
STATIC_ASSERT(JS_PROXY_TYPE == FIRST_JS_RECEIVER_TYPE);
__ CompareObjectType(r3, r4, r4, JS_PROXY_TYPE);
DeoptimizeIf(le, instr, Deoptimizer::kWrongInstanceType);
Label use_cache, call_runtime;
Register null_value = r8;
__ LoadRoot(null_value, Heap::kNullValueRootIndex);
__ CheckEnumCache(null_value, &call_runtime);
__ CheckEnumCache(&call_runtime);
__ LoadP(r3, FieldMemOperand(r3, HeapObject::kMapOffset));
__ b(&use_cache);
......@@ -5739,11 +5730,6 @@ void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
__ bind(&call_runtime);
__ push(r3);
CallRuntime(Runtime::kGetPropertyNamesFast, instr);
__ LoadP(r4, FieldMemOperand(r3, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kMetaMapRootIndex);
__ cmp(r4, ip);
DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap);
__ bind(&use_cache);
}
......
......@@ -998,25 +998,20 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
ForIn loop_statement(this, stmt);
increment_loop_depth();
// Get the object to enumerate over. If the object is null or undefined, skip
// over the loop. See ECMA-262 version 5, section 12.6.4.
// Get the object to enumerate over.
SetExpressionAsStatementPosition(stmt->enumerable());
VisitForAccumulatorValue(stmt->enumerable());
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
__ cmp(r3, ip);
__ beq(&exit);
Register null_value = r7;
__ LoadRoot(null_value, Heap::kNullValueRootIndex);
__ cmp(r3, null_value);
__ beq(&exit);
PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
// Convert the object to a JS object.
// If the object is null or undefined, skip over the loop, otherwise convert
// it to a JS receiver. See ECMA-262 version 5, section 12.6.4.
Label convert, done_convert;
__ JumpIfSmi(r3, &convert);
__ CompareObjectType(r3, r4, r4, FIRST_JS_RECEIVER_TYPE);
__ bge(&done_convert);
__ CompareRoot(r3, Heap::kNullValueRootIndex);
__ beq(&exit);
__ CompareRoot(r3, Heap::kUndefinedValueRootIndex);
__ beq(&exit);
__ bind(&convert);
ToObjectStub stub(isolate());
__ CallStub(&stub);
......@@ -1024,16 +1019,14 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
__ push(r3);
// Check for proxies.
Label call_runtime;
__ CompareObjectType(r3, r4, r4, JS_PROXY_TYPE);
__ beq(&call_runtime);
// Check cache validity in generated code. This is a fast case for
// the JSObject::IsSimpleEnum cache validity checks. If we cannot
// guarantee cache validity, call the runtime system to check cache
// validity or get the property names in a fixed array.
__ CheckEnumCache(null_value, &call_runtime);
// Note: Proxies never have an enum cache, so will always take the
// slow path.
Label call_runtime;
__ CheckEnumCache(&call_runtime);
// The enum cache is valid. Load the map of the object being
// iterated over and use the cache for the iteration.
......
......@@ -5597,7 +5597,7 @@ void CallApiGetterStub::Generate(MacroAssembler* masm) {
int apiStackSpace = 0;
DCHECK(api_function_address.is(r5));
__ mr(r3, sp); // r0 = Handle<Name>
__ mr(r3, sp); // r3 = Handle<Name>
__ addi(r4, r3, Operand(1 * kPointerSize)); // r4 = PCA
// If ABI passes Handles (pointer-sized struct) in a register:
......
......@@ -3375,7 +3375,8 @@ void MacroAssembler::LoadAccessor(Register dst, Register holder,
}
void MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) {
void MacroAssembler::CheckEnumCache(Label* call_runtime) {
Register null_value = r8;
Register empty_fixed_array_value = r9;
LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
Label next, start;
......@@ -3389,6 +3390,7 @@ void MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) {
CmpSmiLiteral(r6, Smi::FromInt(kInvalidEnumCacheSentinel), r0);
beq(call_runtime);
LoadRoot(null_value, Heap::kNullValueRootIndex);
b(&start);
bind(&next);
......
......@@ -1443,9 +1443,9 @@ class MacroAssembler : public Assembler {
// Returns the pc offset at which the frame ends.
int LeaveFrame(StackFrame::Type type, int stack_adjustment = 0);
// Expects object in r0 and returns map with validated enum cache
// in r0. Assumes that any other register can be used as a scratch.
void CheckEnumCache(Register null_value, Label* call_runtime);
// Expects object in r3 and returns map with validated enum cache
// in r3. Assumes that any other register can be used as a scratch.
void CheckEnumCache(Label* call_runtime);
// AllocationMemento support. Arrays may have an associated
// AllocationMemento object that can be checked for in order to pretransition
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment