OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 2306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2317 __ j(equal, &done, Label::kNear); | 2317 __ j(equal, &done, Label::kNear); |
2318 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), | 2318 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), |
2319 Heap::kFixedCOWArrayMapRootIndex); | 2319 Heap::kFixedCOWArrayMapRootIndex); |
2320 __ j(equal, &done, Label::kNear); | 2320 __ j(equal, &done, Label::kNear); |
2321 Register temp((result.is(rax)) ? rbx : rax); | 2321 Register temp((result.is(rax)) ? rbx : rax); |
2322 __ push(temp); | 2322 __ push(temp); |
2323 __ movq(temp, FieldOperand(result, HeapObject::kMapOffset)); | 2323 __ movq(temp, FieldOperand(result, HeapObject::kMapOffset)); |
2324 __ movzxbq(temp, FieldOperand(temp, Map::kBitField2Offset)); | 2324 __ movzxbq(temp, FieldOperand(temp, Map::kBitField2Offset)); |
2325 __ and_(temp, Immediate(Map::kElementsKindMask)); | 2325 __ and_(temp, Immediate(Map::kElementsKindMask)); |
2326 __ shr(temp, Immediate(Map::kElementsKindShift)); | 2326 __ shr(temp, Immediate(Map::kElementsKindShift)); |
2327 __ cmpl(temp, Immediate(GetInitialFastElementsKind())); | 2327 __ cmpl(temp, Immediate(FAST_ELEMENTS)); |
2328 __ j(less, &fail, Label::kNear); | 2328 __ j(equal, &ok, Label::kNear); |
2329 __ cmpl(temp, Immediate(TERMINAL_FAST_ELEMENTS_KIND)); | |
2330 __ j(less_equal, &ok, Label::kNear); | |
2331 __ cmpl(temp, Immediate(FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND)); | 2329 __ cmpl(temp, Immediate(FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND)); |
2332 __ j(less, &fail, Label::kNear); | 2330 __ j(less, &fail, Label::kNear); |
2333 __ cmpl(temp, Immediate(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND)); | 2331 __ cmpl(temp, Immediate(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND)); |
2334 __ j(less_equal, &ok, Label::kNear); | 2332 __ j(less_equal, &ok, Label::kNear); |
2335 __ bind(&fail); | 2333 __ bind(&fail); |
2336 __ Abort("Check for fast or external elements failed"); | 2334 __ Abort("Check for fast or external elements failed"); |
2337 __ bind(&ok); | 2335 __ bind(&ok); |
2338 __ pop(temp); | 2336 __ pop(temp); |
2339 __ bind(&done); | 2337 __ bind(&done); |
2340 } | 2338 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2398 LLoadKeyedFastDoubleElement* instr) { | 2396 LLoadKeyedFastDoubleElement* instr) { |
2399 XMMRegister result(ToDoubleRegister(instr->result())); | 2397 XMMRegister result(ToDoubleRegister(instr->result())); |
2400 | 2398 |
2401 if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) { | 2399 if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) { |
2402 // Sign extend key because it could be a 32 bit negative value | 2400 // Sign extend key because it could be a 32 bit negative value |
2403 // and the dehoisted address computation happens in 64 bits | 2401 // and the dehoisted address computation happens in 64 bits |
2404 Register key_reg = ToRegister(instr->key()); | 2402 Register key_reg = ToRegister(instr->key()); |
2405 __ movsxlq(key_reg, key_reg); | 2403 __ movsxlq(key_reg, key_reg); |
2406 } | 2404 } |
2407 | 2405 |
2408 if (instr->hydrogen()->RequiresHoleCheck()) { | 2406 int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag + |
2409 int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag + | 2407 sizeof(kHoleNanLower32); |
2410 sizeof(kHoleNanLower32); | 2408 Operand hole_check_operand = BuildFastArrayOperand( |
2411 Operand hole_check_operand = BuildFastArrayOperand( | 2409 instr->elements(), |
2412 instr->elements(), | 2410 instr->key(), |
2413 instr->key(), | 2411 FAST_DOUBLE_ELEMENTS, |
2414 FAST_DOUBLE_ELEMENTS, | 2412 offset, |
2415 offset, | 2413 instr->additional_index()); |
2416 instr->additional_index()); | 2414 __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32)); |
2417 __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32)); | 2415 DeoptimizeIf(equal, instr->environment()); |
2418 DeoptimizeIf(equal, instr->environment()); | |
2419 } | |
2420 | 2416 |
2421 Operand double_load_operand = BuildFastArrayOperand( | 2417 Operand double_load_operand = BuildFastArrayOperand( |
2422 instr->elements(), | 2418 instr->elements(), |
2423 instr->key(), | 2419 instr->key(), |
2424 FAST_DOUBLE_ELEMENTS, | 2420 FAST_DOUBLE_ELEMENTS, |
2425 FixedDoubleArray::kHeaderSize - kHeapObjectTag, | 2421 FixedDoubleArray::kHeaderSize - kHeapObjectTag, |
2426 instr->additional_index()); | 2422 instr->additional_index()); |
2427 __ movsd(result, double_load_operand); | 2423 __ movsd(result, double_load_operand); |
2428 } | 2424 } |
2429 | 2425 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2498 __ movl(result, operand); | 2494 __ movl(result, operand); |
2499 __ testl(result, result); | 2495 __ testl(result, result); |
2500 // TODO(danno): we could be more clever here, perhaps having a special | 2496 // TODO(danno): we could be more clever here, perhaps having a special |
2501 // version of the stub that detects if the overflow case actually | 2497 // version of the stub that detects if the overflow case actually |
2502 // happens, and generate code that returns a double rather than int. | 2498 // happens, and generate code that returns a double rather than int. |
2503 DeoptimizeIf(negative, instr->environment()); | 2499 DeoptimizeIf(negative, instr->environment()); |
2504 break; | 2500 break; |
2505 case EXTERNAL_FLOAT_ELEMENTS: | 2501 case EXTERNAL_FLOAT_ELEMENTS: |
2506 case EXTERNAL_DOUBLE_ELEMENTS: | 2502 case EXTERNAL_DOUBLE_ELEMENTS: |
2507 case FAST_ELEMENTS: | 2503 case FAST_ELEMENTS: |
2508 case FAST_SMI_ELEMENTS: | 2504 case FAST_SMI_ONLY_ELEMENTS: |
2509 case FAST_DOUBLE_ELEMENTS: | 2505 case FAST_DOUBLE_ELEMENTS: |
2510 case FAST_HOLEY_ELEMENTS: | |
2511 case FAST_HOLEY_SMI_ELEMENTS: | |
2512 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
2513 case DICTIONARY_ELEMENTS: | 2506 case DICTIONARY_ELEMENTS: |
2514 case NON_STRICT_ARGUMENTS_ELEMENTS: | 2507 case NON_STRICT_ARGUMENTS_ELEMENTS: |
2515 UNREACHABLE(); | 2508 UNREACHABLE(); |
2516 break; | 2509 break; |
2517 } | 2510 } |
2518 } | 2511 } |
2519 } | 2512 } |
2520 | 2513 |
2521 | 2514 |
2522 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 2515 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
(...skipping 880 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3403 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3396 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
3404 __ movw(operand, value); | 3397 __ movw(operand, value); |
3405 break; | 3398 break; |
3406 case EXTERNAL_INT_ELEMENTS: | 3399 case EXTERNAL_INT_ELEMENTS: |
3407 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3400 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
3408 __ movl(operand, value); | 3401 __ movl(operand, value); |
3409 break; | 3402 break; |
3410 case EXTERNAL_FLOAT_ELEMENTS: | 3403 case EXTERNAL_FLOAT_ELEMENTS: |
3411 case EXTERNAL_DOUBLE_ELEMENTS: | 3404 case EXTERNAL_DOUBLE_ELEMENTS: |
3412 case FAST_ELEMENTS: | 3405 case FAST_ELEMENTS: |
3413 case FAST_SMI_ELEMENTS: | 3406 case FAST_SMI_ONLY_ELEMENTS: |
3414 case FAST_DOUBLE_ELEMENTS: | 3407 case FAST_DOUBLE_ELEMENTS: |
3415 case FAST_HOLEY_ELEMENTS: | |
3416 case FAST_HOLEY_SMI_ELEMENTS: | |
3417 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
3418 case DICTIONARY_ELEMENTS: | 3408 case DICTIONARY_ELEMENTS: |
3419 case NON_STRICT_ARGUMENTS_ELEMENTS: | 3409 case NON_STRICT_ARGUMENTS_ELEMENTS: |
3420 UNREACHABLE(); | 3410 UNREACHABLE(); |
3421 break; | 3411 break; |
3422 } | 3412 } |
3423 } | 3413 } |
3424 } | 3414 } |
3425 | 3415 |
3426 | 3416 |
3427 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { | 3417 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3542 | 3532 |
3543 Handle<Map> from_map = instr->original_map(); | 3533 Handle<Map> from_map = instr->original_map(); |
3544 Handle<Map> to_map = instr->transitioned_map(); | 3534 Handle<Map> to_map = instr->transitioned_map(); |
3545 ElementsKind from_kind = from_map->elements_kind(); | 3535 ElementsKind from_kind = from_map->elements_kind(); |
3546 ElementsKind to_kind = to_map->elements_kind(); | 3536 ElementsKind to_kind = to_map->elements_kind(); |
3547 | 3537 |
3548 Label not_applicable; | 3538 Label not_applicable; |
3549 __ Cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); | 3539 __ Cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); |
3550 __ j(not_equal, ¬_applicable); | 3540 __ j(not_equal, ¬_applicable); |
3551 __ movq(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT); | 3541 __ movq(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT); |
3552 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { | 3542 if (from_kind == FAST_SMI_ONLY_ELEMENTS && to_kind == FAST_ELEMENTS) { |
3553 __ movq(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); | 3543 __ movq(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); |
3554 // Write barrier. | 3544 // Write barrier. |
3555 ASSERT_NE(instr->temp_reg(), NULL); | 3545 ASSERT_NE(instr->temp_reg(), NULL); |
3556 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, | 3546 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, |
3557 ToRegister(instr->temp_reg()), kDontSaveFPRegs); | 3547 ToRegister(instr->temp_reg()), kDontSaveFPRegs); |
3558 } else if (IsFastSmiElementsKind(from_kind) && | 3548 } else if (from_kind == FAST_SMI_ONLY_ELEMENTS && |
3559 IsFastDoubleElementsKind(to_kind)) { | 3549 to_kind == FAST_DOUBLE_ELEMENTS) { |
3560 Register fixed_object_reg = ToRegister(instr->temp_reg()); | 3550 Register fixed_object_reg = ToRegister(instr->temp_reg()); |
3561 ASSERT(fixed_object_reg.is(rdx)); | 3551 ASSERT(fixed_object_reg.is(rdx)); |
3562 ASSERT(new_map_reg.is(rbx)); | 3552 ASSERT(new_map_reg.is(rbx)); |
3563 __ movq(fixed_object_reg, object_reg); | 3553 __ movq(fixed_object_reg, object_reg); |
3564 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), | 3554 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), |
3565 RelocInfo::CODE_TARGET, instr); | 3555 RelocInfo::CODE_TARGET, instr); |
3566 } else if (IsFastDoubleElementsKind(from_kind) && | 3556 } else if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { |
3567 IsFastObjectElementsKind(to_kind)) { | |
3568 Register fixed_object_reg = ToRegister(instr->temp_reg()); | 3557 Register fixed_object_reg = ToRegister(instr->temp_reg()); |
3569 ASSERT(fixed_object_reg.is(rdx)); | 3558 ASSERT(fixed_object_reg.is(rdx)); |
3570 ASSERT(new_map_reg.is(rbx)); | 3559 ASSERT(new_map_reg.is(rbx)); |
3571 __ movq(fixed_object_reg, object_reg); | 3560 __ movq(fixed_object_reg, object_reg); |
3572 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), | 3561 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), |
3573 RelocInfo::CODE_TARGET, instr); | 3562 RelocInfo::CODE_TARGET, instr); |
3574 } else { | 3563 } else { |
3575 UNREACHABLE(); | 3564 UNREACHABLE(); |
3576 } | 3565 } |
3577 __ bind(¬_applicable); | 3566 __ bind(¬_applicable); |
(...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4231 } | 4220 } |
4232 | 4221 |
4233 | 4222 |
4234 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { | 4223 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { |
4235 Heap* heap = isolate()->heap(); | 4224 Heap* heap = isolate()->heap(); |
4236 ElementsKind boilerplate_elements_kind = | 4225 ElementsKind boilerplate_elements_kind = |
4237 instr->hydrogen()->boilerplate_elements_kind(); | 4226 instr->hydrogen()->boilerplate_elements_kind(); |
4238 | 4227 |
4239 // Deopt if the array literal boilerplate ElementsKind is of a type different | 4228 // Deopt if the array literal boilerplate ElementsKind is of a type different |
4240 // than the expected one. The check isn't necessary if the boilerplate has | 4229 // than the expected one. The check isn't necessary if the boilerplate has |
4241 // already been converted to TERMINAL_FAST_ELEMENTS_KIND. | 4230 // already been converted to FAST_ELEMENTS. |
4242 if (CanTransitionToMoreGeneralFastElementsKind( | 4231 if (boilerplate_elements_kind != FAST_ELEMENTS) { |
4243 boilerplate_elements_kind, true)) { | |
4244 __ LoadHeapObject(rax, instr->hydrogen()->boilerplate_object()); | 4232 __ LoadHeapObject(rax, instr->hydrogen()->boilerplate_object()); |
4245 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 4233 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
4246 // Load the map's "bit field 2". | 4234 // Load the map's "bit field 2". |
4247 __ movb(rbx, FieldOperand(rbx, Map::kBitField2Offset)); | 4235 __ movb(rbx, FieldOperand(rbx, Map::kBitField2Offset)); |
4248 // Retrieve elements_kind from bit field 2. | 4236 // Retrieve elements_kind from bit field 2. |
4249 __ and_(rbx, Immediate(Map::kElementsKindMask)); | 4237 __ and_(rbx, Immediate(Map::kElementsKindMask)); |
4250 __ cmpb(rbx, Immediate(boilerplate_elements_kind << | 4238 __ cmpb(rbx, Immediate(boilerplate_elements_kind << |
4251 Map::kElementsKindShift)); | 4239 Map::kElementsKindShift)); |
4252 DeoptimizeIf(not_equal, instr->environment()); | 4240 DeoptimizeIf(not_equal, instr->environment()); |
4253 } | 4241 } |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4379 } | 4367 } |
4380 } | 4368 } |
4381 } | 4369 } |
4382 | 4370 |
4383 | 4371 |
4384 void LCodeGen::DoFastLiteral(LFastLiteral* instr) { | 4372 void LCodeGen::DoFastLiteral(LFastLiteral* instr) { |
4385 int size = instr->hydrogen()->total_size(); | 4373 int size = instr->hydrogen()->total_size(); |
4386 ElementsKind boilerplate_elements_kind = | 4374 ElementsKind boilerplate_elements_kind = |
4387 instr->hydrogen()->boilerplate()->GetElementsKind(); | 4375 instr->hydrogen()->boilerplate()->GetElementsKind(); |
4388 | 4376 |
4389 // Deopt if the array literal boilerplate ElementsKind is of a type different | 4377 // Deopt if the literal boilerplate ElementsKind is of a type different than |
4390 // than the expected one. The check isn't necessary if the boilerplate has | 4378 // the expected one. The check isn't necessary if the boilerplate has already |
4391 // already been converted to TERMINAL_FAST_ELEMENTS_KIND. | 4379 // been converted to FAST_ELEMENTS. |
4392 if (CanTransitionToMoreGeneralFastElementsKind( | 4380 if (boilerplate_elements_kind != FAST_ELEMENTS) { |
4393 boilerplate_elements_kind, true)) { | |
4394 __ LoadHeapObject(rbx, instr->hydrogen()->boilerplate()); | 4381 __ LoadHeapObject(rbx, instr->hydrogen()->boilerplate()); |
4395 __ movq(rcx, FieldOperand(rbx, HeapObject::kMapOffset)); | 4382 __ movq(rcx, FieldOperand(rbx, HeapObject::kMapOffset)); |
4396 // Load the map's "bit field 2". | 4383 // Load the map's "bit field 2". |
4397 __ movb(rcx, FieldOperand(rcx, Map::kBitField2Offset)); | 4384 __ movb(rcx, FieldOperand(rcx, Map::kBitField2Offset)); |
4398 // Retrieve elements_kind from bit field 2. | 4385 // Retrieve elements_kind from bit field 2. |
4399 __ and_(rcx, Immediate(Map::kElementsKindMask)); | 4386 __ and_(rcx, Immediate(Map::kElementsKindMask)); |
4400 __ cmpb(rcx, Immediate(boilerplate_elements_kind << | 4387 __ cmpb(rcx, Immediate(boilerplate_elements_kind << |
4401 Map::kElementsKindShift)); | 4388 Map::kElementsKindShift)); |
4402 DeoptimizeIf(not_equal, instr->environment()); | 4389 DeoptimizeIf(not_equal, instr->environment()); |
4403 } | 4390 } |
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4879 FixedArray::kHeaderSize - kPointerSize)); | 4866 FixedArray::kHeaderSize - kPointerSize)); |
4880 __ bind(&done); | 4867 __ bind(&done); |
4881 } | 4868 } |
4882 | 4869 |
4883 | 4870 |
4884 #undef __ | 4871 #undef __ |
4885 | 4872 |
4886 } } // namespace v8::internal | 4873 } } // namespace v8::internal |
4887 | 4874 |
4888 #endif // V8_TARGET_ARCH_X64 | 4875 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |