break;
case Constant::kHeapObject: {
Handle<HeapObject> src_object = src.ToHeapObject();
- if (info()->IsOptimizing() &&
- src_object.is_identical_to(info()->context())) {
- // Loading the context from the frame is way cheaper than
- // materializing the actual context heap object address.
- __ ldr(dst, MemOperand(fp, StandardFrameConstants::kContextOffset));
- } else if (info()->IsOptimizing() &&
- src_object.is_identical_to(info()->closure())) {
- // Loading the JSFunction from the frame is way cheaper than
- // materializing the actual JSFunction heap object address.
- __ ldr(dst,
- MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+ Heap::RootListIndex index;
+ int offset;
+ if (IsMaterializableFromFrame(src_object, &offset)) {
+ __ ldr(dst, MemOperand(fp, offset));
+ } else if (IsMaterializableFromRoot(src_object, &index)) {
+ __ LoadRoot(dst, index);
} else {
__ Move(dst, src_object);
}
: scope.AcquireX();
if (src.type() == Constant::kHeapObject) {
Handle<HeapObject> src_object = src.ToHeapObject();
- if (info()->IsOptimizing() &&
- src_object.is_identical_to(info()->context())) {
- // Loading the context from the frame is way cheaper than
- // materializing the actual context heap object address.
- __ Ldr(dst, MemOperand(fp, StandardFrameConstants::kContextOffset));
- } else if (info()->IsOptimizing() &&
- src_object.is_identical_to(info()->closure())) {
- // Loading the JSFunction from the frame is way cheaper than
- // materializing the actual JSFunction heap object address.
- __ Ldr(dst,
- MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+ Heap::RootListIndex index;
+ int offset;
+ if (IsMaterializableFromFrame(src_object, &offset)) {
+ __ Ldr(dst, MemOperand(fp, offset));
+ } else if (IsMaterializableFromRoot(src_object, &index)) {
+ __ LoadRoot(dst, index);
} else {
__ LoadObject(dst, src_object);
}
}
+bool CodeGenerator::IsMaterializableFromFrame(Handle<HeapObject> object,
+ int* offset_return) {
+ if (linkage()->GetIncomingDescriptor()->IsJSFunctionCall()) {
+ if (object.is_identical_to(info()->context())) {
+ *offset_return = StandardFrameConstants::kContextOffset;
+ return true;
+ } else if (object.is_identical_to(info()->closure())) {
+ *offset_return = JavaScriptFrameConstants::kFunctionOffset;
+ return true;
+ }
+ }
+ return false;
+}
+
+
+bool CodeGenerator::IsMaterializableFromRoot(
+ Handle<HeapObject> object, Heap::RootListIndex* index_return) {
+ if (linkage()->GetIncomingDescriptor()->IsJSFunctionCall()) {
+#define IMMORTAL_IMMOVABLE_ROOT(Name) \
+ if (*object == isolate()->heap()->root(Heap::k##Name##RootIndex)) { \
+ *index_return = Heap::k##Name##RootIndex; \
+ return true; \
+ }
+ IMMORTAL_IMMOVABLE_ROOT_LIST(IMMORTAL_IMMOVABLE_ROOT)
+#undef IMMORTAL_IMMOVABLE_ROOT
+ }
+ return false;
+}
+
+
void CodeGenerator::AssembleInstruction(Instruction* instr) {
AssembleGaps(instr);
AssembleSourcePosition(instr);
void RecordSafepoint(ReferenceMap* references, Safepoint::Kind kind,
int arguments, Safepoint::DeoptMode deopt_mode);
+ // Check if a heap object can be materialized by loading from the frame, which
+ // is usually way cheaper than materializing the actual heap object constant.
+ bool IsMaterializableFromFrame(Handle<HeapObject> object, int* offset_return);
+ // Check if a heap object can be materialized by loading from a heap root,
+ // which is cheaper on some platforms than materializing the actual heap
+ // object constant.
+ bool IsMaterializableFromRoot(Handle<HeapObject> object,
+ Heap::RootListIndex* index_return);
+
// Assemble code for the specified instruction.
void AssembleInstruction(Instruction* instr);
void AssembleSourcePosition(Instruction* instr);
Constant src_constant = g.ToConstant(source);
if (src_constant.type() == Constant::kHeapObject) {
Handle<HeapObject> src = src_constant.ToHeapObject();
- if (info()->IsOptimizing() && src.is_identical_to(info()->context())) {
- // Loading the context from the frame is way cheaper than materializing
- // the actual context heap object address.
+ int offset;
+ if (IsMaterializableFromFrame(src, &offset)) {
if (destination->IsRegister()) {
Register dst = g.ToRegister(destination);
- __ mov(dst, Operand(ebp, StandardFrameConstants::kContextOffset));
+ __ mov(dst, Operand(ebp, offset));
} else {
DCHECK(destination->IsStackSlot());
Operand dst = g.ToOperand(destination);
- __ push(Operand(ebp, StandardFrameConstants::kContextOffset));
- __ pop(dst);
- }
- } else if (info()->IsOptimizing() &&
- src.is_identical_to(info()->closure())) {
- // Loading the JSFunction from the frame is way cheaper than
- // materializing the actual JSFunction heap object address.
- if (destination->IsRegister()) {
- Register dst = g.ToRegister(destination);
- __ mov(dst, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
- } else {
- DCHECK(destination->IsStackSlot());
- Operand dst = g.ToOperand(destination);
- __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
+ __ push(Operand(ebp, offset));
__ pop(dst);
}
} else if (destination->IsRegister()) {
break;
case Constant::kHeapObject: {
Handle<HeapObject> src_object = src.ToHeapObject();
- if (info()->IsOptimizing() &&
- src_object.is_identical_to(info()->context())) {
- // Loading the context from the frame is way cheaper than
- // materializing the actual context heap object address.
- __ movp(dst, Operand(rbp, StandardFrameConstants::kContextOffset));
- } else if (info()->IsOptimizing() &&
- src_object.is_identical_to(info()->closure())) {
- // Loading the JSFunction from the frame is way cheaper than
- // materializing the actual JSFunction heap object address.
- __ movp(dst,
- Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
+ Heap::RootListIndex index;
+ int offset;
+ if (IsMaterializableFromFrame(src_object, &offset)) {
+ __ movp(dst, Operand(rbp, offset));
+ } else if (IsMaterializableFromRoot(src_object, &index)) {
+ __ LoadRoot(dst, index);
} else {
__ Move(dst, src_object);
}