| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 | 334 |
| 335 int LCodeGen::ToInteger32(LConstantOperand* op) const { | 335 int LCodeGen::ToInteger32(LConstantOperand* op) const { |
| 336 Handle<Object> value = chunk_->LookupLiteral(op); | 336 Handle<Object> value = chunk_->LookupLiteral(op); |
| 337 ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32()); | 337 ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32()); |
| 338 ASSERT(static_cast<double>(static_cast<int32_t>(value->Number())) == | 338 ASSERT(static_cast<double>(static_cast<int32_t>(value->Number())) == |
| 339 value->Number()); | 339 value->Number()); |
| 340 return static_cast<int32_t>(value->Number()); | 340 return static_cast<int32_t>(value->Number()); |
| 341 } | 341 } |
| 342 | 342 |
| 343 | 343 |
| 344 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { |
| 345 Handle<Object> literal = chunk_->LookupLiteral(op); |
| 346 ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged()); |
| 347 return literal; |
| 348 } |
| 349 |
| 350 |
| 344 double LCodeGen::ToDouble(LConstantOperand* op) const { | 351 double LCodeGen::ToDouble(LConstantOperand* op) const { |
| 345 Handle<Object> value = chunk_->LookupLiteral(op); | 352 Handle<Object> value = chunk_->LookupLiteral(op); |
| 346 return value->Number(); | 353 return value->Number(); |
| 347 } | 354 } |
| 348 | 355 |
| 349 | 356 |
| 350 Immediate LCodeGen::ToImmediate(LOperand* op) { | 357 Immediate LCodeGen::ToImmediate(LOperand* op) { |
| 351 LConstantOperand* const_op = LConstantOperand::cast(op); | 358 LConstantOperand* const_op = LConstantOperand::cast(op); |
| 352 Handle<Object> literal = chunk_->LookupLiteral(const_op); | 359 Handle<Object> literal = chunk_->LookupLiteral(const_op); |
| 353 Representation r = chunk_->LookupLiteralRepresentation(const_op); | 360 Representation r = chunk_->LookupLiteralRepresentation(const_op); |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 511 LOperand* context) { | 518 LOperand* context) { |
| 512 if (context->IsRegister()) { | 519 if (context->IsRegister()) { |
| 513 if (!ToRegister(context).is(esi)) { | 520 if (!ToRegister(context).is(esi)) { |
| 514 __ mov(esi, ToRegister(context)); | 521 __ mov(esi, ToRegister(context)); |
| 515 } | 522 } |
| 516 } else if (context->IsStackSlot()) { | 523 } else if (context->IsStackSlot()) { |
| 517 __ mov(esi, ToOperand(context)); | 524 __ mov(esi, ToOperand(context)); |
| 518 } else if (context->IsConstantOperand()) { | 525 } else if (context->IsConstantOperand()) { |
| 519 Handle<Object> literal = | 526 Handle<Object> literal = |
| 520 chunk_->LookupLiteral(LConstantOperand::cast(context)); | 527 chunk_->LookupLiteral(LConstantOperand::cast(context)); |
| 521 LoadHeapObject(esi, Handle<Context>::cast(literal)); | 528 __ LoadHeapObject(esi, Handle<Context>::cast(literal)); |
| 522 } else { | 529 } else { |
| 523 UNREACHABLE(); | 530 UNREACHABLE(); |
| 524 } | 531 } |
| 525 | 532 |
| 526 __ CallRuntimeSaveDoubles(id); | 533 __ CallRuntimeSaveDoubles(id); |
| 527 RecordSafepointWithRegisters( | 534 RecordSafepointWithRegisters( |
| 528 instr->pointer_map(), argc, Safepoint::kNoLazyDeopt); | 535 instr->pointer_map(), argc, Safepoint::kNoLazyDeopt); |
| 529 } | 536 } |
| 530 | 537 |
| 531 | 538 |
| (...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1212 } | 1219 } |
| 1213 } | 1220 } |
| 1214 } | 1221 } |
| 1215 } | 1222 } |
| 1216 | 1223 |
| 1217 | 1224 |
| 1218 void LCodeGen::DoConstantT(LConstantT* instr) { | 1225 void LCodeGen::DoConstantT(LConstantT* instr) { |
| 1219 Register reg = ToRegister(instr->result()); | 1226 Register reg = ToRegister(instr->result()); |
| 1220 Handle<Object> handle = instr->value(); | 1227 Handle<Object> handle = instr->value(); |
| 1221 if (handle->IsHeapObject()) { | 1228 if (handle->IsHeapObject()) { |
| 1222 LoadHeapObject(reg, Handle<HeapObject>::cast(handle)); | 1229 __ LoadHeapObject(reg, Handle<HeapObject>::cast(handle)); |
| 1223 } else { | 1230 } else { |
| 1224 __ Set(reg, Immediate(handle)); | 1231 __ Set(reg, Immediate(handle)); |
| 1225 } | 1232 } |
| 1226 } | 1233 } |
| 1227 | 1234 |
| 1228 | 1235 |
| 1229 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { | 1236 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { |
| 1230 Register result = ToRegister(instr->result()); | 1237 Register result = ToRegister(instr->result()); |
| 1231 Register array = ToRegister(instr->InputAt(0)); | 1238 Register array = ToRegister(instr->InputAt(0)); |
| 1232 __ mov(result, FieldOperand(array, JSArray::kLengthOffset)); | 1239 __ mov(result, FieldOperand(array, JSArray::kLengthOffset)); |
| (...skipping 790 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2023 flags = static_cast<InstanceofStub::Flags>( | 2030 flags = static_cast<InstanceofStub::Flags>( |
| 2024 flags | InstanceofStub::kReturnTrueFalseObject); | 2031 flags | InstanceofStub::kReturnTrueFalseObject); |
| 2025 InstanceofStub stub(flags); | 2032 InstanceofStub stub(flags); |
| 2026 | 2033 |
| 2027 // Get the temp register reserved by the instruction. This needs to be a | 2034 // Get the temp register reserved by the instruction. This needs to be a |
| 2028 // register which is pushed last by PushSafepointRegisters as top of the | 2035 // register which is pushed last by PushSafepointRegisters as top of the |
| 2029 // stack is used to pass the offset to the location of the map check to | 2036 // stack is used to pass the offset to the location of the map check to |
| 2030 // the stub. | 2037 // the stub. |
| 2031 Register temp = ToRegister(instr->TempAt(0)); | 2038 Register temp = ToRegister(instr->TempAt(0)); |
| 2032 ASSERT(MacroAssembler::SafepointRegisterStackIndex(temp) == 0); | 2039 ASSERT(MacroAssembler::SafepointRegisterStackIndex(temp) == 0); |
| 2033 __ mov(InstanceofStub::right(), Immediate(instr->function())); | 2040 __ LoadHeapObject(InstanceofStub::right(), instr->function()); |
| 2034 static const int kAdditionalDelta = 13; | 2041 static const int kAdditionalDelta = 13; |
| 2035 int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; | 2042 int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; |
| 2036 __ mov(temp, Immediate(delta)); | 2043 __ mov(temp, Immediate(delta)); |
| 2037 __ StoreToSafepointRegisterSlot(temp, temp); | 2044 __ StoreToSafepointRegisterSlot(temp, temp); |
| 2038 CallCodeGeneric(stub.GetCode(), | 2045 CallCodeGeneric(stub.GetCode(), |
| 2039 RelocInfo::CODE_TARGET, | 2046 RelocInfo::CODE_TARGET, |
| 2040 instr, | 2047 instr, |
| 2041 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | 2048 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
| 2042 ASSERT(instr->HasDeoptimizationEnvironment()); | 2049 ASSERT(instr->HasDeoptimizationEnvironment()); |
| 2043 LEnvironment* env = instr->deoptimization_environment(); | 2050 LEnvironment* env = instr->deoptimization_environment(); |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2222 // Negative property indices are in-object properties, indexed | 2229 // Negative property indices are in-object properties, indexed |
| 2223 // from the end of the fixed part of the object. | 2230 // from the end of the fixed part of the object. |
| 2224 __ mov(result, FieldOperand(object, offset + type->instance_size())); | 2231 __ mov(result, FieldOperand(object, offset + type->instance_size())); |
| 2225 } else { | 2232 } else { |
| 2226 // Non-negative property indices are in the properties array. | 2233 // Non-negative property indices are in the properties array. |
| 2227 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); | 2234 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 2228 __ mov(result, FieldOperand(result, offset + FixedArray::kHeaderSize)); | 2235 __ mov(result, FieldOperand(result, offset + FixedArray::kHeaderSize)); |
| 2229 } | 2236 } |
| 2230 } else { | 2237 } else { |
| 2231 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type)); | 2238 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type)); |
| 2232 LoadHeapObject(result, Handle<HeapObject>::cast(function)); | 2239 __ LoadHeapObject(result, function); |
| 2240 } |
| 2241 } |
| 2242 |
| 2243 |
| 2244 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { |
| 2245 ASSERT(!operand->IsDoubleRegister()); |
| 2246 if (operand->IsConstantOperand()) { |
| 2247 Handle<Object> object = ToHandle(LConstantOperand::cast(operand)); |
| 2248 if (object->IsSmi()) { |
| 2249 __ Push(Handle<Smi>::cast(object)); |
| 2250 } else { |
| 2251 __ PushHeapObject(Handle<HeapObject>::cast(object)); |
| 2252 } |
| 2253 } else if (operand->IsRegister()) { |
| 2254 __ push(ToRegister(operand)); |
| 2255 } else { |
| 2256 __ push(ToOperand(operand)); |
| 2233 } | 2257 } |
| 2234 } | 2258 } |
| 2235 | 2259 |
| 2236 | 2260 |
| 2237 void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { | 2261 void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { |
| 2238 Register object = ToRegister(instr->object()); | 2262 Register object = ToRegister(instr->object()); |
| 2239 Register result = ToRegister(instr->result()); | 2263 Register result = ToRegister(instr->result()); |
| 2240 | 2264 |
| 2241 int map_count = instr->hydrogen()->types()->length(); | 2265 int map_count = instr->hydrogen()->types()->length(); |
| 2242 Handle<String> name = instr->hydrogen()->name(); | 2266 Handle<String> name = instr->hydrogen()->name(); |
| (...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2632 SafepointGenerator safepoint_generator( | 2656 SafepointGenerator safepoint_generator( |
| 2633 this, pointers, Safepoint::kLazyDeopt); | 2657 this, pointers, Safepoint::kLazyDeopt); |
| 2634 ParameterCount actual(eax); | 2658 ParameterCount actual(eax); |
| 2635 __ InvokeFunction(function, actual, CALL_FUNCTION, | 2659 __ InvokeFunction(function, actual, CALL_FUNCTION, |
| 2636 safepoint_generator, CALL_AS_METHOD); | 2660 safepoint_generator, CALL_AS_METHOD); |
| 2637 } | 2661 } |
| 2638 | 2662 |
| 2639 | 2663 |
| 2640 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 2664 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
| 2641 LOperand* argument = instr->InputAt(0); | 2665 LOperand* argument = instr->InputAt(0); |
| 2642 if (argument->IsConstantOperand()) { | 2666 EmitPushTaggedOperand(argument); |
| 2643 __ push(ToImmediate(argument)); | |
| 2644 } else { | |
| 2645 __ push(ToOperand(argument)); | |
| 2646 } | |
| 2647 } | 2667 } |
| 2648 | 2668 |
| 2649 | 2669 |
| 2650 void LCodeGen::DoThisFunction(LThisFunction* instr) { | 2670 void LCodeGen::DoThisFunction(LThisFunction* instr) { |
| 2651 Register result = ToRegister(instr->result()); | 2671 Register result = ToRegister(instr->result()); |
| 2652 LoadHeapObject(result, instr->hydrogen()->closure()); | 2672 __ LoadHeapObject(result, instr->hydrogen()->closure()); |
| 2653 } | 2673 } |
| 2654 | 2674 |
| 2655 | 2675 |
| 2656 void LCodeGen::DoContext(LContext* instr) { | 2676 void LCodeGen::DoContext(LContext* instr) { |
| 2657 Register result = ToRegister(instr->result()); | 2677 Register result = ToRegister(instr->result()); |
| 2658 __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2678 __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2659 } | 2679 } |
| 2660 | 2680 |
| 2661 | 2681 |
| 2662 void LCodeGen::DoOuterContext(LOuterContext* instr) { | 2682 void LCodeGen::DoOuterContext(LOuterContext* instr) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2712 } else { | 2732 } else { |
| 2713 __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset)); | 2733 __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset)); |
| 2714 } | 2734 } |
| 2715 | 2735 |
| 2716 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 2736 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
| 2717 } | 2737 } |
| 2718 | 2738 |
| 2719 | 2739 |
| 2720 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 2740 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
| 2721 ASSERT(ToRegister(instr->result()).is(eax)); | 2741 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2722 __ mov(edi, instr->function()); | 2742 __ LoadHeapObject(edi, instr->function()); |
| 2723 CallKnownFunction(instr->function(), | 2743 CallKnownFunction(instr->function(), |
| 2724 instr->arity(), | 2744 instr->arity(), |
| 2725 instr, | 2745 instr, |
| 2726 CALL_AS_METHOD); | 2746 CALL_AS_METHOD); |
| 2727 } | 2747 } |
| 2728 | 2748 |
| 2729 | 2749 |
| 2730 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { | 2750 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
| 2731 Register input_reg = ToRegister(instr->value()); | 2751 Register input_reg = ToRegister(instr->value()); |
| 2732 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 2752 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3152 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; | 3172 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; |
| 3153 Handle<Code> ic = | 3173 Handle<Code> ic = |
| 3154 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); | 3174 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); |
| 3155 __ mov(ecx, instr->name()); | 3175 __ mov(ecx, instr->name()); |
| 3156 CallCode(ic, mode, instr); | 3176 CallCode(ic, mode, instr); |
| 3157 } | 3177 } |
| 3158 | 3178 |
| 3159 | 3179 |
| 3160 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { | 3180 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { |
| 3161 ASSERT(ToRegister(instr->result()).is(eax)); | 3181 ASSERT(ToRegister(instr->result()).is(eax)); |
| 3162 __ mov(edi, instr->target()); | 3182 __ LoadHeapObject(edi, instr->target()); |
| 3163 CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION); | 3183 CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION); |
| 3164 } | 3184 } |
| 3165 | 3185 |
| 3166 | 3186 |
| 3167 void LCodeGen::DoCallNew(LCallNew* instr) { | 3187 void LCodeGen::DoCallNew(LCallNew* instr) { |
| 3168 ASSERT(ToRegister(instr->context()).is(esi)); | 3188 ASSERT(ToRegister(instr->context()).is(esi)); |
| 3169 ASSERT(ToRegister(instr->constructor()).is(edi)); | 3189 ASSERT(ToRegister(instr->constructor()).is(edi)); |
| 3170 ASSERT(ToRegister(instr->result()).is(eax)); | 3190 ASSERT(ToRegister(instr->result()).is(eax)); |
| 3171 | 3191 |
| 3172 Handle<Code> builtin = isolate()->builtins()->JSConstructCall(); | 3192 Handle<Code> builtin = isolate()->builtins()->JSConstructCall(); |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3517 | 3537 |
| 3518 | 3538 |
| 3519 void LCodeGen::DoStringLength(LStringLength* instr) { | 3539 void LCodeGen::DoStringLength(LStringLength* instr) { |
| 3520 Register string = ToRegister(instr->string()); | 3540 Register string = ToRegister(instr->string()); |
| 3521 Register result = ToRegister(instr->result()); | 3541 Register result = ToRegister(instr->result()); |
| 3522 __ mov(result, FieldOperand(string, String::kLengthOffset)); | 3542 __ mov(result, FieldOperand(string, String::kLengthOffset)); |
| 3523 } | 3543 } |
| 3524 | 3544 |
| 3525 | 3545 |
| 3526 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 3546 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
| 3527 if (instr->left()->IsConstantOperand()) { | 3547 EmitPushTaggedOperand(instr->left()); |
| 3528 __ push(ToImmediate(instr->left())); | 3548 EmitPushTaggedOperand(instr->right()); |
| 3529 } else { | |
| 3530 __ push(ToOperand(instr->left())); | |
| 3531 } | |
| 3532 if (instr->right()->IsConstantOperand()) { | |
| 3533 __ push(ToImmediate(instr->right())); | |
| 3534 } else { | |
| 3535 __ push(ToOperand(instr->right())); | |
| 3536 } | |
| 3537 StringAddStub stub(NO_STRING_CHECK_IN_STUB); | 3549 StringAddStub stub(NO_STRING_CHECK_IN_STUB); |
| 3538 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 3550 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 3539 } | 3551 } |
| 3540 | 3552 |
| 3541 | 3553 |
| 3542 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 3554 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
| 3543 LOperand* input = instr->InputAt(0); | 3555 LOperand* input = instr->InputAt(0); |
| 3544 ASSERT(input->IsRegister() || input->IsStackSlot()); | 3556 ASSERT(input->IsRegister() || input->IsStackSlot()); |
| 3545 LOperand* output = instr->result(); | 3557 LOperand* output = instr->result(); |
| 3546 ASSERT(output->IsDoubleRegister()); | 3558 ASSERT(output->IsDoubleRegister()); |
| (...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4025 | 4037 |
| 4026 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { | 4038 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { |
| 4027 Handle<JSFunction> target = instr->hydrogen()->target(); | 4039 Handle<JSFunction> target = instr->hydrogen()->target(); |
| 4028 if (isolate()->heap()->InNewSpace(*target)) { | 4040 if (isolate()->heap()->InNewSpace(*target)) { |
| 4029 Register reg = ToRegister(instr->value()); | 4041 Register reg = ToRegister(instr->value()); |
| 4030 Handle<JSGlobalPropertyCell> cell = | 4042 Handle<JSGlobalPropertyCell> cell = |
| 4031 isolate()->factory()->NewJSGlobalPropertyCell(target); | 4043 isolate()->factory()->NewJSGlobalPropertyCell(target); |
| 4032 __ cmp(reg, Operand::Cell(cell)); | 4044 __ cmp(reg, Operand::Cell(cell)); |
| 4033 } else { | 4045 } else { |
| 4034 Operand operand = ToOperand(instr->value()); | 4046 Operand operand = ToOperand(instr->value()); |
| 4035 __ cmp(operand, instr->hydrogen()->target()); | 4047 __ cmp(operand, target); |
| 4036 } | 4048 } |
| 4037 DeoptimizeIf(not_equal, instr->environment()); | 4049 DeoptimizeIf(not_equal, instr->environment()); |
| 4038 } | 4050 } |
| 4039 | 4051 |
| 4040 | 4052 |
| 4041 void LCodeGen::DoCheckMap(LCheckMap* instr) { | 4053 void LCodeGen::DoCheckMap(LCheckMap* instr) { |
| 4042 LOperand* input = instr->InputAt(0); | 4054 LOperand* input = instr->InputAt(0); |
| 4043 ASSERT(input->IsRegister()); | 4055 ASSERT(input->IsRegister()); |
| 4044 Register reg = ToRegister(input); | 4056 Register reg = ToRegister(input); |
| 4045 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 4057 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4089 | 4101 |
| 4090 // smi | 4102 // smi |
| 4091 __ bind(&is_smi); | 4103 __ bind(&is_smi); |
| 4092 __ SmiUntag(input_reg); | 4104 __ SmiUntag(input_reg); |
| 4093 __ ClampUint8(input_reg); | 4105 __ ClampUint8(input_reg); |
| 4094 | 4106 |
| 4095 __ bind(&done); | 4107 __ bind(&done); |
| 4096 } | 4108 } |
| 4097 | 4109 |
| 4098 | 4110 |
| 4099 void LCodeGen::LoadHeapObject(Register result, Handle<HeapObject> object) { | |
| 4100 if (isolate()->heap()->InNewSpace(*object)) { | |
| 4101 Handle<JSGlobalPropertyCell> cell = | |
| 4102 isolate()->factory()->NewJSGlobalPropertyCell(object); | |
| 4103 __ mov(result, Operand::Cell(cell)); | |
| 4104 } else { | |
| 4105 __ mov(result, object); | |
| 4106 } | |
| 4107 } | |
| 4108 | |
| 4109 | |
| 4110 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { | 4111 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { |
| 4111 Register reg = ToRegister(instr->TempAt(0)); | 4112 Register reg = ToRegister(instr->TempAt(0)); |
| 4112 | 4113 |
| 4113 Handle<JSObject> holder = instr->holder(); | 4114 Handle<JSObject> holder = instr->holder(); |
| 4114 Handle<JSObject> current_prototype = instr->prototype(); | 4115 Handle<JSObject> current_prototype = instr->prototype(); |
| 4115 | 4116 |
| 4116 // Load prototype object. | 4117 // Load prototype object. |
| 4117 LoadHeapObject(reg, current_prototype); | 4118 __ LoadHeapObject(reg, current_prototype); |
| 4118 | 4119 |
| 4119 // Check prototype maps up to the holder. | 4120 // Check prototype maps up to the holder. |
| 4120 while (!current_prototype.is_identical_to(holder)) { | 4121 while (!current_prototype.is_identical_to(holder)) { |
| 4121 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 4122 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 4122 Handle<Map>(current_prototype->map())); | 4123 Handle<Map>(current_prototype->map())); |
| 4123 DeoptimizeIf(not_equal, instr->environment()); | 4124 DeoptimizeIf(not_equal, instr->environment()); |
| 4124 current_prototype = | 4125 current_prototype = |
| 4125 Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); | 4126 Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); |
| 4126 // Load next prototype object. | 4127 // Load next prototype object. |
| 4127 LoadHeapObject(reg, current_prototype); | 4128 __ LoadHeapObject(reg, current_prototype); |
| 4128 } | 4129 } |
| 4129 | 4130 |
| 4130 // Check the holder map. | 4131 // Check the holder map. |
| 4131 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 4132 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 4132 Handle<Map>(current_prototype->map())); | 4133 Handle<Map>(current_prototype->map())); |
| 4133 DeoptimizeIf(not_equal, instr->environment()); | 4134 DeoptimizeIf(not_equal, instr->environment()); |
| 4134 } | 4135 } |
| 4135 | 4136 |
| 4136 | 4137 |
| 4137 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { | 4138 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4172 | 4173 |
| 4173 | 4174 |
| 4174 void LCodeGen::EmitDeepCopy(Handle<JSObject> object, | 4175 void LCodeGen::EmitDeepCopy(Handle<JSObject> object, |
| 4175 Register result, | 4176 Register result, |
| 4176 Register source, | 4177 Register source, |
| 4177 int* offset) { | 4178 int* offset) { |
| 4178 ASSERT(!source.is(ecx)); | 4179 ASSERT(!source.is(ecx)); |
| 4179 ASSERT(!result.is(ecx)); | 4180 ASSERT(!result.is(ecx)); |
| 4180 | 4181 |
| 4181 if (FLAG_debug_code) { | 4182 if (FLAG_debug_code) { |
| 4182 LoadHeapObject(ecx, object); | 4183 __ LoadHeapObject(ecx, object); |
| 4183 __ cmp(source, ecx); | 4184 __ cmp(source, ecx); |
| 4184 __ Assert(equal, "Unexpected object literal boilerplate"); | 4185 __ Assert(equal, "Unexpected object literal boilerplate"); |
| 4185 } | 4186 } |
| 4186 | 4187 |
| 4187 // Increase the offset so that subsequent objects end up right after | 4188 // Increase the offset so that subsequent objects end up right after |
| 4188 // this one. | 4189 // this one. |
| 4189 int current_offset = *offset; | 4190 int current_offset = *offset; |
| 4190 int size = object->map()->instance_size(); | 4191 int size = object->map()->instance_size(); |
| 4191 *offset += size; | 4192 *offset += size; |
| 4192 | 4193 |
| 4193 // Copy object header. | 4194 // Copy object header. |
| 4194 ASSERT(object->properties()->length() == 0); | 4195 ASSERT(object->properties()->length() == 0); |
| 4195 ASSERT(object->elements()->length() == 0 || | 4196 ASSERT(object->elements()->length() == 0 || |
| 4196 object->elements()->map() == isolate()->heap()->fixed_cow_array_map()); | 4197 object->elements()->map() == isolate()->heap()->fixed_cow_array_map()); |
| 4197 int inobject_properties = object->map()->inobject_properties(); | 4198 int inobject_properties = object->map()->inobject_properties(); |
| 4198 int header_size = size - inobject_properties * kPointerSize; | 4199 int header_size = size - inobject_properties * kPointerSize; |
| 4199 for (int i = 0; i < header_size; i += kPointerSize) { | 4200 for (int i = 0; i < header_size; i += kPointerSize) { |
| 4200 __ mov(ecx, FieldOperand(source, i)); | 4201 __ mov(ecx, FieldOperand(source, i)); |
| 4201 __ mov(FieldOperand(result, current_offset + i), ecx); | 4202 __ mov(FieldOperand(result, current_offset + i), ecx); |
| 4202 } | 4203 } |
| 4203 | 4204 |
| 4204 // Copy in-object properties. | 4205 // Copy in-object properties. |
| 4205 for (int i = 0; i < inobject_properties; i++) { | 4206 for (int i = 0; i < inobject_properties; i++) { |
| 4206 int total_offset = current_offset + object->GetInObjectPropertyOffset(i); | 4207 int total_offset = current_offset + object->GetInObjectPropertyOffset(i); |
| 4207 Handle<Object> value = Handle<Object>(object->InObjectPropertyAt(i)); | 4208 Handle<Object> value = Handle<Object>(object->InObjectPropertyAt(i)); |
| 4208 if (value->IsJSObject()) { | 4209 if (value->IsJSObject()) { |
| 4209 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 4210 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 4210 __ lea(ecx, Operand(result, *offset)); | 4211 __ lea(ecx, Operand(result, *offset)); |
| 4211 __ mov(FieldOperand(result, total_offset), ecx); | 4212 __ mov(FieldOperand(result, total_offset), ecx); |
| 4212 LoadHeapObject(source, value_object); | 4213 __ LoadHeapObject(source, value_object); |
| 4213 EmitDeepCopy(value_object, result, source, offset); | 4214 EmitDeepCopy(value_object, result, source, offset); |
| 4214 } else if (value->IsHeapObject()) { | 4215 } else if (value->IsHeapObject()) { |
| 4215 LoadHeapObject(ecx, Handle<HeapObject>::cast(value)); | 4216 __ LoadHeapObject(ecx, Handle<HeapObject>::cast(value)); |
| 4216 __ mov(FieldOperand(result, total_offset), ecx); | 4217 __ mov(FieldOperand(result, total_offset), ecx); |
| 4217 } else { | 4218 } else { |
| 4218 __ mov(FieldOperand(result, total_offset), Immediate(value)); | 4219 __ mov(FieldOperand(result, total_offset), Immediate(value)); |
| 4219 } | 4220 } |
| 4220 } | 4221 } |
| 4221 } | 4222 } |
| 4222 | 4223 |
| 4223 | 4224 |
| 4224 void LCodeGen::DoObjectLiteralFast(LObjectLiteralFast* instr) { | 4225 void LCodeGen::DoObjectLiteralFast(LObjectLiteralFast* instr) { |
| 4225 ASSERT(ToRegister(instr->context()).is(esi)); | 4226 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4226 int size = instr->hydrogen()->total_size(); | 4227 int size = instr->hydrogen()->total_size(); |
| 4227 | 4228 |
| 4228 // Allocate all objects that are part of the literal in one big | 4229 // Allocate all objects that are part of the literal in one big |
| 4229 // allocation. This avoids multiple limit checks. | 4230 // allocation. This avoids multiple limit checks. |
| 4230 Label allocated, runtime_allocate; | 4231 Label allocated, runtime_allocate; |
| 4231 __ AllocateInNewSpace(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); | 4232 __ AllocateInNewSpace(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); |
| 4232 __ jmp(&allocated); | 4233 __ jmp(&allocated); |
| 4233 | 4234 |
| 4234 __ bind(&runtime_allocate); | 4235 __ bind(&runtime_allocate); |
| 4235 __ push(Immediate(Smi::FromInt(size))); | 4236 __ push(Immediate(Smi::FromInt(size))); |
| 4236 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); | 4237 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); |
| 4237 | 4238 |
| 4238 __ bind(&allocated); | 4239 __ bind(&allocated); |
| 4239 int offset = 0; | 4240 int offset = 0; |
| 4240 LoadHeapObject(ebx, instr->hydrogen()->boilerplate()); | 4241 __ LoadHeapObject(ebx, instr->hydrogen()->boilerplate()); |
| 4241 EmitDeepCopy(instr->hydrogen()->boilerplate(), eax, ebx, &offset); | 4242 EmitDeepCopy(instr->hydrogen()->boilerplate(), eax, ebx, &offset); |
| 4242 ASSERT_EQ(size, offset); | 4243 ASSERT_EQ(size, offset); |
| 4243 } | 4244 } |
| 4244 | 4245 |
| 4245 | 4246 |
| 4246 void LCodeGen::DoObjectLiteralGeneric(LObjectLiteralGeneric* instr) { | 4247 void LCodeGen::DoObjectLiteralGeneric(LObjectLiteralGeneric* instr) { |
| 4247 ASSERT(ToRegister(instr->context()).is(esi)); | 4248 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4248 Handle<FixedArray> constant_properties = | 4249 Handle<FixedArray> constant_properties = |
| 4249 instr->hydrogen()->constant_properties(); | 4250 instr->hydrogen()->constant_properties(); |
| 4250 | 4251 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4352 __ push(Immediate(pretenure | 4353 __ push(Immediate(pretenure |
| 4353 ? factory()->true_value() | 4354 ? factory()->true_value() |
| 4354 : factory()->false_value())); | 4355 : factory()->false_value())); |
| 4355 CallRuntime(Runtime::kNewClosure, 3, instr); | 4356 CallRuntime(Runtime::kNewClosure, 3, instr); |
| 4356 } | 4357 } |
| 4357 } | 4358 } |
| 4358 | 4359 |
| 4359 | 4360 |
| 4360 void LCodeGen::DoTypeof(LTypeof* instr) { | 4361 void LCodeGen::DoTypeof(LTypeof* instr) { |
| 4361 LOperand* input = instr->InputAt(1); | 4362 LOperand* input = instr->InputAt(1); |
| 4362 if (input->IsConstantOperand()) { | 4363 EmitPushTaggedOperand(input); |
| 4363 __ push(ToImmediate(input)); | |
| 4364 } else { | |
| 4365 __ push(ToOperand(input)); | |
| 4366 } | |
| 4367 CallRuntime(Runtime::kTypeof, 1, instr); | 4364 CallRuntime(Runtime::kTypeof, 1, instr); |
| 4368 } | 4365 } |
| 4369 | 4366 |
| 4370 | 4367 |
| 4371 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 4368 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
| 4372 Register input = ToRegister(instr->InputAt(0)); | 4369 Register input = ToRegister(instr->InputAt(0)); |
| 4373 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 4370 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 4374 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 4371 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 4375 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 4372 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 4376 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 4373 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4506 | 4503 |
| 4507 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { | 4504 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { |
| 4508 DeoptimizeIf(no_condition, instr->environment()); | 4505 DeoptimizeIf(no_condition, instr->environment()); |
| 4509 } | 4506 } |
| 4510 | 4507 |
| 4511 | 4508 |
| 4512 void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) { | 4509 void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) { |
| 4513 LOperand* obj = instr->object(); | 4510 LOperand* obj = instr->object(); |
| 4514 LOperand* key = instr->key(); | 4511 LOperand* key = instr->key(); |
| 4515 __ push(ToOperand(obj)); | 4512 __ push(ToOperand(obj)); |
| 4516 if (key->IsConstantOperand()) { | 4513 EmitPushTaggedOperand(key); |
| 4517 __ push(ToImmediate(key)); | |
| 4518 } else { | |
| 4519 __ push(ToOperand(key)); | |
| 4520 } | |
| 4521 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); | 4514 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); |
| 4522 LPointerMap* pointers = instr->pointer_map(); | 4515 LPointerMap* pointers = instr->pointer_map(); |
| 4523 RecordPosition(pointers->position()); | 4516 RecordPosition(pointers->position()); |
| 4524 // Create safepoint generator that will also ensure enough space in the | 4517 // Create safepoint generator that will also ensure enough space in the |
| 4525 // reloc info for patching in deoptimization (since this is invoking a | 4518 // reloc info for patching in deoptimization (since this is invoking a |
| 4526 // builtin) | 4519 // builtin) |
| 4527 SafepointGenerator safepoint_generator( | 4520 SafepointGenerator safepoint_generator( |
| 4528 this, pointers, Safepoint::kLazyDeopt); | 4521 this, pointers, Safepoint::kLazyDeopt); |
| 4529 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); | 4522 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); |
| 4530 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator); | 4523 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4587 ASSERT(!environment->HasBeenRegistered()); | 4580 ASSERT(!environment->HasBeenRegistered()); |
| 4588 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 4581 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
| 4589 ASSERT(osr_pc_offset_ == -1); | 4582 ASSERT(osr_pc_offset_ == -1); |
| 4590 osr_pc_offset_ = masm()->pc_offset(); | 4583 osr_pc_offset_ = masm()->pc_offset(); |
| 4591 } | 4584 } |
| 4592 | 4585 |
| 4593 | 4586 |
| 4594 void LCodeGen::DoIn(LIn* instr) { | 4587 void LCodeGen::DoIn(LIn* instr) { |
| 4595 LOperand* obj = instr->object(); | 4588 LOperand* obj = instr->object(); |
| 4596 LOperand* key = instr->key(); | 4589 LOperand* key = instr->key(); |
| 4597 if (key->IsConstantOperand()) { | 4590 EmitPushTaggedOperand(key); |
| 4598 __ push(ToImmediate(key)); | 4591 EmitPushTaggedOperand(obj); |
| 4599 } else { | |
| 4600 __ push(ToOperand(key)); | |
| 4601 } | |
| 4602 if (obj->IsConstantOperand()) { | |
| 4603 __ push(ToImmediate(obj)); | |
| 4604 } else { | |
| 4605 __ push(ToOperand(obj)); | |
| 4606 } | |
| 4607 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); | 4592 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); |
| 4608 LPointerMap* pointers = instr->pointer_map(); | 4593 LPointerMap* pointers = instr->pointer_map(); |
| 4609 RecordPosition(pointers->position()); | 4594 RecordPosition(pointers->position()); |
| 4610 SafepointGenerator safepoint_generator( | 4595 SafepointGenerator safepoint_generator( |
| 4611 this, pointers, Safepoint::kLazyDeopt); | 4596 this, pointers, Safepoint::kLazyDeopt); |
| 4612 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); | 4597 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); |
| 4613 } | 4598 } |
| 4614 | 4599 |
| 4615 | 4600 |
| 4616 #undef __ | 4601 #undef __ |
| 4617 | 4602 |
| 4618 } } // namespace v8::internal | 4603 } } // namespace v8::internal |
| 4619 | 4604 |
| 4620 #endif // V8_TARGET_ARCH_IA32 | 4605 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |