Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(535)

Side by Side Diff: src/x64/codegen-x64.cc

Issue 141056: x64: Generate code for loading from, storing to and calling properties. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/assembler-x64.cc ('k') | src/x64/frames-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 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 11 matching lines...) Expand all
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 28
29 #include "v8.h" 29 #include "v8.h"
30 30
31 #include "bootstrapper.h" 31 #include "bootstrapper.h"
32 // #include "macro-assembler.h"
33 #include "codegen-inl.h" 32 #include "codegen-inl.h"
33 #include "debug.h"
34 #include "ic-inl.h"
35 #include "parser.h"
34 #include "register-allocator-inl.h" 36 #include "register-allocator-inl.h"
37 #include "scopes.h"
35 38
36 // TEST 39 // TEST
37 #include "compiler.h" 40 #include "compiler.h"
38 41
39 namespace v8 { 42 namespace v8 {
40 namespace internal { 43 namespace internal {
41 44
42 #define __ ACCESS_MASM(masm_) 45 #define __ ACCESS_MASM(masm_)
43 46
44 // ------------------------------------------------------------------------- 47 // -------------------------------------------------------------------------
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 " var w; y = x; x = w; w = y; y = x; return w;" 163 " var w; y = x; x = w; w = y; y = x; return w;"
161 " };" 164 " };"
162 " test_local_variables(2,3);" 165 " test_local_variables(2,3);"
163 " function test_nesting_calls(x, y, zee){return zee;};" 166 " function test_nesting_calls(x, y, zee){return zee;};"
164 " test_local_variables(" 167 " test_local_variables("
165 " test_nesting_calls(test_local_variables(1,3), 42, 47)," 168 " test_nesting_calls(test_local_variables(1,3), 42, 47),"
166 " test_local_variables(-25.3, 2));" 169 " test_local_variables(-25.3, 2));"
167 " // return test_recursion_with_base(0, 0, 0, 47);\n" 170 " // return test_recursion_with_base(0, 0, 0, 47);\n"
168 " var x_value = 42;" 171 " var x_value = 42;"
169 " var o = { x: x_value };" 172 " var o = { x: x_value };"
173 " o.x = 43;"
174 " o.x;"
175 " var x_string = 'x';"
176 " o[x_string] = 44;"
177 " o[x_string];"
178 " o.f = function() { return 45; };"
179 " o.f();"
180 " var f_string = 'f';"
181 " o[f_string]();"
William Hesse 2009/06/22 21:31:29 Now that if ... then is working, we can check all
170 " var a = [ 1, 2, 3 ];" 182 " var a = [ 1, 2, 3 ];"
171 " var x = true ? 42 : 32;" 183 " var x = true ? 42 : 32;"
172 " return test_if_then_else(0, 46, 47);" 184 " return test_if_then_else(0, 46, 47);"
173 "})()")), 185 "})()")),
174 Factory::NewStringFromAscii(CStrVector("CodeGeneratorTestScript")), 186 Factory::NewStringFromAscii(CStrVector("CodeGeneratorTestScript")),
175 0, 187 0,
176 0, 188 0,
177 NULL, 189 NULL,
178 NULL); 190 NULL);
179 191
(...skipping 969 matching lines...) Expand 10 before | Expand all | Expand 10 after
1149 // first value pushed as part of the reference, which is below 1161 // first value pushed as part of the reference, which is below
1150 // the lhs value. 1162 // the lhs value.
1151 frame_->PushElementAt(target.size()); 1163 frame_->PushElementAt(target.size());
1152 // Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1); 1164 // Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1);
1153 } 1165 }
1154 } 1166 }
1155 } 1167 }
1156 } 1168 }
1157 1169
1158 1170
1159 void CodeGenerator::VisitThrow(Throw* a) { 1171 void CodeGenerator::VisitThrow(Throw* node) {
1160 // UNIMPLEMENTED(); 1172 Comment cmnt(masm_, "[ Throw");
1161 } 1173 CodeForStatementPosition(node);
1162 1174
1163 void CodeGenerator::VisitProperty(Property* a) { 1175 Load(node->exception());
1164 UNIMPLEMENTED(); 1176 Result result = frame_->CallRuntime(Runtime::kThrow, 1);
1177 frame_->Push(&result);
1165 } 1178 }
1166 1179
1167 1180
1181 void CodeGenerator::VisitProperty(Property* node) {
1182 Comment cmnt(masm_, "[ Property");
1183 Reference property(this, node);
1184 property.GetValue(typeof_state());
1185 }
1186
1187
1168 void CodeGenerator::VisitCall(Call* node) { 1188 void CodeGenerator::VisitCall(Call* node) {
1169 Comment cmnt(masm_, "[ Call"); 1189 Comment cmnt(masm_, "[ Call");
1170 1190
1171 ZoneList<Expression*>* args = node->arguments(); 1191 ZoneList<Expression*>* args = node->arguments();
1172 1192
1173 CodeForStatementPosition(node); 1193 CodeForStatementPosition(node);
1174 1194
1175 // Check if the function is a variable or a property. 1195 // Check if the function is a variable or a property.
1176 Expression* function = node->expression(); 1196 Expression* function = node->expression();
1177 Variable* var = function->AsVariableProxy()->AsVariable(); 1197 Variable* var = function->AsVariableProxy()->AsVariable();
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1237 frame_->EmitPush(eax); 1257 frame_->EmitPush(eax);
1238 1258
1239 // Load the receiver. 1259 // Load the receiver.
1240 ASSERT(!allocator()->is_used(edx)); 1260 ASSERT(!allocator()->is_used(edx));
1241 frame_->EmitPush(edx); 1261 frame_->EmitPush(edx);
1242 1262
1243 // Call the function. 1263 // Call the function.
1244 CallWithArguments(args, node->position()); 1264 CallWithArguments(args, node->position());
1245 */ 1265 */
1246 } else if (property != NULL) { 1266 } else if (property != NULL) {
1247 UNIMPLEMENTED();
1248 /*
1249 // Check if the key is a literal string. 1267 // Check if the key is a literal string.
1250 Literal* literal = property->key()->AsLiteral(); 1268 Literal* literal = property->key()->AsLiteral();
1251 1269
1252 if (literal != NULL && literal->handle()->IsSymbol()) { 1270 if (literal != NULL && literal->handle()->IsSymbol()) {
1253 // ------------------------------------------------------------------ 1271 // ------------------------------------------------------------------
1254 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)' 1272 // JavaScript example: 'object.foo(1, 2, 3)' or 'map["key"](1, 2, 3)'
1255 // ------------------------------------------------------------------ 1273 // ------------------------------------------------------------------
1256 1274
1257 // Push the name of the function and the receiver onto the stack. 1275 // Push the name of the function and the receiver onto the stack.
1258 frame_->Push(literal->handle()); 1276 frame_->Push(literal->handle());
(...skipping 27 matching lines...) Expand all
1286 // Use global object as receiver. 1304 // Use global object as receiver.
1287 LoadGlobalReceiver(); 1305 LoadGlobalReceiver();
1288 } else { 1306 } else {
1289 // The reference's size is non-negative. 1307 // The reference's size is non-negative.
1290 frame_->PushElementAt(ref.size()); 1308 frame_->PushElementAt(ref.size());
1291 } 1309 }
1292 1310
1293 // Call the function. 1311 // Call the function.
1294 CallWithArguments(args, node->position()); 1312 CallWithArguments(args, node->position());
1295 } 1313 }
1296 */ 1314
1297 } else { 1315 } else {
1298 // ---------------------------------- 1316 // ----------------------------------
1299 // JavaScript example: 'foo(1, 2, 3)' // foo is not global 1317 // JavaScript example: 'foo(1, 2, 3)' // foo is not global
1300 // ---------------------------------- 1318 // ----------------------------------
1301 1319
1302 // Load the function. 1320 // Load the function.
1303 Load(function); 1321 Load(function);
1304 1322
1305 // Pass the global proxy as the receiver. 1323 // Pass the global proxy as the receiver.
1306 LoadGlobalReceiver(); 1324 LoadGlobalReceiver();
1307 1325
1308 // Call the function. 1326 // Call the function.
1309 CallWithArguments(args, node->position()); 1327 CallWithArguments(args, node->position());
1310 } 1328 }
1311 } 1329 }
1312 1330
1313 1331
1314 void CodeGenerator::VisitCallEval(CallEval* a) { 1332 void CodeGenerator::VisitCallEval(CallEval* a) {
1315 UNIMPLEMENTED(); 1333 UNIMPLEMENTED();
1316 } 1334 }
1317 1335
1336
1318 void CodeGenerator::VisitCallNew(CallNew* a) { 1337 void CodeGenerator::VisitCallNew(CallNew* a) {
1319 UNIMPLEMENTED(); 1338 UNIMPLEMENTED();
1320 } 1339 }
1321 1340
1341
1322 void CodeGenerator::VisitCallRuntime(CallRuntime* a) { 1342 void CodeGenerator::VisitCallRuntime(CallRuntime* a) {
1323 UNIMPLEMENTED(); 1343 UNIMPLEMENTED();
1324 } 1344 }
1325 1345
1326 1346
1327 void CodeGenerator::VisitUnaryOperation(UnaryOperation* a) { 1347 void CodeGenerator::VisitUnaryOperation(UnaryOperation* a) {
1328 UNIMPLEMENTED(); 1348 UNIMPLEMENTED();
1329 } 1349 }
1330 1350
1331 void CodeGenerator::VisitCountOperation(CountOperation* a) { 1351 void CodeGenerator::VisitCountOperation(CountOperation* a) {
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
1625 } 1645 }
1626 1646
1627 1647
1628 void CodeGenerator::UnloadReference(Reference* ref) { 1648 void CodeGenerator::UnloadReference(Reference* ref) {
1629 // Pop a reference from the stack while preserving TOS. 1649 // Pop a reference from the stack while preserving TOS.
1630 Comment cmnt(masm_, "[ UnloadReference"); 1650 Comment cmnt(masm_, "[ UnloadReference");
1631 frame_->Nip(ref->size()); 1651 frame_->Nip(ref->size());
1632 } 1652 }
1633 1653
1634 1654
1635 void Reference::SetValue(InitState init_state) {
1636 ASSERT(cgen_->HasValidEntryRegisters());
1637 ASSERT(!is_illegal());
1638 MacroAssembler* masm = cgen_->masm();
1639 switch (type_) {
1640 case SLOT: {
1641 Comment cmnt(masm, "[ Store to Slot");
1642 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
1643 ASSERT(slot != NULL);
1644 cgen_->StoreToSlot(slot, init_state);
1645 break;
1646 }
1647 // TODO(X64): Make cases other than SLOT work.
1648 /*
1649 case NAMED: {
1650 Comment cmnt(masm, "[ Store to named Property");
1651 cgen_->frame()->Push(GetName());
1652 Result answer = cgen_->frame()->CallStoreIC();
1653 cgen_->frame()->Push(&answer);
1654 break;
1655 }
1656
1657 case KEYED: {
1658 Comment cmnt(masm, "[ Store to keyed Property");
1659
1660 // Generate inlined version of the keyed store if the code is in
1661 // a loop and the key is likely to be a smi.
1662 Property* property = expression()->AsProperty();
1663 ASSERT(property != NULL);
1664 SmiAnalysis* key_smi_analysis = property->key()->type();
1665
1666 if (cgen_->loop_nesting() > 0 && key_smi_analysis->IsLikelySmi()) {
1667 Comment cmnt(masm, "[ Inlined store to keyed Property");
1668
1669 // Get the receiver, key and value into registers.
1670 Result value = cgen_->frame()->Pop();
1671 Result key = cgen_->frame()->Pop();
1672 Result receiver = cgen_->frame()->Pop();
1673
1674 Result tmp = cgen_->allocator_->Allocate();
1675 ASSERT(tmp.is_valid());
1676
1677 // Determine whether the value is a constant before putting it
1678 // in a register.
1679 bool value_is_constant = value.is_constant();
1680
1681 // Make sure that value, key and receiver are in registers.
1682 value.ToRegister();
1683 key.ToRegister();
1684 receiver.ToRegister();
1685
1686 DeferredReferenceSetKeyedValue* deferred =
1687 new DeferredReferenceSetKeyedValue(value.reg(),
1688 key.reg(),
1689 receiver.reg());
1690
1691 // Check that the value is a smi if it is not a constant. We
1692 // can skip the write barrier for smis and constants.
1693 if (!value_is_constant) {
1694 __ test(value.reg(), Immediate(kSmiTagMask));
1695 deferred->Branch(not_zero);
1696 }
1697
1698 // Check that the key is a non-negative smi.
1699 __ test(key.reg(), Immediate(kSmiTagMask | 0x80000000));
1700 deferred->Branch(not_zero);
1701
1702 // Check that the receiver is not a smi.
1703 __ test(receiver.reg(), Immediate(kSmiTagMask));
1704 deferred->Branch(zero);
1705
1706 // Check that the receiver is a JSArray.
1707 __ mov(tmp.reg(),
1708 FieldOperand(receiver.reg(), HeapObject::kMapOffset));
1709 __ movzx_b(tmp.reg(),
1710 FieldOperand(tmp.reg(), Map::kInstanceTypeOffset));
1711 __ cmp(tmp.reg(), JS_ARRAY_TYPE);
1712 deferred->Branch(not_equal);
1713
1714 // Check that the key is within bounds. Both the key and the
1715 // length of the JSArray are smis.
1716 __ cmp(key.reg(),
1717 FieldOperand(receiver.reg(), JSArray::kLengthOffset));
1718 deferred->Branch(greater_equal);
1719
1720 // Get the elements array from the receiver and check that it
1721 // is not a dictionary.
1722 __ mov(tmp.reg(),
1723 FieldOperand(receiver.reg(), JSObject::kElementsOffset));
1724 // Bind the deferred code patch site to be able to locate the
1725 // fixed array map comparison. When debugging, we patch this
1726 // comparison to always fail so that we will hit the IC call
1727 // in the deferred code which will allow the debugger to
1728 // break for fast case stores.
1729 __ bind(deferred->patch_site());
1730 __ cmp(FieldOperand(tmp.reg(), HeapObject::kMapOffset),
1731 Immediate(Factory::fixed_array_map()));
1732 deferred->Branch(not_equal);
1733
1734 // Store the value.
1735 __ mov(Operand(tmp.reg(),
1736 key.reg(),
1737 times_2,
1738 Array::kHeaderSize - kHeapObjectTag),
1739 value.reg());
1740 __ IncrementCounter(&Counters::keyed_store_inline, 1);
1741
1742 deferred->BindExit();
1743
1744 cgen_->frame()->Push(&receiver);
1745 cgen_->frame()->Push(&key);
1746 cgen_->frame()->Push(&value);
1747 } else {
1748 Result answer = cgen_->frame()->CallKeyedStoreIC();
1749 // Make sure that we do not have a test instruction after the
1750 // call. A test instruction after the call is used to
1751 // indicate that we have generated an inline version of the
1752 // keyed store.
1753 __ nop();
1754 cgen_->frame()->Push(&answer);
1755 }
1756 break;
1757 }
1758 */
1759 default:
1760 UNREACHABLE();
1761 }
1762 }
1763
1764
1765 Operand CodeGenerator::SlotOperand(Slot* slot, Register tmp) { 1655 Operand CodeGenerator::SlotOperand(Slot* slot, Register tmp) {
1766 // Currently, this assertion will fail if we try to assign to 1656 // Currently, this assertion will fail if we try to assign to
1767 // a constant variable that is constant because it is read-only 1657 // a constant variable that is constant because it is read-only
1768 // (such as the variable referring to a named function expression). 1658 // (such as the variable referring to a named function expression).
1769 // We need to implement assignments to read-only variables. 1659 // We need to implement assignments to read-only variables.
1770 // Ideally, we should do this during AST generation (by converting 1660 // Ideally, we should do this during AST generation (by converting
1771 // such assignments into expression statements); however, in general 1661 // such assignments into expression statements); however, in general
1772 // we may not be able to make the decision until past AST generation, 1662 // we may not be able to make the decision until past AST generation,
1773 // that is when the entire program is known. 1663 // that is when the entire program is known.
1774 ASSERT(slot != NULL); 1664 ASSERT(slot != NULL);
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
2050 1940
2051 1941
2052 void CodeGenerator::LoadGlobalReceiver() { 1942 void CodeGenerator::LoadGlobalReceiver() {
2053 Result temp = allocator_->Allocate(); 1943 Result temp = allocator_->Allocate();
2054 Register reg = temp.reg(); 1944 Register reg = temp.reg();
2055 __ movq(reg, GlobalObject()); 1945 __ movq(reg, GlobalObject());
2056 __ movq(reg, FieldOperand(reg, GlobalObject::kGlobalReceiverOffset)); 1946 __ movq(reg, FieldOperand(reg, GlobalObject::kGlobalReceiverOffset));
2057 frame_->Push(&temp); 1947 frame_->Push(&temp);
2058 } 1948 }
2059 1949
1950 // Emit a LoadIC call to get the value from receiver and leave it in
1951 // dst. The receiver register is restored after the call.
1952 class DeferredReferenceGetNamedValue: public DeferredCode {
1953 public:
1954 DeferredReferenceGetNamedValue(Register dst,
1955 Register receiver,
1956 Handle<String> name)
1957 : dst_(dst), receiver_(receiver), name_(name) {
1958 set_comment("[ DeferredReferenceGetNamedValue");
1959 }
1960
1961 virtual void Generate();
1962
1963 Label* patch_site() { return &patch_site_; }
1964
1965 private:
1966 Label patch_site_;
1967 Register dst_;
1968 Register receiver_;
1969 Handle<String> name_;
1970 };
1971
1972
1973 void DeferredReferenceGetNamedValue::Generate() {
1974 __ push(receiver_);
1975 __ Move(rcx, name_);
1976 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1977 __ Call(ic, RelocInfo::CODE_TARGET);
1978 // The call must be followed by a test eax instruction to indicate
1979 // that the inobject property case was inlined.
1980 //
1981 // Store the delta to the map check instruction here in the test
1982 // instruction. Use masm_-> instead of the __ macro since the
1983 // latter can't return a value.
1984 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site());
1985 // Here we use masm_-> instead of the __ macro because this is the
1986 // instruction that gets patched and coverage code gets in the way.
1987 masm_->testq(rax, Immediate(-delta_to_patch_site));
1988 __ IncrementCounter(&Counters::named_load_inline_miss, 1);
1989
1990 if (!dst_.is(rax)) __ movq(dst_, rax);
1991 __ pop(receiver_);
1992 }
1993
2060 1994
2061 #undef __ 1995 #undef __
2062
2063 // End of CodeGenerator implementation.
2064
2065 // -----------------------------------------------------------------------------
2066 // Implementation of stubs.
2067
2068 // Stub classes have public member named masm, not masm_.
2069 #define __ ACCESS_MASM(masm) 1996 #define __ ACCESS_MASM(masm)
2070 1997
2071 1998
1999 Handle<String> Reference::GetName() {
2000 ASSERT(type_ == NAMED);
2001 Property* property = expression_->AsProperty();
2002 if (property == NULL) {
2003 // Global variable reference treated as a named property reference.
2004 VariableProxy* proxy = expression_->AsVariableProxy();
2005 ASSERT(proxy->AsVariable() != NULL);
2006 ASSERT(proxy->AsVariable()->is_global());
2007 return proxy->name();
2008 } else {
2009 Literal* raw_name = property->key()->AsLiteral();
2010 ASSERT(raw_name != NULL);
2011 return Handle<String>(String::cast(*raw_name->handle()));
2012 }
2013 }
2014
2015
2072 void Reference::GetValue(TypeofState typeof_state) { 2016 void Reference::GetValue(TypeofState typeof_state) {
2073 UNIMPLEMENTED(); 2017 ASSERT(!cgen_->in_spilled_code());
2018 ASSERT(cgen_->HasValidEntryRegisters());
2019 ASSERT(!is_illegal());
2020 MacroAssembler* masm = cgen_->masm();
2021 switch (type_) {
2022 case SLOT: {
2023 Comment cmnt(masm, "[ Load from Slot");
2024 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
2025 ASSERT(slot != NULL);
2026 cgen_->LoadFromSlot(slot, typeof_state);
2027 break;
2028 }
2029
2030 case NAMED: {
2031 // TODO(1241834): Make sure that it is safe to ignore the
2032 // distinction between expressions in a typeof and not in a
2033 // typeof. If there is a chance that reference errors can be
2034 // thrown below, we must distinguish between the two kinds of
2035 // loads (typeof expression loads must not throw a reference
2036 // error).
2037 Variable* var = expression_->AsVariableProxy()->AsVariable();
2038 bool is_global = var != NULL;
2039 ASSERT(!is_global || var->is_global());
2040
2041 // Do not inline the inobject property case for loads from the global
2042 // object. Also do not inline for unoptimized code. This saves time
2043 // in the code generator. Unoptimized code is toplevel code or code
2044 // that is not in a loop.
2045 if (is_global ||
2046 cgen_->scope()->is_global_scope() ||
2047 cgen_->loop_nesting() == 0) {
2048 Comment cmnt(masm, "[ Load from named Property");
2049 cgen_->frame()->Push(GetName());
2050
2051 RelocInfo::Mode mode = is_global
2052 ? RelocInfo::CODE_TARGET_CONTEXT
2053 : RelocInfo::CODE_TARGET;
2054 Result answer = cgen_->frame()->CallLoadIC(mode);
2055 // A test eax instruction following the call signals that the
2056 // inobject property case was inlined. Ensure that there is not
2057 // a test eax instruction here.
2058 __ nop();
2059 cgen_->frame()->Push(&answer);
2060 } else {
2061 // Inline the inobject property case.
2062 Comment cmnt(masm, "[ Inlined named property load");
2063 Result receiver = cgen_->frame()->Pop();
2064 receiver.ToRegister();
2065
2066 Result value = cgen_->allocator()->Allocate();
2067 ASSERT(value.is_valid());
2068 DeferredReferenceGetNamedValue* deferred =
2069 new DeferredReferenceGetNamedValue(value.reg(),
2070 receiver.reg(),
2071 GetName());
2072
2073 // Check that the receiver is a heap object.
2074 __ testq(receiver.reg(), Immediate(kSmiTagMask));
2075 deferred->Branch(zero);
2076
2077 __ bind(deferred->patch_site());
2078 // This is the map check instruction that will be patched (so we can't
2079 // use the double underscore macro that may insert instructions).
2080 // Initially use an invalid map to force a failure.
2081 masm->Move(kScratchRegister, Factory::null_value());
2082 masm->cmpq(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
2083 kScratchRegister);
2084 // This branch is always a forwards branch so it's always a fixed
2085 // size which allows the assert below to succeed and patching to work.
2086 deferred->Branch(not_equal);
2087
2088 // The delta from the patch label to the load offset must be
2089 // statically known.
2090 ASSERT(masm->SizeOfCodeGeneratedSince(deferred->patch_site()) ==
2091 LoadIC::kOffsetToLoadInstruction);
2092 // The initial (invalid) offset has to be large enough to force
2093 // a 32-bit instruction encoding to allow patching with an
2094 // arbitrary offset. Use kMaxInt (minus kHeapObjectTag).
2095 int offset = kMaxInt;
2096 masm->movq(value.reg(), FieldOperand(receiver.reg(), offset));
2097
2098 __ IncrementCounter(&Counters::named_load_inline, 1);
2099 deferred->BindExit();
2100 cgen_->frame()->Push(&receiver);
2101 cgen_->frame()->Push(&value);
2102 }
2103 break;
2104 }
2105
2106 case KEYED: {
2107 // TODO(1241834): Make sure that this it is safe to ignore the
2108 // distinction between expressions in a typeof and not in a typeof.
2109 Comment cmnt(masm, "[ Load from keyed Property");
2110 Variable* var = expression_->AsVariableProxy()->AsVariable();
2111 bool is_global = var != NULL;
2112 ASSERT(!is_global || var->is_global());
2113 // Inline array load code if inside of a loop. We do not know
2114 // the receiver map yet, so we initially generate the code with
2115 // a check against an invalid map. In the inline cache code, we
2116 // patch the map check if appropriate.
2117
2118 // TODO(x64): Implement inlined loads for keyed properties.
2119 // Comment cmnt(masm, "[ Load from keyed Property");
2120
2121 RelocInfo::Mode mode = is_global
2122 ? RelocInfo::CODE_TARGET_CONTEXT
2123 : RelocInfo::CODE_TARGET;
2124 Result answer = cgen_->frame()->CallKeyedLoadIC(mode);
2125 // Make sure that we do not have a test instruction after the
2126 // call. A test instruction after the call is used to
2127 // indicate that we have generated an inline version of the
2128 // keyed load. The explicit nop instruction is here because
2129 // the push that follows might be peep-hole optimized away.
2130 __ nop();
2131 cgen_->frame()->Push(&answer);
2132 break;
2133 }
2134
2135 default:
2136 UNREACHABLE();
2137 }
2138 }
2139
2140
2141 void Reference::SetValue(InitState init_state) {
2142 ASSERT(cgen_->HasValidEntryRegisters());
2143 ASSERT(!is_illegal());
2144 MacroAssembler* masm = cgen_->masm();
2145 switch (type_) {
2146 case SLOT: {
2147 Comment cmnt(masm, "[ Store to Slot");
2148 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
2149 ASSERT(slot != NULL);
2150 cgen_->StoreToSlot(slot, init_state);
2151 break;
2152 }
2153
2154 case NAMED: {
2155 Comment cmnt(masm, "[ Store to named Property");
2156 cgen_->frame()->Push(GetName());
2157 Result answer = cgen_->frame()->CallStoreIC();
2158 cgen_->frame()->Push(&answer);
2159 break;
2160 }
2161
2162 case KEYED: {
2163 Comment cmnt(masm, "[ Store to keyed Property");
2164
2165 // Generate inlined version of the keyed store if the code is in
2166 // a loop and the key is likely to be a smi.
2167 Property* property = expression()->AsProperty();
2168 ASSERT(property != NULL);
2169
2170 // TODO(x64): Implement inlined version of keyed stores.
2171
2172 Result answer = cgen_->frame()->CallKeyedStoreIC();
2173 // Make sure that we do not have a test instruction after the
2174 // call. A test instruction after the call is used to
2175 // indicate that we have generated an inline version of the
2176 // keyed store.
2177 __ nop();
2178 cgen_->frame()->Push(&answer);
2179 break;
2180 }
2181
2182 default:
2183 UNREACHABLE();
2184 }
2074 } 2185 }
2075 2186
2076 2187
2077 void ToBooleanStub::Generate(MacroAssembler* masm) { 2188 void ToBooleanStub::Generate(MacroAssembler* masm) {
2078 Label false_result, true_result, not_string; 2189 Label false_result, true_result, not_string;
2079 __ movq(rax, Operand(rsp, 1 * kPointerSize)); 2190 __ movq(rax, Operand(rsp, 1 * kPointerSize));
2080 2191
2081 // 'null' => false. 2192 // 'null' => false.
2082 __ Cmp(rax, Factory::null_value()); 2193 __ Cmp(rax, Factory::null_value());
2083 __ j(equal, &false_result); 2194 __ j(equal, &false_result);
(...skipping 839 matching lines...) Expand 10 before | Expand all | Expand 10 after
2923 __ addq(rsp, Immediate(2 * kPointerSize)); // remove markers 3034 __ addq(rsp, Immediate(2 * kPointerSize)); // remove markers
2924 3035
2925 // Restore frame pointer and return. 3036 // Restore frame pointer and return.
2926 __ pop(rbp); 3037 __ pop(rbp);
2927 __ ret(0); 3038 __ ret(0);
2928 } 3039 }
2929 3040
2930 #undef __ 3041 #undef __
2931 3042
2932 } } // namespace v8::internal 3043 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/x64/assembler-x64.cc ('k') | src/x64/frames-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698