Commit 73529a7d authored by verwaest@chromium.org's avatar verwaest@chromium.org

Support loads from primitive values.

This also changes load computation to use HeapTypes rather than Maps.
TODO: move conversion between maps and heaptypes earlier in the process, already in the oracle.

BUG=
R=dcarney@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18938 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 0c2c9ece
......@@ -91,10 +91,19 @@ static V8_INLINE bool CheckForName(Handle<String> name,
}
bool Accessors::IsJSObjectFieldAccessor(
Handle<Map> map, Handle<String> name,
int* object_offset) {
Isolate* isolate = map->GetIsolate();
bool Accessors::IsJSObjectFieldAccessor(Handle<HeapType> type,
Handle<String> name,
int* object_offset) {
Isolate* isolate = name->GetIsolate();
if (type->Is(HeapType::String())) {
return CheckForName(name, isolate->heap()->length_string(),
String::kLengthOffset, object_offset);
}
if (!type->IsClass()) return false;
Handle<Map> map = type->AsClass();
switch (map->instance_type()) {
case JS_ARRAY_TYPE:
return
......@@ -122,14 +131,8 @@ bool Accessors::IsJSObjectFieldAccessor(
JSDataView::kByteOffsetOffset, object_offset) ||
CheckForName(name, isolate->heap()->buffer_string(),
JSDataView::kBufferOffset, object_offset);
default: {
if (map->instance_type() < FIRST_NONSTRING_TYPE) {
return
CheckForName(name, isolate->heap()->length_string(),
String::kLengthOffset, object_offset);
}
default:
return false;
}
}
}
......
......@@ -89,8 +89,7 @@ class Accessors : public AllStatic {
// Returns true for properties that are accessors to object fields.
// If true, *object_offset contains offset of object field.
static bool IsJSObjectFieldAccessor(
Handle<Map> map, Handle<String> name,
int* object_offset);
Handle<HeapType> map, Handle<String> name, int* object_offset);
private:
......
......@@ -4269,6 +4269,9 @@ class HIsStringAndBranch V8_FINAL : public HUnaryControlInstruction {
DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch)
protected:
virtual int RedefinedOperandIndex() { return 0; }
private:
HIsStringAndBranch(HValue* value,
HBasicBlock* true_target = NULL,
......@@ -4291,6 +4294,7 @@ class HIsSmiAndBranch V8_FINAL : public HUnaryControlInstruction {
protected:
virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
virtual int RedefinedOperandIndex() { return 0; }
private:
HIsSmiAndBranch(HValue* value,
......
This diff is collapsed.
......@@ -2256,9 +2256,12 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
class PropertyAccessInfo {
public:
PropertyAccessInfo(Isolate* isolate, Handle<Map> map, Handle<String> name)
: lookup_(isolate),
map_(map),
PropertyAccessInfo(HOptimizedGraphBuilder* builder,
Handle<HeapType> type,
Handle<String> name)
: lookup_(builder->isolate()),
builder_(builder),
type_(type),
name_(name),
access_(HObjectAccess::ForMap()) { }
......@@ -2275,32 +2278,48 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
// PropertyAccessInfo is built for types->first().
bool CanLoadAsMonomorphic(SmallMapList* types);
Handle<Map> map() {
if (type_->Is(HeapType::Number())) {
Context* context = current_info()->closure()->context();
context = context->native_context();
return handle(context->number_function()->initial_map());
} else if (type_->Is(HeapType::String())) {
Context* context = current_info()->closure()->context();
context = context->native_context();
return handle(context->string_function()->initial_map());
} else {
return type_->AsClass();
}
}
Handle<HeapType> type() const { return type_; }
Handle<String> name() const { return name_; }
bool IsJSObjectFieldAccessor() {
int offset; // unused
return Accessors::IsJSObjectFieldAccessor(map_, name_, &offset);
return Accessors::IsJSObjectFieldAccessor(type_, name_, &offset);
}
bool GetJSObjectFieldAccess(HObjectAccess* access) {
if (IsStringLength()) {
*access = HObjectAccess::ForStringLength();
return true;
} else if (IsArrayLength()) {
*access = HObjectAccess::ForArrayLength(map_->elements_kind());
if (IsArrayLength()) {
*access = HObjectAccess::ForArrayLength(map()->elements_kind());
return true;
} else {
int offset;
if (Accessors::IsJSObjectFieldAccessor(map_, name_, &offset)) {
}
int offset;
if (Accessors::IsJSObjectFieldAccessor(type_, name_, &offset)) {
if (type_->Is(HeapType::String())) {
ASSERT(name_->Equals(isolate()->heap()->length_string()));
*access = HObjectAccess::ForStringLength();
} else {
*access = HObjectAccess::ForJSObjectOffset(offset);
return true;
}
return false;
return true;
}
return false;
}
bool has_holder() { return !holder_.is_null(); }
LookupResult* lookup() { return &lookup_; }
Handle<Map> map() { return map_; }
Handle<JSObject> holder() { return holder_; }
Handle<JSFunction> accessor() { return accessor_; }
Handle<Object> constant() { return constant_; }
......@@ -2308,14 +2327,10 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
private:
Isolate* isolate() { return lookup_.isolate(); }
bool IsStringLength() {
return map_->instance_type() < FIRST_NONSTRING_TYPE &&
name_->Equals(isolate()->heap()->length_string());
}
CompilationInfo* current_info() { return builder_->current_info(); }
bool IsArrayLength() {
return map_->instance_type() == JS_ARRAY_TYPE &&
return map()->instance_type() == JS_ARRAY_TYPE &&
name_->Equals(isolate()->heap()->length_string());
}
......@@ -2330,7 +2345,8 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
}
LookupResult lookup_;
Handle<Map> map_;
HOptimizedGraphBuilder* builder_;
Handle<HeapType> type_;
Handle<String> name_;
Handle<JSObject> holder_;
Handle<JSFunction> accessor_;
......@@ -2340,7 +2356,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
HInstruction* BuildLoadMonomorphic(PropertyAccessInfo* info,
HValue* object,
HInstruction* checked_object,
HValue* checked_object,
BailoutId ast_id,
BailoutId return_id,
bool can_inline_accessor = true);
......
......@@ -1208,9 +1208,9 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
// Use simple field loads for some well-known callback properties.
if (object->IsJSObject()) {
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
Handle<Map> map(receiver->map());
Handle<HeapType> type = IC::MapToType(handle(receiver->map()));
int object_offset;
if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) {
if (Accessors::IsJSObjectFieldAccessor(type, name, &object_offset)) {
return SimpleFieldLoad(object_offset / kPointerSize);
}
}
......
// Copyright 2014 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// When calling user-defined accessors on strings, booleans or
// numbers, we should create a wrapper object in classic-mode.
// Flags: --allow-natives-syntax
function test(object, prototype) {
var result;
Object.defineProperty(prototype, "nonstrict", {
get: function() { result = this; },
set: function(v) { result = this; }
});
Object.defineProperty(prototype, "strict", {
get: function() { "use strict"; result = this; },
set: function(v) { "use strict"; result = this; }
});
(function() {
function nonstrict(s) {
return s.nonstrict;
}
function strict(s) {
return s.strict;
}
nonstrict(object);
nonstrict(object);
%OptimizeFunctionOnNextCall(nonstrict);
result = undefined;
nonstrict(object);
assertEquals("object", typeof result);
strict(object);
strict(object);
%OptimizeFunctionOnNextCall(strict);
result = undefined;
strict(object);
assertEquals(typeof object, typeof result);
})();
(function() {
function nonstrict(s) {
return s.nonstrict = 10;
}
function strict(s) {
return s.strict = 10;
}
nonstrict(object);
nonstrict(object);
%OptimizeFunctionOnNextCall(nonstrict);
result = undefined;
nonstrict(object);
// TODO(1475): Support storing to primitive values.
// This should return "object" once storing to primitive values is
// supported.
assertEquals("undefined", typeof result);
strict(object);
strict(object);
%OptimizeFunctionOnNextCall(strict);
result = undefined;
strict(object);
// TODO(1475): Support storing to primitive values.
// This should return "object" once storing to primitive values is
// supported.
assertEquals("undefined", typeof result);
})();
}
test(1, Number.prototype);
test("string", String.prototype);
test(true, Boolean.prototype);
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