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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 | 44 |
45 | 45 |
46 void FastCodeGenerator::EmitLoadReceiver() { | 46 void FastCodeGenerator::EmitLoadReceiver() { |
47 // Offset 2 is due to return address and saved frame pointer. | 47 // Offset 2 is due to return address and saved frame pointer. |
48 int index = 2 + function()->scope()->num_parameters(); | 48 int index = 2 + function()->scope()->num_parameters(); |
49 __ mov(receiver_reg(), Operand(ebp, index * kPointerSize)); | 49 __ mov(receiver_reg(), Operand(ebp, index * kPointerSize)); |
50 } | 50 } |
51 | 51 |
52 | 52 |
53 void FastCodeGenerator::EmitGlobalVariableLoad(Handle<Object> cell) { | 53 void FastCodeGenerator::EmitGlobalVariableLoad(Handle<Object> cell) { |
| 54 ASSERT(!destination().is(no_reg)); |
54 ASSERT(cell->IsJSGlobalPropertyCell()); | 55 ASSERT(cell->IsJSGlobalPropertyCell()); |
55 __ mov(accumulator0(), Immediate(cell)); | 56 |
56 __ mov(accumulator0(), | 57 __ mov(destination(), Immediate(cell)); |
57 FieldOperand(accumulator0(), JSGlobalPropertyCell::kValueOffset)); | 58 __ mov(destination(), |
| 59 FieldOperand(destination(), JSGlobalPropertyCell::kValueOffset)); |
58 if (FLAG_debug_code) { | 60 if (FLAG_debug_code) { |
59 __ cmp(accumulator0(), Factory::the_hole_value()); | 61 __ cmp(destination(), Factory::the_hole_value()); |
60 __ Check(not_equal, "DontDelete cells can't contain the hole"); | 62 __ Check(not_equal, "DontDelete cells can't contain the hole"); |
61 } | 63 } |
62 } | 64 } |
63 | 65 |
64 | 66 |
65 void FastCodeGenerator::EmitThisPropertyStore(Handle<String> name) { | 67 void FastCodeGenerator::EmitThisPropertyStore(Handle<String> name) { |
66 LookupResult lookup; | 68 LookupResult lookup; |
67 info()->receiver()->Lookup(*name, &lookup); | 69 info()->receiver()->Lookup(*name, &lookup); |
68 | 70 |
69 ASSERT(lookup.holder() == *info()->receiver()); | 71 ASSERT(lookup.holder() == *info()->receiver()); |
70 ASSERT(lookup.type() == FIELD); | 72 ASSERT(lookup.type() == FIELD); |
71 Handle<Map> map(Handle<HeapObject>::cast(info()->receiver())->map()); | 73 Handle<Map> map(Handle<HeapObject>::cast(info()->receiver())->map()); |
72 int index = lookup.GetFieldIndex() - map->inobject_properties(); | 74 int index = lookup.GetFieldIndex() - map->inobject_properties(); |
73 int offset = index * kPointerSize; | 75 int offset = index * kPointerSize; |
74 | 76 |
75 // Negative offsets are inobject properties. | 77 // Negative offsets are inobject properties. |
76 if (offset < 0) { | 78 if (offset < 0) { |
77 offset += map->instance_size(); | 79 offset += map->instance_size(); |
78 __ mov(scratch0(), receiver_reg()); // Copy receiver for write barrier. | 80 __ mov(scratch0(), receiver_reg()); // Copy receiver for write barrier. |
79 } else { | 81 } else { |
80 offset += FixedArray::kHeaderSize; | 82 offset += FixedArray::kHeaderSize; |
81 __ mov(scratch0(), | 83 __ mov(scratch0(), |
82 FieldOperand(receiver_reg(), JSObject::kPropertiesOffset)); | 84 FieldOperand(receiver_reg(), JSObject::kPropertiesOffset)); |
83 } | 85 } |
84 // Perform the store. | 86 // Perform the store. |
85 __ mov(FieldOperand(scratch0(), offset), accumulator0()); | 87 __ mov(FieldOperand(scratch0(), offset), accumulator0()); |
86 // Preserve value from write barrier in case it's needed. | 88 if (destination().is(no_reg)) { |
87 __ mov(accumulator1(), accumulator0()); | 89 __ RecordWrite(scratch0(), offset, accumulator0(), scratch1()); |
88 // The other accumulator register is available as a scratch register | 90 } else { |
89 // because this is not an AST leaf node. | 91 // Copy the value to the other accumulator to preserve a copy from the |
90 __ RecordWrite(scratch0(), offset, accumulator1(), scratch1()); | 92 // write barrier. One of the accumulators is available as a scratch |
| 93 // register. |
| 94 __ mov(accumulator1(), accumulator0()); |
| 95 Register value_scratch = other_accumulator(destination()); |
| 96 __ RecordWrite(scratch0(), offset, value_scratch, scratch1()); |
| 97 } |
91 } | 98 } |
92 | 99 |
93 | 100 |
| 101 void FastCodeGenerator::EmitThisPropertyLoad(Handle<String> name) { |
| 102 ASSERT(!destination().is(no_reg)); |
| 103 LookupResult lookup; |
| 104 info()->receiver()->Lookup(*name, &lookup); |
| 105 |
| 106 ASSERT(lookup.holder() == *info()->receiver()); |
| 107 ASSERT(lookup.type() == FIELD); |
| 108 Handle<Map> map(Handle<HeapObject>::cast(info()->receiver())->map()); |
| 109 int index = lookup.GetFieldIndex() - map->inobject_properties(); |
| 110 int offset = index * kPointerSize; |
| 111 |
| 112 // Perform the load. Negative offsets are inobject properties. |
| 113 if (offset < 0) { |
| 114 offset += map->instance_size(); |
| 115 __ mov(destination(), FieldOperand(receiver_reg(), offset)); |
| 116 } else { |
| 117 offset += FixedArray::kHeaderSize; |
| 118 __ mov(scratch0(), |
| 119 FieldOperand(receiver_reg(), JSObject::kPropertiesOffset)); |
| 120 __ mov(destination(), FieldOperand(scratch0(), offset)); |
| 121 } |
| 122 } |
| 123 |
| 124 |
| 125 void FastCodeGenerator::EmitBitOr() { |
| 126 Register copied; // One operand is copied to a scratch register. |
| 127 Register other; // The other is not modified by the operation. |
| 128 Register check; // A register is used for the smi check/operation. |
| 129 if (destination().is(no_reg)) { |
| 130 copied = accumulator1(); // Arbitrary choice of operand to copy. |
| 131 other = accumulator0(); |
| 132 check = scratch0(); // Do not clobber either operand register. |
| 133 } else { |
| 134 copied = destination(); |
| 135 other = other_accumulator(destination()); |
| 136 check = destination(); |
| 137 } |
| 138 __ mov(scratch0(), copied); |
| 139 __ or_(check, Operand(other)); |
| 140 __ test(check, Immediate(kSmiTagMask)); |
| 141 |
| 142 // Restore the clobbered operand if necessary. |
| 143 if (destination().is(no_reg)) { |
| 144 __ j(not_zero, bailout(), not_taken); |
| 145 } else { |
| 146 Label done; |
| 147 __ j(zero, &done, taken); |
| 148 __ mov(copied, scratch0()); |
| 149 __ jmp(bailout()); |
| 150 __ bind(&done); |
| 151 } |
| 152 } |
| 153 |
| 154 |
94 void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { | 155 void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { |
95 ASSERT(info_ == NULL); | 156 ASSERT(info_ == NULL); |
96 info_ = compilation_info; | 157 info_ = compilation_info; |
97 | 158 |
98 // Save the caller's frame pointer and set up our own. | 159 // Save the caller's frame pointer and set up our own. |
99 Comment prologue_cmnt(masm(), ";; Prologue"); | 160 Comment prologue_cmnt(masm(), ";; Prologue"); |
100 __ push(ebp); | 161 __ push(ebp); |
101 __ mov(ebp, esp); | 162 __ mov(ebp, esp); |
102 __ push(esi); // Context. | 163 __ push(esi); // Context. |
103 __ push(edi); // Closure. | 164 __ push(edi); // Closure. |
104 // Note that we keep a live register reference to esi (context) at this | 165 // Note that we keep a live register reference to esi (context) at this |
105 // point. | 166 // point. |
106 | 167 |
107 // Receiver (this) is allocated to a fixed register. | 168 // Receiver (this) is allocated to a fixed register. |
108 if (info()->has_this_properties()) { | 169 if (info()->has_this_properties()) { |
109 Comment cmnt(masm(), ";; MapCheck(this)"); | 170 Comment cmnt(masm(), ";; MapCheck(this)"); |
110 if (FLAG_print_ir) { | 171 if (FLAG_print_ir) { |
111 PrintF("MapCheck(this)\n"); | 172 PrintF("#: MapCheck(this)\n"); |
112 } | 173 } |
113 ASSERT(info()->has_receiver() && info()->receiver()->IsHeapObject()); | 174 ASSERT(info()->has_receiver() && info()->receiver()->IsHeapObject()); |
114 Handle<HeapObject> object = Handle<HeapObject>::cast(info()->receiver()); | 175 Handle<HeapObject> object = Handle<HeapObject>::cast(info()->receiver()); |
115 Handle<Map> map(object->map()); | 176 Handle<Map> map(object->map()); |
116 EmitLoadReceiver(); | 177 EmitLoadReceiver(); |
117 __ CheckMap(receiver_reg(), map, bailout(), false); | 178 __ CheckMap(receiver_reg(), map, bailout(), false); |
118 } | 179 } |
119 | 180 |
120 // If there is a global variable access check if the global object is the | 181 // If there is a global variable access check if the global object is the |
121 // same as at lazy-compilation time. | 182 // same as at lazy-compilation time. |
122 if (info()->has_globals()) { | 183 if (info()->has_globals()) { |
123 Comment cmnt(masm(), ";; MapCheck(GLOBAL)"); | 184 Comment cmnt(masm(), ";; MapCheck(GLOBAL)"); |
124 if (FLAG_print_ir) { | 185 if (FLAG_print_ir) { |
125 PrintF("MapCheck(GLOBAL)\n"); | 186 PrintF("#: MapCheck(GLOBAL)\n"); |
126 } | 187 } |
127 ASSERT(info()->has_global_object()); | 188 ASSERT(info()->has_global_object()); |
128 Handle<Map> map(info()->global_object()->map()); | 189 Handle<Map> map(info()->global_object()->map()); |
129 __ mov(scratch0(), CodeGenerator::GlobalObject()); | 190 __ mov(scratch0(), CodeGenerator::GlobalObject()); |
130 __ CheckMap(scratch0(), map, bailout(), true); | 191 __ CheckMap(scratch0(), map, bailout(), true); |
131 } | 192 } |
132 | 193 |
133 VisitStatements(function()->body()); | 194 VisitStatements(function()->body()); |
134 | 195 |
135 Comment return_cmnt(masm(), ";; Return(<undefined>)"); | 196 Comment return_cmnt(masm(), ";; Return(<undefined>)"); |
136 if (FLAG_print_ir) { | 197 if (FLAG_print_ir) { |
137 PrintF("Return(<undefined>)\n"); | 198 PrintF("#: Return(<undefined>)\n"); |
138 } | 199 } |
139 __ mov(eax, Factory::undefined_value()); | 200 __ mov(eax, Factory::undefined_value()); |
140 __ mov(esp, ebp); | 201 __ mov(esp, ebp); |
141 __ pop(ebp); | 202 __ pop(ebp); |
142 __ ret((scope()->num_parameters() + 1) * kPointerSize); | 203 __ ret((scope()->num_parameters() + 1) * kPointerSize); |
143 | 204 |
144 __ bind(&bailout_); | 205 __ bind(&bailout_); |
145 } | 206 } |
146 | 207 |
147 | 208 |
148 #undef __ | 209 #undef __ |
149 | 210 |
150 | 211 |
151 } } // namespace v8::internal | 212 } } // namespace v8::internal |
OLD | NEW |