Abort("EmitLoadRegister: Unsupported double immediate.");
} else {
ASSERT(r.IsTagged());
- if (literal->IsSmi()) {
- __ mov(scratch, Operand(literal));
- } else {
- __ LoadHeapObject(scratch, Handle<HeapObject>::cast(literal));
- }
+ __ LoadObject(scratch, literal);
}
return scratch;
} else if (op->IsStackSlot() || op->IsArgument()) {
void LCodeGen::DoConstantT(LConstantT* instr) {
Handle<Object> value = instr->value();
AllowDeferredHandleDereference smi_check;
- if (value->IsSmi()) {
- __ mov(ToRegister(instr->result()), Operand(value));
- } else {
- __ LoadHeapObject(ToRegister(instr->result()),
- Handle<HeapObject>::cast(value));
- }
+ __ LoadObject(ToRegister(instr->result()), value);
}
__ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
__ ldr(result, FieldMemOperand(result, offset + FixedArray::kHeaderSize));
}
- } else if (lookup.IsConstantFunction()) {
- Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type));
- __ LoadHeapObject(result, function);
+ } else if (lookup.IsConstant()) {
+ Handle<Object> constant(lookup.GetConstantFromMap(*type), isolate());
+ __ LoadObject(result, constant);
} else {
// Negative lookup.
// Check prototypes.
Representation representation = details.representation();
ASSERT(!representation.IsNone());
- if (details.type() == CONSTANT_FUNCTION) {
- Handle<HeapObject> constant(
- HeapObject::cast(descriptors->GetValue(descriptor)));
- __ LoadHeapObject(scratch1, constant);
+ if (details.type() == CONSTANT) {
+ Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate());
+ __ LoadObject(scratch1, constant);
__ cmp(value_reg, scratch1);
__ b(ne, miss_label);
} else if (FLAG_track_fields && representation.IsSmi()) {
OMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
- if (details.type() == CONSTANT_FUNCTION) {
+ if (details.type() == CONSTANT) {
ASSERT(value_reg.is(r0));
__ Ret();
return;
}
-void BaseLoadStubCompiler::GenerateLoadConstant(Handle<JSFunction> value) {
+void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
// Return the constant value.
- __ LoadHeapObject(r0, value);
+ __ LoadObject(r0, value);
__ Ret();
}
Handle<Code> code = CompileCustomCall(object, holder,
Handle<Cell>::null(),
function, Handle<String>::cast(name),
- Code::CONSTANT_FUNCTION);
+ Code::CONSTANT);
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
type->LookupDescriptor(NULL, *name, &lookup);
if (lookup.IsFound()) {
switch (lookup.type()) {
- case CONSTANT_FUNCTION:
+ case CONSTANT: {
// We surely know the target for a constant function.
- target_ =
- Handle<JSFunction>(lookup.GetConstantFunctionFromMap(*type));
- return true;
+ Handle<Object> constant(lookup.GetConstantFromMap(*type),
+ type->GetIsolate());
+ if (constant->IsJSFunction()) {
+ target_ = Handle<JSFunction>::cast(constant);
+ return true;
+ }
+ // Fall through.
+ }
case NORMAL:
case FIELD:
case CALLBACKS:
JSObject::SetLocalPropertyIgnoreAttributes(
result, factory->length_string(),
factory->undefined_value(), DONT_ENUM,
- Object::FORCE_TAGGED));
+ Object::FORCE_TAGGED, JSReceiver::FORCE_FIELD));
CHECK_NOT_EMPTY_HANDLE(isolate,
JSObject::SetLocalPropertyIgnoreAttributes(
result, factory->callee_string(),
factory->undefined_value(), DONT_ENUM,
- Object::FORCE_TAGGED));
+ Object::FORCE_TAGGED, JSReceiver::FORCE_FIELD));
#ifdef DEBUG
LookupResult lookup(isolate);
to, key, value, details.attributes()));
break;
}
- case CONSTANT_FUNCTION: {
+ case CONSTANT: {
HandleScope inner(isolate());
Handle<Name> key = Handle<Name>(descs->GetKey(i));
- Handle<JSFunction> fun =
- Handle<JSFunction>(descs->GetConstantFunction(i));
+ Handle<Object> constant(descs->GetConstant(i), isolate());
CHECK_NOT_EMPTY_HANDLE(isolate(),
JSObject::SetLocalPropertyIgnoreAttributes(
- to, key, fun, details.attributes()));
+ to, key, constant, details.attributes()));
break;
}
case CALLBACKS: {
}
break;
}
- case CONSTANT_FUNCTION:
+ case CONSTANT:
SetPropertyReference(
js_obj, entry,
- descs->GetKey(i), descs->GetConstantFunction(i));
+ descs->GetKey(i), descs->GetConstant(i));
break;
case CALLBACKS:
ExtractAccessorPairProperty(
types_.Add(types->at(i), zone);
break;
}
- case CONSTANT_FUNCTION:
+ case CONSTANT:
types_.Add(types->at(i), zone);
break;
case CALLBACKS:
}
// Handle a load of a constant known function.
- if (lookup.IsConstantFunction()) {
+ if (lookup.IsConstant()) {
AddCheckMap(object, map);
- Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map));
- return new(zone()) HConstant(function);
+ Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate());
+ return new(zone()) HConstant(constant);
}
// Handle a load from a known field somewhere in the prototype chain.
}
// Handle a load of a constant function somewhere in the prototype chain.
- if (lookup.IsConstantFunction()) {
+ if (lookup.IsConstant()) {
Handle<JSObject> prototype(JSObject::cast(map->prototype()));
Handle<JSObject> holder(lookup.holder());
Handle<Map> holder_map(holder->map());
AddCheckMap(object, map);
Add<HCheckPrototypeMaps>(prototype, holder, zone(), top_info());
- Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map));
- return new(zone()) HConstant(function);
+ Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate());
+ return new(zone()) HConstant(constant);
}
// No luck, do a generic load.
Register reg = ToRegister(instr->result());
Handle<Object> handle = instr->value();
AllowDeferredHandleDereference smi_check;
- if (handle->IsHeapObject()) {
- __ LoadHeapObject(reg, Handle<HeapObject>::cast(handle));
- } else {
- __ Set(reg, Immediate(handle));
- }
+ __ LoadObject(reg, handle);
}
}
-void LCodeGen::EmitLoadFieldOrConstantFunction(Register result,
- Register object,
- Handle<Map> type,
- Handle<String> name,
- LEnvironment* env) {
+void LCodeGen::EmitLoadFieldOrConstant(Register result,
+ Register object,
+ Handle<Map> type,
+ Handle<String> name,
+ LEnvironment* env) {
LookupResult lookup(isolate());
type->LookupDescriptor(NULL, *name, &lookup);
ASSERT(lookup.IsFound() || lookup.IsCacheable());
__ mov(result, FieldOperand(object, JSObject::kPropertiesOffset));
__ mov(result, FieldOperand(result, offset + FixedArray::kHeaderSize));
}
- } else if (lookup.IsConstantFunction()) {
- Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type));
- __ LoadHeapObject(result, function);
+ } else if (lookup.IsConstant()) {
+ Handle<Object> constant(lookup.GetConstantFromMap(*type), isolate());
+ __ LoadObject(result, constant);
} else {
// Negative lookup.
// Check prototypes.
if (map->HasElementsTransition()) return false;
LookupResult lookup(isolate);
map->LookupDescriptor(NULL, *name, &lookup);
- return lookup.IsField() || lookup.IsConstantFunction();
+ return lookup.IsField() || lookup.IsConstant();
}
if (last && !need_generic) {
DeoptimizeIf(not_equal, instr->environment());
__ bind(&check_passed);
- EmitLoadFieldOrConstantFunction(
- result, object, map, name, instr->environment());
+ EmitLoadFieldOrConstant(result, object, map, name, instr->environment());
} else {
Label next;
bool compact = all_are_compact ? true :
CompactEmit(instr->hydrogen()->types(), name, i, isolate());
__ j(not_equal, &next, compact ? Label::kNear : Label::kFar);
__ bind(&check_passed);
- EmitLoadFieldOrConstantFunction(
- result, object, map, name, instr->environment());
+ EmitLoadFieldOrConstant(result, object, map, name, instr->environment());
__ jmp(&done, all_are_compact ? Label::kNear : Label::kFar);
__ bind(&next);
}
// Caller should branch on equal condition.
void EmitIsConstructCall(Register temp);
- void EmitLoadFieldOrConstantFunction(Register result,
- Register object,
- Handle<Map> type,
- Handle<String> name,
- LEnvironment* env);
+ void EmitLoadFieldOrConstant(Register result,
+ Register object,
+ Handle<Map> type,
+ Handle<String> name,
+ LEnvironment* env);
// Emits optimized code to deep-copy the contents of statically known
// object graphs (e.g. object literal boilerplate).
Representation representation = details.representation();
ASSERT(!representation.IsNone());
- if (details.type() == CONSTANT_FUNCTION) {
- Handle<HeapObject> constant(
- HeapObject::cast(descriptors->GetValue(descriptor)));
- __ LoadHeapObject(scratch1, constant);
- __ cmp(value_reg, scratch1);
+ if (details.type() == CONSTANT) {
+ Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate());
+ __ CmpObject(value_reg, constant);
__ j(not_equal, miss_label);
} else if (FLAG_track_fields && representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
OMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
- if (details.type() == CONSTANT_FUNCTION) {
+ if (details.type() == CONSTANT) {
ASSERT(value_reg.is(eax));
__ ret(0);
return;
}
-void BaseLoadStubCompiler::GenerateLoadConstant(Handle<JSFunction> value) {
+void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
// Return the constant value.
- __ LoadHeapObject(eax, value);
+ __ LoadObject(eax, value);
__ ret(0);
}
Handle<Code> code = CompileCustomCall(object, holder,
Handle<Cell>::null(),
function, Handle<String>::cast(name),
- Code::CONSTANT_FUNCTION);
+ Code::CONSTANT);
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
Handle<Object> object,
Code::ExtraICState* extra_ic_state) {
ASSERT(kind_ == Code::CALL_IC);
- if (lookup->type() != CONSTANT_FUNCTION) return false;
+ if (!lookup->IsConstantFunction()) return false;
JSFunction* function = lookup->GetConstantFunction();
if (!function->shared()->HasBuiltinFunctionId()) return false;
return isolate()->stub_cache()->ComputeCallField(
argc, kind_, extra_state, name, object, holder, index);
}
- case CONSTANT_FUNCTION: {
+ case CONSTANT: {
+ if (!lookup->IsConstantFunction()) return Handle<Code>::null();
// Get the constant function and compute the code stub for this
// call; used for rewriting to monomorphic state and making sure
// that the code stub is in the stub cache.
return isolate()->stub_cache()->ComputeLoadField(
name, receiver, holder,
lookup->GetFieldIndex(), lookup->representation());
- case CONSTANT_FUNCTION: {
- Handle<JSFunction> constant(lookup->GetConstantFunction());
+ case CONSTANT: {
+ Handle<Object> constant(lookup->GetConstant(), isolate());
+ // TODO(2803): Don't compute a stub for cons strings because they cannot
+ // be embedded into code.
+ if (constant->IsConsString()) return Handle<Code>::null();
return isolate()->stub_cache()->ComputeLoadConstant(
name, receiver, holder, constant);
}
return isolate()->stub_cache()->ComputeKeyedLoadField(
name, receiver, holder,
lookup->GetFieldIndex(), lookup->representation());
- case CONSTANT_FUNCTION: {
- Handle<JSFunction> constant(lookup->GetConstantFunction(), isolate());
+ case CONSTANT: {
+ Handle<Object> constant(lookup->GetConstant(), isolate());
+ // TODO(2803): Don't compute a stub for cons strings because they cannot
+ // be embedded into code.
+ if (constant->IsConsString()) return Handle<Code>::null();
return isolate()->stub_cache()->ComputeKeyedLoadConstant(
name, receiver, holder, constant);
}
ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined());
return isolate()->stub_cache()->ComputeStoreInterceptor(
name, receiver, strict_mode);
- case CONSTANT_FUNCTION:
+ case CONSTANT:
break;
case TRANSITION: {
// Explicitly pass in the receiver map since LookupForWrite may have
// fall through.
}
case NORMAL:
- case CONSTANT_FUNCTION:
+ case CONSTANT:
case CALLBACKS:
case INTERCEPTOR:
// Always rewrite to the generic case so that we do not
var PropertyType = {};
PropertyType.Normal = 0;
PropertyType.Field = 1;
-PropertyType.ConstantFunction = 2;
+PropertyType.Constant = 2;
PropertyType.Callbacks = 3;
PropertyType.Handler = 4;
PropertyType.Interceptor = 5;
}
-JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) {
- return JSFunction::cast(GetValue(descriptor_number));
+Object* DescriptorArray::GetConstant(int descriptor_number) {
+ return GetValue(descriptor_number);
}
details.representation().IsHeapObject()) {
return true;
}
- if (FLAG_track_fields && details.type() == CONSTANT_FUNCTION) {
+ if (FLAG_track_fields && details.type() == CONSTANT) {
return true;
}
}
PrintF(out, " (field at offset %d)\n", index);
break;
}
- case CONSTANT_FUNCTION:
- descs->GetConstantFunction(i)->ShortPrint(out);
- PrintF(out, " (constant function)\n");
+ case CONSTANT:
+ descs->GetConstant(i)->ShortPrint(out);
+ PrintF(out, " (constant)\n");
break;
case CALLBACKS:
descs->GetCallbacksObject(i)->ShortPrint(out);
PrintF(out, " (transition to field)\n");
break;
}
- case CONSTANT_FUNCTION:
- PrintF(out, " (transition to constant function)\n");
+ case CONSTANT:
+ PrintF(out, " (transition to constant)\n");
break;
case CALLBACKS:
PrintF(out, " (transition to callback)\n");
PrintF(out, " (transition to field)\n");
break;
}
- case CONSTANT_FUNCTION:
- PrintF(out, " (transition to constant function)\n");
+ case CONSTANT:
+ PrintF(out, " (transition to constant)\n");
break;
case CALLBACKS:
PrintF(out, " (transition to callback)\n");
}
case NORMAL:
case FIELD:
- case CONSTANT_FUNCTION: {
+ case CONSTANT: {
// Search ALL_CAN_READ accessors in prototype chain.
LookupResult r(GetIsolate());
result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
case NORMAL:
case FIELD:
- case CONSTANT_FUNCTION: {
+ case CONSTANT: {
if (!continue_search) break;
// Search ALL_CAN_READ accessors in prototype chain.
LookupResult r(GetIsolate());
ASSERT(!value->IsTheHole() || result->IsReadOnly());
return value->IsTheHole() ? heap->undefined_value() : value;
}
- case CONSTANT_FUNCTION:
- return result->GetConstantFunction();
+ case CONSTANT:
+ return result->GetConstant();
case CALLBACKS:
return result->holder()->GetPropertyWithCallback(
receiver, result->GetCallbackObject(), name);
}
-MaybeObject* JSObject::AddConstantFunctionProperty(
+MaybeObject* JSObject::AddConstantProperty(
Name* name,
- JSFunction* function,
+ Object* constant,
PropertyAttributes attributes) {
- // Allocate new instance descriptors with (name, function) added
- ConstantFunctionDescriptor d(name, function, attributes);
+ // Allocate new instance descriptors with (name, constant) added
+ ConstantDescriptor d(name, constant, attributes);
TransitionFlag flag =
// Do not add transitions to global objects.
if (!maybe_new_map->To(&new_map)) return maybe_new_map;
set_map(new_map);
- return function;
+ return constant;
}
StrictModeFlag strict_mode,
JSReceiver::StoreFromKeyed store_mode,
ExtensibilityCheck extensibility_check,
- ValueType value_type) {
+ ValueType value_type,
+ StoreMode mode) {
ASSERT(!IsJSGlobalProxy());
Map* map_of_this = map();
Heap* heap = GetHeap();
// Ensure the descriptor array does not get too big.
if (map_of_this->NumberOfOwnDescriptors() <
DescriptorArray::kMaxNumberOfDescriptors) {
+ // TODO(verwaest): Support other constants.
+ // if (mode == ALLOW_AS_CONSTANT &&
+ // !value->IsTheHole() &&
+ // !value->IsConsString()) {
if (value->IsJSFunction()) {
- result = AddConstantFunctionProperty(name,
- JSFunction::cast(value),
- attributes);
+ result = AddConstantProperty(name, value, attributes);
} else {
result = AddFastProperty(
name, value, attributes, store_mode, value_type);
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
- ExtensibilityCheck extensibility_check) {
+ ExtensibilityCheck extensibility_check,
+ StoreMode mode) {
// Check local property, ignore interceptor.
LookupResult result(GetIsolate());
LocalLookupRealNamedProperty(name, &result);
if (done) return result_object;
// Add a new real property.
return AddProperty(name, value, attributes, strict_mode,
- MAY_BE_STORE_FROM_KEYED, extensibility_check);
+ MAY_BE_STORE_FROM_KEYED, extensibility_check,
+ OPTIMAL_REPRESENTATION, mode);
}
PropertyDetails details = new_descriptors->GetDetails(i);
if (details.type() != FIELD) continue;
PropertyDetails old_details = old_descriptors->GetDetails(i);
- ASSERT(old_details.type() == CONSTANT_FUNCTION ||
+ ASSERT(old_details.type() == CONSTANT ||
old_details.type() == FIELD);
- Object* value = old_details.type() == CONSTANT_FUNCTION
+ Object* value = old_details.type() == CONSTANT
? old_descriptors->GetValue(i)
: RawFastPropertyAt(old_descriptors->GetFieldIndex(i));
if (FLAG_track_double_fields &&
switch (result.type()) {
case NORMAL:
case FIELD:
- case CONSTANT_FUNCTION:
+ case CONSTANT:
*done = result.IsReadOnly();
break;
case INTERCEPTOR: {
result = *value;
break;
}
- case CONSTANT_FUNCTION:
- // Only replace the function if necessary.
- if (*value == lookup->GetConstantFunction()) return *value;
+ case CONSTANT:
+ // Only replace the constant if necessary.
+ if (*value == lookup->GetConstant()) return *value;
// Preserve the attributes of this existing property.
attributes = lookup->GetAttributes();
- result =
- lookup->holder()->ConvertDescriptorToField(*name, *value, attributes);
+ result = lookup->holder()->ConvertDescriptorToField(
+ *name, *value, attributes);
break;
case CALLBACKS: {
Object* callback_object = lookup->GetCallbackObject();
result = lookup->holder()->ConvertDescriptorToField(
*name, *value, attributes);
} else {
- ASSERT(details.type() == CONSTANT_FUNCTION);
+ ASSERT(details.type() == CONSTANT);
- Object* constant_function = descriptors->GetValue(descriptor);
- if (constant_function == *value) {
+ Object* constant = descriptors->GetValue(descriptor);
+ if (constant == *value) {
// If the same constant function is being added we can simply
// transition to the target map.
lookup->holder()->set_map(transition_map);
- result = constant_function;
+ result = constant;
} else {
// Otherwise, replace with a map transition to a new map with a FIELD,
// even if the value is a constant function.
Handle<Name> key,
Handle<Object> value,
PropertyAttributes attributes,
- ValueType value_type) {
+ ValueType value_type,
+ StoreMode mode) {
CALL_HEAP_FUNCTION(
object->GetIsolate(),
object->SetLocalPropertyIgnoreAttributes(
- *key, *value, attributes, value_type),
+ *key, *value, attributes, value_type, mode),
Object);
}
Name* name_raw,
Object* value_raw,
PropertyAttributes attributes,
- ValueType value_type) {
+ ValueType value_type,
+ StoreMode mode) {
// Make sure that the top context does not change when doing callbacks or
// interceptor calls.
AssertNoContextChange ncc;
name_raw,
value_raw,
attributes,
- value_type);
+ value_type,
+ mode);
}
// Check for accessor in prototype chain removed here in clone.
// Neither properties nor transitions found.
return AddProperty(
name_raw, value_raw, attributes, kNonStrictMode,
- MAY_BE_STORE_FROM_KEYED, PERFORM_EXTENSIBILITY_CHECK, value_type);
+ MAY_BE_STORE_FROM_KEYED, PERFORM_EXTENSIBILITY_CHECK, value_type, mode);
}
// From this point on everything needs to be handlified.
result = *value;
break;
}
- case CONSTANT_FUNCTION:
+ case CONSTANT:
// Only replace the function if necessary.
- if (*value != lookup.GetConstantFunction()) {
+ if (*value != lookup.GetConstant()) {
// Preserve the attributes of this existing property.
attributes = lookup.GetAttributes();
result = self->ConvertDescriptorToField(*name, *value, attributes);
} else if (details.type() == CALLBACKS) {
result = self->ConvertDescriptorToField(*name, *value, attributes);
} else {
- ASSERT(details.type() == CONSTANT_FUNCTION);
+ ASSERT(details.type() == CONSTANT);
// Replace transition to CONSTANT FUNCTION with a map transition to a
// new map with a FIELD, even if the value is a function.
switch (lookup->type()) {
case NORMAL: // fall through
case FIELD:
- case CONSTANT_FUNCTION:
+ case CONSTANT:
case CALLBACKS:
return lookup->GetAttributes();
case HANDLER: {
for (int i = 0; i < real_size; i++) {
PropertyDetails details = descs->GetDetails(i);
switch (details.type()) {
- case CONSTANT_FUNCTION: {
+ case CONSTANT: {
PropertyDetails d = PropertyDetails(
details.attributes(), NORMAL, i + 1);
- Object* value = descs->GetConstantFunction(i);
+ Object* value = descs->GetConstant(i);
MaybeObject* maybe_dictionary =
dictionary->Add(descs->GetKey(i), value, d);
if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
hashtable,
DONT_ENUM,
kNonStrictMode,
- OMIT_EXTENSIBILITY_CHECK);
+ OMIT_EXTENSIBILITY_CHECK,
+ FORCE_FIELD);
if (store_result->IsFailure()) return store_result;
return hashtable;
}
value,
DONT_ENUM,
kNonStrictMode,
- OMIT_EXTENSIBILITY_CHECK);
+ OMIT_EXTENSIBILITY_CHECK,
+ FORCE_FIELD);
if (store_result->IsFailure()) return store_result;
return this;
}
} else if (property == value) {
return descs->GetKey(i);
}
- } else if (descs->GetType(i) == CONSTANT_FUNCTION) {
- if (descs->GetConstantFunction(i) == value) {
+ } else if (descs->GetType(i) == CONSTANT) {
+ if (descs->GetConstant(i) == value) {
return descs->GetKey(i);
}
}
PropertyDetails other_details = other->GetDetails(descriptor);
if (details.type() == FIELD || other_details.type() == FIELD ||
- (details.type() == CONSTANT_FUNCTION &&
- other_details.type() == CONSTANT_FUNCTION &&
+ (details.type() == CONSTANT &&
+ other_details.type() == CONSTANT &&
GetValue(descriptor) != other->GetValue(descriptor))) {
Representation representation =
details.representation().generalize(other_details.representation());
if (!other_details.representation().fits_into(details.representation())) {
return false;
}
- if (details.type() == CONSTANT_FUNCTION) {
- if (other_details.type() != CONSTANT_FUNCTION) return false;
+ if (details.type() == CONSTANT) {
+ if (other_details.type() != CONSTANT) return false;
if (GetValue(descriptor) != other->GetValue(descriptor)) return false;
}
}
switch (type) {
case NORMAL: return "NORMAL";
case FIELD: return "FIELD";
- case CONSTANT_FUNCTION: return "CONSTANT_FUNCTION";
+ case CONSTANT: return "CONSTANT";
case CALLBACKS: return "CALLBACKS";
case INTERCEPTOR: return "INTERCEPTOR";
case MAP_TRANSITION: return "MAP_TRANSITION";
PropertyType type = details.type();
if (value->IsJSFunction()) {
- ConstantFunctionDescriptor d(key,
- JSFunction::cast(value),
- details.attributes());
+ ConstantDescriptor d(key, value, details.attributes());
descriptors->Set(enumeration_index - 1, &d, witness);
} else if (type == NORMAL) {
if (current_offset < inobject_props) {
Handle<Object> value) {
Isolate* isolate = cell->GetIsolate();
Handle<Type> old_type(cell->type(), isolate);
+ // TODO(2803): Do not track ConsString as constant because they cannot be
+ // embedded into code.
Handle<Type> new_type(value->IsConsString() || value->IsTheHole()
? Type::Any()
: Type::Constant(value, isolate), isolate);
CERTAINLY_NOT_STORE_FROM_KEYED
};
+ // Indicates whether a value can be loaded as a constant.
+ enum StoreMode {
+ ALLOW_AS_CONSTANT,
+ FORCE_FIELD
+ };
+
// Internal properties (e.g. the hidden properties dictionary) might
// be added even though the receiver is non-extensible.
enum ExtensibilityCheck {
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode,
- ExtensibilityCheck extensibility_check);
+ ExtensibilityCheck extensibility_check,
+ StoreMode mode = ALLOW_AS_CONSTANT);
static Handle<Object> SetLocalPropertyIgnoreAttributes(
Handle<JSObject> object,
Handle<Name> key,
Handle<Object> value,
PropertyAttributes attributes,
- ValueType value_type = OPTIMAL_REPRESENTATION);
+ ValueType value_type = OPTIMAL_REPRESENTATION,
+ StoreMode mode = ALLOW_AS_CONSTANT);
static inline Handle<String> ExpectedTransitionKey(Handle<Map> map);
static inline Handle<Map> ExpectedTransitionTarget(Handle<Map> map);
Name* key,
Object* value,
PropertyAttributes attributes,
- ValueType value_type = OPTIMAL_REPRESENTATION);
+ ValueType value_type = OPTIMAL_REPRESENTATION,
+ StoreMode mode = ALLOW_AS_CONSTANT);
// Retrieve a value in a normalized object given a lookup result.
// Handles the special representation of JS global objects.
// normal property is added instead, with a map transition.
// This avoids the creation of many maps with the same constant
// function, all orphaned.
- MUST_USE_RESULT MaybeObject* AddConstantFunctionProperty(
+ MUST_USE_RESULT MaybeObject* AddConstantProperty(
Name* name,
- JSFunction* function,
+ Object* constant,
PropertyAttributes attributes);
MUST_USE_RESULT MaybeObject* ReplaceSlowProperty(
StrictModeFlag strict_mode,
StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED,
ExtensibilityCheck extensibility_check = PERFORM_EXTENSIBILITY_CHECK,
- ValueType value_type = OPTIMAL_REPRESENTATION);
+ ValueType value_type = OPTIMAL_REPRESENTATION,
+ StoreMode mode = ALLOW_AS_CONSTANT);
// Convert the object to use the canonical dictionary
// representation. If the object is expected to have additional properties
inline PropertyDetails GetDetails(int descriptor_number);
inline PropertyType GetType(int descriptor_number);
inline int GetFieldIndex(int descriptor_number);
- inline JSFunction* GetConstantFunction(int descriptor_number);
+ inline Object* GetConstant(int descriptor_number);
inline Object* GetCallbacksObject(int descriptor_number);
inline AccessorDescriptor* GetCallbacks(int descriptor_number);
enum StubType {
NORMAL,
FIELD,
- CONSTANT_FUNCTION,
+ CONSTANT,
CALLBACKS,
INTERCEPTOR,
MAP_TRANSITION,
NORMAL = 0,
// Only in fast mode.
FIELD = 1,
- CONSTANT_FUNCTION = 2,
+ CONSTANT = 2,
CALLBACKS = 3,
// Only in lookup results, not in descriptors.
HANDLER = 4,
PrintF(out, " -type = normal\n");
PrintF(out, " -entry = %d", GetDictionaryEntry());
break;
- case CONSTANT_FUNCTION:
- PrintF(out, " -type = constant function\n");
- PrintF(out, " -function:\n");
- GetConstantFunction()->Print(out);
+ case CONSTANT:
+ PrintF(out, " -type = constant\n");
+ PrintF(out, " -value:\n");
+ GetConstant()->Print(out);
PrintF(out, "\n");
break;
case FIELD:
GetTransitionMap()->Print(out);
PrintF(out, "\n");
return;
- case CONSTANT_FUNCTION:
+ case CONSTANT:
PrintF(out, " -type = constant property transition\n");
PrintF(out, " -map:\n");
GetTransitionMap()->Print(out);
};
-class ConstantFunctionDescriptor: public Descriptor {
+class ConstantDescriptor: public Descriptor {
public:
- ConstantFunctionDescriptor(Name* key,
- JSFunction* function,
- PropertyAttributes attributes)
- : Descriptor(key, function, attributes, CONSTANT_FUNCTION,
- Representation::HeapObject()) {}
+ ConstantDescriptor(Name* key,
+ Object* value,
+ PropertyAttributes attributes)
+ : Descriptor(key, value, attributes, CONSTANT,
+ value->OptimalRepresentation()) {}
};
return details_.type() == NORMAL;
}
+ bool IsConstant() {
+ ASSERT(!(details_.type() == CONSTANT && !IsFound()));
+ return details_.type() == CONSTANT;
+ }
+
bool IsConstantFunction() {
- ASSERT(!(details_.type() == CONSTANT_FUNCTION && !IsFound()));
- return details_.type() == CONSTANT_FUNCTION;
+ return IsConstant() && GetValue()->IsJSFunction();
}
bool IsDontDelete() { return details_.IsDontDelete(); }
switch (type()) {
case FIELD:
case NORMAL:
- case CONSTANT_FUNCTION:
+ case CONSTANT:
return true;
case CALLBACKS: {
Object* callback = GetCallbackObject();
}
return value;
}
- case CONSTANT_FUNCTION:
- return GetConstantFunction();
+ case CONSTANT:
+ return GetConstant();
case CALLBACKS:
case HANDLER:
case INTERCEPTOR:
return IsTransition() && GetTransitionDetails(map).type() == FIELD;
}
- bool IsTransitionToConstantFunction(Map* map) {
- return IsTransition() &&
- GetTransitionDetails(map).type() == CONSTANT_FUNCTION;
+ bool IsTransitionToConstant(Map* map) {
+ return IsTransition() && GetTransitionDetails(map).type() == CONSTANT;
}
Map* GetTransitionMap() {
}
JSFunction* GetConstantFunction() {
- ASSERT(type() == CONSTANT_FUNCTION);
+ ASSERT(type() == CONSTANT);
return JSFunction::cast(GetValue());
}
+ Object* GetConstantFromMap(Map* map) {
+ ASSERT(type() == CONSTANT);
+ return GetValueFromMap(map);
+ }
+
JSFunction* GetConstantFunctionFromMap(Map* map) {
- ASSERT(type() == CONSTANT_FUNCTION);
- return JSFunction::cast(GetValueFromMap(map));
+ return JSFunction::cast(GetConstantFromMap(map));
+ }
+
+ Object* GetConstant() {
+ ASSERT(type() == CONSTANT);
+ return GetValue();
}
Object* GetCallbackObject() {
}
Handle<Object> result;
uint32_t element_index = 0;
+ JSReceiver::StoreMode mode = value->IsJSObject()
+ ? JSReceiver::FORCE_FIELD
+ : JSReceiver::ALLOW_AS_CONSTANT;
if (key->IsInternalizedString()) {
if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
// Array index as string (uint32).
Handle<String> name(String::cast(*key));
ASSERT(!name->AsArrayIndex(&element_index));
result = JSObject::SetLocalPropertyIgnoreAttributes(
- boilerplate, name, value, NONE);
+ boilerplate, name, value, NONE,
+ Object::OPTIMAL_REPRESENTATION, mode);
}
} else if (key->ToArrayIndex(&element_index)) {
// Array index (uint32).
Handle<String> name =
isolate->factory()->NewStringFromAscii(CStrVector(str));
result = JSObject::SetLocalPropertyIgnoreAttributes(
- boilerplate, name, value, NONE);
+ boilerplate, name, value, NONE,
+ Object::OPTIMAL_REPRESENTATION, mode);
}
// If setting the property on the boilerplate throws an
// exception, the exception is converted to an empty handle in
}
} else {
// Ignore re-initialization of constants that have already been
- // assigned a function value.
- ASSERT(lookup.IsReadOnly() && lookup.IsConstantFunction());
+ // assigned a constant value.
+ ASSERT(lookup.IsReadOnly() && lookup.IsConstant());
}
// Use the set value as the result of the operation.
return lookup.holder()->FastPropertyAt(
lookup.representation(),
lookup.GetFieldIndex().field_index());
- case CONSTANT_FUNCTION:
- return lookup.GetConstantFunction();
+ case CONSTANT:
+ return lookup.GetConstant();
case CALLBACKS:
case HANDLER:
case INTERCEPTOR:
}
return value;
}
- case CONSTANT_FUNCTION:
- return result->GetConstantFunction();
+ case CONSTANT:
+ return result->GetConstant();
case CALLBACKS: {
Object* structure = result->GetCallbackObject();
if (structure->IsForeign() || structure->IsAccessorInfo()) {
Handle<Code> StubCache::ComputeLoadConstant(Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
- Handle<JSFunction> value) {
+ Handle<Object> value) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
Handle<Code> handler = FindLoadHandler(
- name, receiver, stub_holder, Code::LOAD_IC, Code::CONSTANT_FUNCTION);
+ name, receiver, stub_holder, Code::LOAD_IC, Code::CONSTANT);
if (!handler.is_null()) return handler;
LoadStubCompiler compiler(isolate_);
Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<Name> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
- Handle<JSFunction> value) {
+ Handle<Object> value) {
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
Handle<Code> handler = FindLoadHandler(
name, receiver, stub_holder, Code::KEYED_LOAD_IC,
- Code::CONSTANT_FUNCTION);
+ Code::CONSTANT);
if (!handler.is_null()) return handler;
KeyedLoadStubCompiler compiler(isolate_);
}
Code::Flags flags = Code::ComputeMonomorphicFlags(
- kind, extra_state, Code::CONSTANT_FUNCTION, argc, cache_holder);
+ kind, extra_state, Code::CONSTANT, argc, cache_holder);
Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe);
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name,
- Handle<JSFunction> value) {
+ Handle<Object> value) {
Label success;
HandlerFrontend(object, receiver(), holder, name, &success);
__ bind(&success);
GenerateLoadConstant(value);
// Return the generated code.
- return GetCode(kind(), Code::CONSTANT_FUNCTION, name);
+ return GetCode(kind(), Code::CONSTANT, name);
}
if (function->shared()->name()->IsString()) {
function_name = Handle<String>(String::cast(function->shared()->name()));
}
- return GetCode(Code::CONSTANT_FUNCTION, function_name);
+ return GetCode(Code::CONSTANT, function_name);
}
CallOptimization::CallOptimization(LookupResult* lookup) {
if (lookup->IsFound() &&
lookup->IsCacheable() &&
- lookup->type() == CONSTANT_FUNCTION) {
+ lookup->IsConstantFunction()) {
// We only optimize constant function calls.
Initialize(Handle<JSFunction>(lookup->GetConstantFunction()));
} else {
Handle<Code> ComputeLoadConstant(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<JSFunction> value);
+ Handle<Object> value);
Handle<Code> ComputeLoadInterceptor(Handle<Name> name,
Handle<JSObject> object,
Handle<Code> ComputeKeyedLoadConstant(Handle<Name> name,
Handle<JSObject> object,
Handle<JSObject> holder,
- Handle<JSFunction> value);
+ Handle<Object> value);
Handle<Code> ComputeKeyedLoadInterceptor(Handle<Name> name,
Handle<JSObject> object,
Handle<Code> CompileLoadConstant(Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Name> name,
- Handle<JSFunction> value);
+ Handle<Object> value);
Handle<Code> CompileLoadInterceptor(Handle<JSObject> object,
Handle<JSObject> holder,
Handle<JSObject> holder,
PropertyIndex field,
Representation representation);
- void GenerateLoadConstant(Handle<JSFunction> value);
+ void GenerateLoadConstant(Handle<Object> value);
void GenerateLoadCallback(Register reg,
Handle<ExecutableAccessorInfo> callback);
void GenerateLoadInterceptor(Register holder_reg,
void LCodeGen::DoConstantT(LConstantT* instr) {
Handle<Object> value = instr->value();
AllowDeferredHandleDereference smi_check;
- if (value->IsSmi()) {
- __ Move(ToRegister(instr->result()), value);
- } else {
- __ LoadHeapObject(ToRegister(instr->result()),
- Handle<HeapObject>::cast(value));
- }
+ __ LoadObject(ToRegister(instr->result()), value);
}
__ movq(result, FieldOperand(object, JSObject::kPropertiesOffset));
__ movq(result, FieldOperand(result, offset + FixedArray::kHeaderSize));
}
- } else if (lookup.IsConstantFunction()) {
- Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type));
- __ LoadHeapObject(result, function);
+ } else if (lookup.IsConstant()) {
+ Handle<Object> constant(lookup.GetConstantFromMap(*type), isolate());
+ __ LoadObject(result, constant);
} else {
// Negative lookup.
// Check prototypes.
if (map->HasElementsTransition()) return false;
LookupResult lookup(isolate);
map->LookupDescriptor(NULL, *name, &lookup);
- return lookup.IsField() || lookup.IsConstantFunction();
+ return lookup.IsField() || lookup.IsConstant();
}
Representation representation = details.representation();
ASSERT(!representation.IsNone());
- if (details.type() == CONSTANT_FUNCTION) {
- Handle<HeapObject> constant(
- HeapObject::cast(descriptors->GetValue(descriptor)));
- __ LoadHeapObject(scratch1, constant);
- __ cmpq(value_reg, scratch1);
+ if (details.type() == CONSTANT) {
+ Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate());
+ __ CmpObject(value_reg, constant);
__ j(not_equal, miss_label);
} else if (FLAG_track_fields && representation.IsSmi()) {
__ JumpIfNotSmi(value_reg, miss_label);
OMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
- if (details.type() == CONSTANT_FUNCTION) {
+ if (details.type() == CONSTANT) {
ASSERT(value_reg.is(rax));
__ ret(0);
return;
}
-void BaseLoadStubCompiler::GenerateLoadConstant(Handle<JSFunction> value) {
+void BaseLoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
// Return the constant value.
- __ LoadHeapObject(rax, value);
+ __ LoadObject(rax, value);
__ ret(0);
}
Handle<Code> code = CompileCustomCall(object, holder,
Handle<PropertyCell>::null(),
function, Handle<String>::cast(name),
- Code::CONSTANT_FUNCTION);
+ Code::CONSTANT);
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}