Commit 01f40e6a authored by verwaest's avatar verwaest Committed by Commit bot

Fix keyed element access wrt string wrappers

BUG=v8:4296
LOG=n

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

Cr-Commit-Position: refs/heads/master@{#29618}
parent 6ddcd327
......@@ -3789,23 +3789,35 @@ void MacroAssembler::JumpIfDictionaryInPrototypeChain(
Register scratch1,
Label* found) {
DCHECK(!scratch1.is(scratch0));
Factory* factory = isolate()->factory();
Register current = scratch0;
Label loop_again;
Label loop_again, end;
// scratch contained elements pointer.
mov(current, object);
ldr(current, FieldMemOperand(current, HeapObject::kMapOffset));
ldr(current, FieldMemOperand(current, Map::kPrototypeOffset));
CompareRoot(current, Heap::kNullValueRootIndex);
b(eq, &end);
// Loop based on the map going up the prototype chain.
bind(&loop_again);
ldr(current, FieldMemOperand(current, HeapObject::kMapOffset));
STATIC_ASSERT(JS_PROXY_TYPE < JS_OBJECT_TYPE);
STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE);
ldrb(scratch1, FieldMemOperand(current, Map::kInstanceTypeOffset));
cmp(scratch1, Operand(JS_OBJECT_TYPE));
b(lo, found);
ldr(scratch1, FieldMemOperand(current, Map::kBitField2Offset));
DecodeField<Map::ElementsKindBits>(scratch1);
cmp(scratch1, Operand(DICTIONARY_ELEMENTS));
b(eq, found);
ldr(current, FieldMemOperand(current, Map::kPrototypeOffset));
cmp(current, Operand(factory->null_value()));
CompareRoot(current, Heap::kNullValueRootIndex);
b(ne, &loop_again);
bind(&end);
}
......
......@@ -4397,21 +4397,29 @@ void MacroAssembler::JumpIfDictionaryInPrototypeChain(
Register scratch1,
Label* found) {
DCHECK(!AreAliased(object, scratch0, scratch1));
Factory* factory = isolate()->factory();
Register current = scratch0;
Label loop_again;
Label loop_again, end;
// Scratch contains elements pointer.
Mov(current, object);
Ldr(current, FieldMemOperand(current, HeapObject::kMapOffset));
Ldr(current, FieldMemOperand(current, Map::kPrototypeOffset));
CompareAndBranch(current, Heap::kNullValueRootIndex, eq, &end);
// Loop based on the map going up the prototype chain.
Bind(&loop_again);
Ldr(current, FieldMemOperand(current, HeapObject::kMapOffset));
STATIC_ASSERT(JS_PROXY_TYPE < JS_OBJECT_TYPE);
STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE);
CompareInstanceType(current, scratch1, JS_OBJECT_TYPE);
B(lo, found);
Ldrb(scratch1, FieldMemOperand(current, Map::kBitField2Offset));
DecodeField<Map::ElementsKindBits>(scratch1);
CompareAndBranch(scratch1, DICTIONARY_ELEMENTS, eq, found);
Ldr(current, FieldMemOperand(current, Map::kPrototypeOffset));
CompareAndBranch(current, Operand(factory->null_value()), ne, &loop_again);
CompareAndBranch(current, Heap::kNullValueRootIndex, ne, &loop_again);
Bind(&end);
}
......
......@@ -3178,14 +3178,22 @@ void MacroAssembler::JumpIfDictionaryInPrototypeChain(
DCHECK(!scratch1.is(scratch0));
Factory* factory = isolate()->factory();
Register current = scratch0;
Label loop_again;
Label loop_again, end;
// scratch contained elements pointer.
mov(current, object);
mov(current, FieldOperand(current, HeapObject::kMapOffset));
mov(current, FieldOperand(current, Map::kPrototypeOffset));
cmp(current, Immediate(factory->null_value()));
j(equal, &end);
// Loop based on the map going up the prototype chain.
bind(&loop_again);
mov(current, FieldOperand(current, HeapObject::kMapOffset));
STATIC_ASSERT(JS_PROXY_TYPE < JS_OBJECT_TYPE);
STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE);
CmpInstanceType(current, JS_OBJECT_TYPE);
j(below, found);
mov(scratch1, FieldOperand(current, Map::kBitField2Offset));
DecodeField<Map::ElementsKindBits>(scratch1);
cmp(scratch1, Immediate(DICTIONARY_ELEMENTS));
......@@ -3193,6 +3201,8 @@ void MacroAssembler::JumpIfDictionaryInPrototypeChain(
mov(current, FieldOperand(current, Map::kPrototypeOffset));
cmp(current, Immediate(factory->null_value()));
j(not_equal, &loop_again);
bind(&end);
}
......
......@@ -658,9 +658,12 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm,
__ ldrb(r4, FieldMemOperand(receiver_map, Map::kInstanceTypeOffset));
__ cmp(r4, Operand(JS_ARRAY_TYPE));
__ b(eq, &array);
// Check that the object is some kind of JSObject.
__ cmp(r4, Operand(FIRST_JS_OBJECT_TYPE));
__ b(lt, &slow);
// Check that the object is some kind of JS object EXCEPT JS Value type. In
// the case that the object is a value-wrapper object, we enter the runtime
// system to make sure that indexing into string objects works as intended.
STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE);
__ cmp(r4, Operand(JS_OBJECT_TYPE));
__ b(lo, &slow);
// Object case: Check key against length in the elements array.
__ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
......
......@@ -657,9 +657,12 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm,
Register instance_type = x10;
__ CompareInstanceType(receiver_map, instance_type, JS_ARRAY_TYPE);
__ B(eq, &array);
// Check that the object is some kind of JSObject.
__ Cmp(instance_type, FIRST_JS_OBJECT_TYPE);
__ B(lt, &slow);
// Check that the object is some kind of JS object EXCEPT JS Value type. In
// the case that the object is a value-wrapper object, we enter the runtime
// system to make sure that indexing into string objects works as intended.
STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE);
__ Cmp(instance_type, JS_OBJECT_TYPE);
__ B(lo, &slow);
// Object case: Check key against length in the elements array.
__ Ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
......
......@@ -157,10 +157,9 @@ static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
__ test_b(FieldOperand(map, Map::kBitFieldOffset),
(1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit));
__ j(not_zero, slow);
// Check that the object is some kind of JS object EXCEPT JS Value type.
// In the case that the object is a value-wrapper object,
// we enter the runtime system to make sure that indexing
// into string objects works as intended.
// Check that the object is some kind of JS object EXCEPT JS Value type. In
// the case that the object is a value-wrapper object, we enter the runtime
// system to make sure that indexing into string objects works as intended.
DCHECK(JS_OBJECT_TYPE > JS_VALUE_TYPE);
__ CmpInstanceType(map, JS_OBJECT_TYPE);
......@@ -539,8 +538,11 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm,
__ JumpIfNotSmi(key, &maybe_name_key);
__ CmpInstanceType(edi, JS_ARRAY_TYPE);
__ j(equal, &array);
// Check that the object is some kind of JSObject.
__ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE);
// Check that the object is some kind of JS object EXCEPT JS Value type. In
// the case that the object is a value-wrapper object, we enter the runtime
// system to make sure that indexing into string objects works as intended.
STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE);
__ CmpInstanceType(edi, JS_OBJECT_TYPE);
__ j(below, &slow);
// Object case: Check key against length in the elements array.
......
......@@ -656,8 +656,11 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm,
// Check if the object is a JS array or not.
__ lbu(t0, FieldMemOperand(receiver_map, Map::kInstanceTypeOffset));
__ Branch(&array, eq, t0, Operand(JS_ARRAY_TYPE));
// Check that the object is some kind of JSObject.
__ Branch(&slow, lt, t0, Operand(FIRST_JS_OBJECT_TYPE));
// Check that the object is some kind of JS object EXCEPT JS Value type. In
// the case that the object is a value-wrapper object, we enter the runtime
// system to make sure that indexing into string objects works as intended.
STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE);
__ Branch(&slow, lo, t0, Operand(JS_OBJECT_TYPE));
// Object case: Check key against length in the elements array.
__ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
......
......@@ -541,8 +541,11 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm,
__ CmpInstanceType(r9, JS_ARRAY_TYPE);
__ j(equal, &array);
// Check that the object is some kind of JSObject.
__ CmpInstanceType(r9, FIRST_JS_OBJECT_TYPE);
// Check that the object is some kind of JS object EXCEPT JS Value type. In
// the case that the object is a value-wrapper object, we enter the runtime
// system to make sure that indexing into string objects works as intended.
STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE);
__ CmpInstanceType(r9, JS_OBJECT_TYPE);
__ j(below, &slow);
// Object case: Check key against length in the elements array.
......
......@@ -5985,19 +5985,28 @@ void MacroAssembler::JumpIfDictionaryInPrototypeChain(
DCHECK(!scratch1.is(scratch0));
Factory* factory = isolate()->factory();
Register current = scratch0;
Label loop_again;
Label loop_again, end;
// Scratch contained elements pointer.
Move(current, object);
lw(current, FieldMemOperand(current, HeapObject::kMapOffset));
lw(current, FieldMemOperand(current, Map::kPrototypeOffset));
Branch(&end, eq, current, Operand(factory->null_value()));
// Loop based on the map going up the prototype chain.
bind(&loop_again);
lw(current, FieldMemOperand(current, HeapObject::kMapOffset));
lbu(scratch1, FieldMemOperand(current, Map::kInstanceTypeOffset));
STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE);
STATIC_ASSERT(JS_PROXY_TYPE < JS_OBJECT_TYPE);
Branch(found, lo, scratch1, Operand(JS_OBJECT_TYPE));
lb(scratch1, FieldMemOperand(current, Map::kBitField2Offset));
DecodeField<Map::ElementsKindBits>(scratch1);
Branch(found, eq, scratch1, Operand(DICTIONARY_ELEMENTS));
lw(current, FieldMemOperand(current, Map::kPrototypeOffset));
Branch(&loop_again, ne, current, Operand(factory->null_value()));
bind(&end);
}
......
......@@ -6338,10 +6338,10 @@ bool Map::DictionaryElementsInPrototypeChainOnly() {
}
for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) {
if (iter.GetCurrent()->IsJSProxy()) {
// Be conservative, don't walk into proxies.
return true;
}
// Be conservative, don't walk into proxies.
if (iter.GetCurrent()->IsJSProxy()) return true;
// String wrappers have non-configurable, non-writable elements.
if (iter.GetCurrent()->IsStringWrapper()) return true;
if (IsDictionaryElementsKind(
JSObject::cast(iter.GetCurrent())->map()->elements_kind())) {
......
......@@ -5044,13 +5044,21 @@ void MacroAssembler::JumpIfDictionaryInPrototypeChain(
DCHECK(!(scratch0.is(kScratchRegister) && scratch1.is(kScratchRegister)));
DCHECK(!scratch1.is(scratch0));
Register current = scratch0;
Label loop_again;
Label loop_again, end;
movp(current, object);
movp(current, FieldOperand(current, HeapObject::kMapOffset));
movp(current, FieldOperand(current, Map::kPrototypeOffset));
CompareRoot(current, Heap::kNullValueRootIndex);
j(equal, &end);
// Loop based on the map going up the prototype chain.
bind(&loop_again);
movp(current, FieldOperand(current, HeapObject::kMapOffset));
STATIC_ASSERT(JS_PROXY_TYPE < JS_OBJECT_TYPE);
STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE);
CmpInstanceType(current, JS_OBJECT_TYPE);
j(below, found);
movp(scratch1, FieldOperand(current, Map::kBitField2Offset));
DecodeField<Map::ElementsKindBits>(scratch1);
cmpp(scratch1, Immediate(DICTIONARY_ELEMENTS));
......@@ -5058,6 +5066,8 @@ void MacroAssembler::JumpIfDictionaryInPrototypeChain(
movp(current, FieldOperand(current, Map::kPrototypeOffset));
CompareRoot(current, Heap::kNullValueRootIndex);
j(not_equal, &loop_again);
bind(&end);
}
......
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(function () {
var o = new String("ab");
function store(o, i, v) { o[i] = v; }
function load(o, i) { return o[i]; }
// Initialize the IC.
store(o, 2, 10);
load(o, 2);
store(o, 0, 100);
assertEquals("a", load(o, 0));
})();
(function () {
var o = {__proto__: new String("ab")};
function store(o, i, v) { o[i] = v; }
function load(o, i) { return o[i]; }
// Initialize the IC.
store(o, 2, 10);
load(o, 2);
store(o, 0, 100);
assertEquals("a", load(o, 0));
})();
(function () {
"use strict";
var o = {__proto__: {}};
function store(o, i, v) { o[i] = v; }
// Initialize the IC.
store(o, 0, 100);
o.__proto__.__proto__ = new String("bla");
assertThrows(function () { store(o, 1, 100) });
})();
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