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 |