| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 17 matching lines...) Expand all Loading... |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "codegen-inl.h" | 30 #include "codegen-inl.h" |
| 31 #include "fast-codegen.h" | 31 #include "fast-codegen.h" |
| 32 | 32 |
| 33 namespace v8 { | 33 namespace v8 { |
| 34 namespace internal { | 34 namespace internal { |
| 35 | 35 |
| 36 #define __ ACCESS_MASM(masm()) | 36 #define __ ACCESS_MASM(masm()) |
| 37 | 37 |
| 38 // Registers rcx, rdi, and r8-r15 are free to use as scratch registers | |
| 39 // without saving and restoring any other registers. | |
| 40 Register FastCodeGenerator::accumulator0() { return rax; } | 38 Register FastCodeGenerator::accumulator0() { return rax; } |
| 41 Register FastCodeGenerator::accumulator1() { return rdx; } | 39 Register FastCodeGenerator::accumulator1() { return rdx; } |
| 42 Register FastCodeGenerator::scratch0() { return rcx; } | 40 Register FastCodeGenerator::scratch0() { return rcx; } |
| 43 Register FastCodeGenerator::scratch1() { return rdi; } | 41 Register FastCodeGenerator::scratch1() { return rdi; } |
| 44 Register FastCodeGenerator::receiver_reg() { return rbx; } | 42 Register FastCodeGenerator::receiver_reg() { return rbx; } |
| 45 Register FastCodeGenerator::context_reg() { return rsi; } | 43 Register FastCodeGenerator::context_reg() { return rsi; } |
| 46 | 44 |
| 47 | 45 |
| 48 void FastCodeGenerator::EmitLoadReceiver() { | 46 void FastCodeGenerator::EmitLoadReceiver() { |
| 49 // Offset 2 is due to return address and saved frame pointer. | 47 // Offset 2 is due to return address and saved frame pointer. |
| 50 int index = 2 + scope()->num_parameters(); | 48 int index = 2 + scope()->num_parameters(); |
| 51 __ movq(receiver_reg(), Operand(rbp, index * kPointerSize)); | 49 __ movq(receiver_reg(), Operand(rbp, index * kPointerSize)); |
| 52 } | 50 } |
| 53 | 51 |
| 54 | 52 |
| 55 void FastCodeGenerator::EmitGlobalVariableLoad(Handle<Object> cell) { | 53 void FastCodeGenerator::EmitGlobalVariableLoad(Handle<Object> cell) { |
| 54 ASSERT(!destination().is(no_reg)); |
| 56 ASSERT(cell->IsJSGlobalPropertyCell()); | 55 ASSERT(cell->IsJSGlobalPropertyCell()); |
| 57 __ Move(accumulator0(), cell); | 56 __ Move(destination(), cell); |
| 58 __ movq(accumulator0(), | 57 __ movq(destination(), |
| 59 FieldOperand(accumulator0(), JSGlobalPropertyCell::kValueOffset)); | 58 FieldOperand(destination(), JSGlobalPropertyCell::kValueOffset)); |
| 60 if (FLAG_debug_code) { | 59 if (FLAG_debug_code) { |
| 61 __ Cmp(accumulator0(), Factory::the_hole_value()); | 60 __ Cmp(destination(), Factory::the_hole_value()); |
| 62 __ Check(not_equal, "DontDelete cells can't contain the hole"); | 61 __ Check(not_equal, "DontDelete cells can't contain the hole"); |
| 63 } | 62 } |
| 64 } | 63 } |
| 65 | 64 |
| 66 | 65 |
| 67 void FastCodeGenerator::EmitThisPropertyStore(Handle<String> name) { | 66 void FastCodeGenerator::EmitThisPropertyStore(Handle<String> name) { |
| 68 LookupResult lookup; | 67 LookupResult lookup; |
| 69 info()->receiver()->Lookup(*name, &lookup); | 68 info()->receiver()->Lookup(*name, &lookup); |
| 70 | 69 |
| 71 ASSERT(lookup.holder() == *info()->receiver()); | 70 ASSERT(lookup.holder() == *info()->receiver()); |
| 72 ASSERT(lookup.type() == FIELD); | 71 ASSERT(lookup.type() == FIELD); |
| 73 Handle<Map> map(Handle<HeapObject>::cast(info()->receiver())->map()); | 72 Handle<Map> map(Handle<HeapObject>::cast(info()->receiver())->map()); |
| 74 int index = lookup.GetFieldIndex() - map->inobject_properties(); | 73 int index = lookup.GetFieldIndex() - map->inobject_properties(); |
| 75 int offset = index * kPointerSize; | 74 int offset = index * kPointerSize; |
| 76 | 75 |
| 77 // Negative offsets are inobject properties. | 76 // Negative offsets are inobject properties. |
| 78 if (offset < 0) { | 77 if (offset < 0) { |
| 79 offset += map->instance_size(); | 78 offset += map->instance_size(); |
| 80 __ movq(scratch0(), receiver_reg()); // Copy receiver for write barrier. | 79 __ movq(scratch0(), receiver_reg()); // Copy receiver for write barrier. |
| 81 } else { | 80 } else { |
| 82 offset += FixedArray::kHeaderSize; | 81 offset += FixedArray::kHeaderSize; |
| 83 __ movq(scratch0(), | 82 __ movq(scratch0(), |
| 84 FieldOperand(receiver_reg(), JSObject::kPropertiesOffset)); | 83 FieldOperand(receiver_reg(), JSObject::kPropertiesOffset)); |
| 85 } | 84 } |
| 86 // Perform the store. | 85 // Perform the store. |
| 87 __ movq(FieldOperand(scratch0(), offset), accumulator0()); | 86 __ movq(FieldOperand(scratch0(), offset), accumulator0()); |
| 88 // Preserve value from write barrier in case it's needed. | 87 if (destination().is(no_reg)) { |
| 89 __ movq(accumulator1(), accumulator0()); | 88 __ RecordWrite(scratch0(), offset, accumulator0(), scratch1()); |
| 90 // The other accumulator register is available as a scratch register | 89 } else { |
| 91 // because this is not an AST leaf node. | 90 // Copy the value to the other accumulator to preserve a copy from the |
| 92 __ RecordWrite(scratch0(), offset, accumulator1(), scratch1()); | 91 // write barrier. One of the accumulators is available as a scratch |
| 92 // register. |
| 93 __ movq(accumulator1(), accumulator0()); |
| 94 Register value_scratch = other_accumulator(destination()); |
| 95 __ RecordWrite(scratch0(), offset, value_scratch, scratch1()); |
| 96 } |
| 93 } | 97 } |
| 94 | 98 |
| 95 | 99 |
| 100 void FastCodeGenerator::EmitThisPropertyLoad(Handle<String> name) { |
| 101 ASSERT(!destination().is(no_reg)); |
| 102 LookupResult lookup; |
| 103 info()->receiver()->Lookup(*name, &lookup); |
| 104 |
| 105 ASSERT(lookup.holder() == *info()->receiver()); |
| 106 ASSERT(lookup.type() == FIELD); |
| 107 Handle<Map> map(Handle<HeapObject>::cast(info()->receiver())->map()); |
| 108 int index = lookup.GetFieldIndex() - map->inobject_properties(); |
| 109 int offset = index * kPointerSize; |
| 110 |
| 111 // Perform the load. Negative offsets are inobject properties. |
| 112 if (offset < 0) { |
| 113 offset += map->instance_size(); |
| 114 __ movq(destination(), FieldOperand(receiver_reg(), offset)); |
| 115 } else { |
| 116 offset += FixedArray::kHeaderSize; |
| 117 __ movq(scratch0(), |
| 118 FieldOperand(receiver_reg(), JSObject::kPropertiesOffset)); |
| 119 __ movq(destination(), FieldOperand(scratch0(), offset)); |
| 120 } |
| 121 } |
| 122 |
| 123 |
| 124 void FastCodeGenerator::EmitBitOr() { |
| 125 Register copied; // One operand is copied to a scratch register. |
| 126 Register other; // The other is not modified by the operation. |
| 127 Register check; // A register is used for the smi check/operation. |
| 128 if (destination().is(no_reg)) { |
| 129 copied = accumulator1(); // Arbitrary choice of operand to copy. |
| 130 other = accumulator0(); |
| 131 check = scratch0(); // Do not clobber either operand register. |
| 132 } else { |
| 133 copied = destination(); |
| 134 other = other_accumulator(destination()); |
| 135 check = destination(); |
| 136 } |
| 137 __ movq(scratch0(), copied); |
| 138 __ or_(check, other); |
| 139 // Restore the clobbered operand if necessary. |
| 140 if (destination().is(no_reg)) { |
| 141 __ JumpIfNotSmi(check, bailout()); |
| 142 } else { |
| 143 Label done; |
| 144 __ JumpIfSmi(check, &done); |
| 145 __ movq(copied, scratch0()); |
| 146 __ jmp(bailout()); |
| 147 __ bind(&done); |
| 148 } |
| 149 } |
| 150 |
| 151 |
| 96 void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { | 152 void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { |
| 97 ASSERT(info_ == NULL); | 153 ASSERT(info_ == NULL); |
| 98 info_ = compilation_info; | 154 info_ = compilation_info; |
| 99 | 155 |
| 100 // Save the caller's frame pointer and set up our own. | 156 // Save the caller's frame pointer and set up our own. |
| 101 Comment prologue_cmnt(masm(), ";; Prologue"); | 157 Comment prologue_cmnt(masm(), ";; Prologue"); |
| 102 __ push(rbp); | 158 __ push(rbp); |
| 103 __ movq(rbp, rsp); | 159 __ movq(rbp, rsp); |
| 104 __ push(rsi); // Context. | 160 __ push(rsi); // Context. |
| 105 __ push(rdi); // Closure. | 161 __ push(rdi); // Closure. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 __ ret((scope()->num_parameters() + 1) * kPointerSize); | 200 __ ret((scope()->num_parameters() + 1) * kPointerSize); |
| 145 | 201 |
| 146 __ bind(&bailout_); | 202 __ bind(&bailout_); |
| 147 } | 203 } |
| 148 | 204 |
| 149 | 205 |
| 150 #undef __ | 206 #undef __ |
| 151 | 207 |
| 152 | 208 |
| 153 } } // namespace v8::internal | 209 } } // namespace v8::internal |
| OLD | NEW |