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 971 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
982 | 982 |
983 | 983 |
984 void HGraphBuilder::AddSimulate(BailoutId id, | 984 void HGraphBuilder::AddSimulate(BailoutId id, |
985 RemovableSimulate removable) { | 985 RemovableSimulate removable) { |
986 ASSERT(current_block() != NULL); | 986 ASSERT(current_block() != NULL); |
987 ASSERT(no_side_effects_scope_count_ == 0); | 987 ASSERT(no_side_effects_scope_count_ == 0); |
988 current_block()->AddSimulate(id, removable); | 988 current_block()->AddSimulate(id, removable); |
989 } | 989 } |
990 | 990 |
991 | 991 |
992 HBoundsCheck* HGraphBuilder::AddBoundsCheck(HValue* index, HValue* length) { | |
993 HBoundsCheck* result = new(graph()->zone()) HBoundsCheck(index, length); | |
994 AddInstruction(result); | |
995 return result; | |
996 } | |
997 | |
998 | |
999 HReturn* HGraphBuilder::AddReturn(HValue* value) { | 992 HReturn* HGraphBuilder::AddReturn(HValue* value) { |
1000 HValue* context = environment()->LookupContext(); | 993 HValue* context = environment()->LookupContext(); |
1001 int num_parameters = graph()->info()->num_parameters(); | 994 int num_parameters = graph()->info()->num_parameters(); |
1002 HValue* params = AddInstruction(new(graph()->zone()) | 995 HValue* params = AddInstruction(new(graph()->zone()) |
1003 HConstant(num_parameters)); | 996 HConstant(num_parameters)); |
1004 HReturn* return_instruction = new(graph()->zone()) | 997 HReturn* return_instruction = new(graph()->zone()) |
1005 HReturn(value, context, params); | 998 HReturn(value, context, params); |
1006 current_block()->FinishExit(return_instruction); | 999 current_block()->FinishExit(return_instruction); |
1007 return return_instruction; | 1000 return return_instruction; |
1008 } | 1001 } |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1168 new_length->ClearFlag(HValue::kCanOverflow); | 1161 new_length->ClearFlag(HValue::kCanOverflow); |
1169 | 1162 |
1170 Representation representation = IsFastElementsKind(kind) | 1163 Representation representation = IsFastElementsKind(kind) |
1171 ? Representation::Smi() : Representation::Tagged(); | 1164 ? Representation::Smi() : Representation::Tagged(); |
1172 AddStore(object, HObjectAccess::ForArrayLength(), new_length, | 1165 AddStore(object, HObjectAccess::ForArrayLength(), new_length, |
1173 representation); | 1166 representation); |
1174 } | 1167 } |
1175 | 1168 |
1176 length_checker.Else(); | 1169 length_checker.Else(); |
1177 | 1170 |
1178 AddBoundsCheck(key, length); | 1171 Add<HBoundsCheck>(key, length); |
1179 environment()->Push(elements); | 1172 environment()->Push(elements); |
1180 | 1173 |
1181 length_checker.End(); | 1174 length_checker.End(); |
1182 | 1175 |
1183 return environment()->Pop(); | 1176 return environment()->Pop(); |
1184 } | 1177 } |
1185 | 1178 |
1186 | 1179 |
1187 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object, | 1180 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object, |
1188 HValue* elements, | 1181 HValue* elements, |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1273 negative_checker.Then(); | 1266 negative_checker.Then(); |
1274 HInstruction* result = BuildExternalArrayElementAccess( | 1267 HInstruction* result = BuildExternalArrayElementAccess( |
1275 external_elements, key, val, bounds_check, | 1268 external_elements, key, val, bounds_check, |
1276 elements_kind, is_store); | 1269 elements_kind, is_store); |
1277 AddInstruction(result); | 1270 AddInstruction(result); |
1278 negative_checker.ElseDeopt(); | 1271 negative_checker.ElseDeopt(); |
1279 length_checker.End(); | 1272 length_checker.End(); |
1280 return result; | 1273 return result; |
1281 } else { | 1274 } else { |
1282 ASSERT(store_mode == STANDARD_STORE); | 1275 ASSERT(store_mode == STANDARD_STORE); |
1283 checked_key = AddBoundsCheck(key, length); | 1276 checked_key = Add<HBoundsCheck>(key, length); |
1284 HLoadExternalArrayPointer* external_elements = | 1277 HLoadExternalArrayPointer* external_elements = |
1285 new(zone) HLoadExternalArrayPointer(elements); | 1278 new(zone) HLoadExternalArrayPointer(elements); |
1286 AddInstruction(external_elements); | 1279 AddInstruction(external_elements); |
1287 return AddInstruction(BuildExternalArrayElementAccess( | 1280 return AddInstruction(BuildExternalArrayElementAccess( |
1288 external_elements, checked_key, val, mapcheck, | 1281 external_elements, checked_key, val, mapcheck, |
1289 elements_kind, is_store)); | 1282 elements_kind, is_store)); |
1290 } | 1283 } |
1291 } | 1284 } |
1292 ASSERT(fast_smi_only_elements || | 1285 ASSERT(fast_smi_only_elements || |
1293 fast_elements || | 1286 fast_elements || |
1294 IsFastDoubleElementsKind(elements_kind)); | 1287 IsFastDoubleElementsKind(elements_kind)); |
1295 | 1288 |
1296 // In case val is stored into a fast smi array, assure that the value is a smi | 1289 // In case val is stored into a fast smi array, assure that the value is a smi |
1297 // before manipulating the backing store. Otherwise the actual store may | 1290 // before manipulating the backing store. Otherwise the actual store may |
1298 // deopt, leaving the backing store in an invalid state. | 1291 // deopt, leaving the backing store in an invalid state. |
1299 if (is_store && IsFastSmiElementsKind(elements_kind) && | 1292 if (is_store && IsFastSmiElementsKind(elements_kind) && |
1300 !val->type().IsSmi()) { | 1293 !val->type().IsSmi()) { |
1301 val = AddInstruction(new(zone) HForceRepresentation( | 1294 val = AddInstruction(new(zone) HForceRepresentation( |
1302 val, Representation::Smi())); | 1295 val, Representation::Smi())); |
1303 } | 1296 } |
1304 | 1297 |
1305 if (IsGrowStoreMode(store_mode)) { | 1298 if (IsGrowStoreMode(store_mode)) { |
1306 NoObservableSideEffectsScope no_effects(this); | 1299 NoObservableSideEffectsScope no_effects(this); |
1307 elements = BuildCheckForCapacityGrow(object, elements, elements_kind, | 1300 elements = BuildCheckForCapacityGrow(object, elements, elements_kind, |
1308 length, key, is_js_array); | 1301 length, key, is_js_array); |
1309 checked_key = key; | 1302 checked_key = key; |
1310 } else { | 1303 } else { |
1311 checked_key = AddBoundsCheck(key, length); | 1304 checked_key = Add<HBoundsCheck>(key, length); |
1312 | 1305 |
1313 if (is_store && (fast_elements || fast_smi_only_elements)) { | 1306 if (is_store && (fast_elements || fast_smi_only_elements)) { |
1314 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { | 1307 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { |
1315 NoObservableSideEffectsScope no_effects(this); | 1308 NoObservableSideEffectsScope no_effects(this); |
1316 | 1309 |
1317 elements = BuildCopyElementsOnWrite(object, elements, elements_kind, | 1310 elements = BuildCopyElementsOnWrite(object, elements, elements_kind, |
1318 length); | 1311 length); |
1319 } else { | 1312 } else { |
1320 HCheckMaps* check_cow_map = HCheckMaps::New( | 1313 HCheckMaps* check_cow_map = HCheckMaps::New( |
1321 elements, isolate()->factory()->fixed_array_map(), zone); | 1314 elements, isolate()->factory()->fixed_array_map(), zone); |
(...skipping 5945 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7267 elements_kind <= LAST_ELEMENTS_KIND; | 7260 elements_kind <= LAST_ELEMENTS_KIND; |
7268 elements_kind = ElementsKind(elements_kind + 1)) { | 7261 elements_kind = ElementsKind(elements_kind + 1)) { |
7269 // After having handled FAST_* and DICTIONARY_ELEMENTS, we need to add some | 7262 // After having handled FAST_* and DICTIONARY_ELEMENTS, we need to add some |
7270 // code that's executed for all external array cases. | 7263 // code that's executed for all external array cases. |
7271 STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == | 7264 STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == |
7272 LAST_ELEMENTS_KIND); | 7265 LAST_ELEMENTS_KIND); |
7273 if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND | 7266 if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND |
7274 && todo_external_array) { | 7267 && todo_external_array) { |
7275 HInstruction* length = | 7268 HInstruction* length = |
7276 AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); | 7269 AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
7277 checked_key = AddBoundsCheck(key, length); | 7270 checked_key = Add<HBoundsCheck>(key, length); |
7278 external_elements = new(zone()) HLoadExternalArrayPointer(elements); | 7271 external_elements = new(zone()) HLoadExternalArrayPointer(elements); |
7279 AddInstruction(external_elements); | 7272 AddInstruction(external_elements); |
7280 } | 7273 } |
7281 if (type_todo[elements_kind]) { | 7274 if (type_todo[elements_kind]) { |
7282 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 7275 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
7283 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 7276 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
7284 HCompareConstantEqAndBranch* elements_kind_branch = | 7277 HCompareConstantEqAndBranch* elements_kind_branch = |
7285 new(zone()) HCompareConstantEqAndBranch( | 7278 new(zone()) HCompareConstantEqAndBranch( |
7286 elements_kind_instr, elements_kind, Token::EQ_STRICT); | 7279 elements_kind_instr, elements_kind, Token::EQ_STRICT); |
7287 elements_kind_branch->SetSuccessorAt(0, if_true); | 7280 elements_kind_branch->SetSuccessorAt(0, if_true); |
(...skipping 22 matching lines...) Expand all Loading... |
7310 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); | 7303 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); |
7311 typecheck->SetSuccessorAt(0, if_jsarray); | 7304 typecheck->SetSuccessorAt(0, if_jsarray); |
7312 typecheck->SetSuccessorAt(1, if_fastobject); | 7305 typecheck->SetSuccessorAt(1, if_fastobject); |
7313 current_block()->Finish(typecheck); | 7306 current_block()->Finish(typecheck); |
7314 | 7307 |
7315 set_current_block(if_jsarray); | 7308 set_current_block(if_jsarray); |
7316 HInstruction* length = AddLoad(object, HObjectAccess::ForArrayLength(), | 7309 HInstruction* length = AddLoad(object, HObjectAccess::ForArrayLength(), |
7317 typecheck, Representation::Smi()); | 7310 typecheck, Representation::Smi()); |
7318 length->set_type(HType::Smi()); | 7311 length->set_type(HType::Smi()); |
7319 | 7312 |
7320 checked_key = AddBoundsCheck(key, length); | 7313 checked_key = Add<HBoundsCheck>(key, length); |
7321 access = AddInstruction(BuildFastElementAccess( | 7314 access = AddInstruction(BuildFastElementAccess( |
7322 elements, checked_key, val, elements_kind_branch, | 7315 elements, checked_key, val, elements_kind_branch, |
7323 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE)); | 7316 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE)); |
7324 if (!is_store) { | 7317 if (!is_store) { |
7325 Push(access); | 7318 Push(access); |
7326 } | 7319 } |
7327 | 7320 |
7328 *has_side_effects |= access->HasObservableSideEffects(); | 7321 *has_side_effects |= access->HasObservableSideEffects(); |
7329 // The caller will use has_side_effects and add correct Simulate. | 7322 // The caller will use has_side_effects and add correct Simulate. |
7330 access->SetFlag(HValue::kHasNoObservableSideEffects); | 7323 access->SetFlag(HValue::kHasNoObservableSideEffects); |
7331 if (position != -1) { | 7324 if (position != -1) { |
7332 access->set_position(position); | 7325 access->set_position(position); |
7333 } | 7326 } |
7334 if_jsarray->GotoNoSimulate(join); | 7327 if_jsarray->GotoNoSimulate(join); |
7335 | 7328 |
7336 set_current_block(if_fastobject); | 7329 set_current_block(if_fastobject); |
7337 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); | 7330 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
7338 checked_key = AddBoundsCheck(key, length); | 7331 checked_key = Add<HBoundsCheck>(key, length); |
7339 access = AddInstruction(BuildFastElementAccess( | 7332 access = AddInstruction(BuildFastElementAccess( |
7340 elements, checked_key, val, elements_kind_branch, | 7333 elements, checked_key, val, elements_kind_branch, |
7341 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE)); | 7334 elements_kind, is_store, NEVER_RETURN_HOLE, STANDARD_STORE)); |
7342 } else if (elements_kind == DICTIONARY_ELEMENTS) { | 7335 } else if (elements_kind == DICTIONARY_ELEMENTS) { |
7343 if (is_store) { | 7336 if (is_store) { |
7344 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); | 7337 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); |
7345 } else { | 7338 } else { |
7346 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); | 7339 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); |
7347 } | 7340 } |
7348 } else { // External array elements. | 7341 } else { // External array elements. |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7480 Push(graph()->GetArgumentsObject()); | 7473 Push(graph()->GetArgumentsObject()); |
7481 VisitForValue(expr->key()); | 7474 VisitForValue(expr->key()); |
7482 if (HasStackOverflow() || current_block() == NULL) return true; | 7475 if (HasStackOverflow() || current_block() == NULL) return true; |
7483 HValue* key = Pop(); | 7476 HValue* key = Pop(); |
7484 Drop(1); // Arguments object. | 7477 Drop(1); // Arguments object. |
7485 if (function_state()->outer() == NULL) { | 7478 if (function_state()->outer() == NULL) { |
7486 HInstruction* elements = AddInstruction( | 7479 HInstruction* elements = AddInstruction( |
7487 new(zone()) HArgumentsElements(false)); | 7480 new(zone()) HArgumentsElements(false)); |
7488 HInstruction* length = AddInstruction( | 7481 HInstruction* length = AddInstruction( |
7489 new(zone()) HArgumentsLength(elements)); | 7482 new(zone()) HArgumentsLength(elements)); |
7490 HInstruction* checked_key = AddBoundsCheck(key, length); | 7483 HInstruction* checked_key = Add<HBoundsCheck>(key, length); |
7491 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); | 7484 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); |
7492 } else { | 7485 } else { |
7493 EnsureArgumentsArePushedForAccess(); | 7486 EnsureArgumentsArePushedForAccess(); |
7494 | 7487 |
7495 // Number of arguments without receiver. | 7488 // Number of arguments without receiver. |
7496 HInstruction* elements = function_state()->arguments_elements(); | 7489 HInstruction* elements = function_state()->arguments_elements(); |
7497 int argument_count = environment()-> | 7490 int argument_count = environment()-> |
7498 arguments_environment()->parameter_count() - 1; | 7491 arguments_environment()->parameter_count() - 1; |
7499 HInstruction* length = AddInstruction(new(zone()) HConstant( | 7492 HInstruction* length = AddInstruction(new(zone()) HConstant( |
7500 argument_count)); | 7493 argument_count)); |
7501 HInstruction* checked_key = AddBoundsCheck(key, length); | 7494 HInstruction* checked_key = Add<HBoundsCheck>(key, length); |
7502 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); | 7495 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); |
7503 } | 7496 } |
7504 } | 7497 } |
7505 ast_context()->ReturnInstruction(result, expr->id()); | 7498 ast_context()->ReturnInstruction(result, expr->id()); |
7506 return true; | 7499 return true; |
7507 } | 7500 } |
7508 | 7501 |
7509 | 7502 |
7510 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { | 7503 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { |
7511 ASSERT(!HasStackOverflow()); | 7504 ASSERT(!HasStackOverflow()); |
(...skipping 1804 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9316 if (i < 0 || i >= s->length()) { | 9309 if (i < 0 || i >= s->length()) { |
9317 return new(zone()) HConstant(OS::nan_value()); | 9310 return new(zone()) HConstant(OS::nan_value()); |
9318 } | 9311 } |
9319 return new(zone()) HConstant(s->Get(i)); | 9312 return new(zone()) HConstant(s->Get(i)); |
9320 } | 9313 } |
9321 } | 9314 } |
9322 BuildCheckHeapObject(string); | 9315 BuildCheckHeapObject(string); |
9323 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | 9316 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |
9324 HInstruction* length = HStringLength::New(zone(), string); | 9317 HInstruction* length = HStringLength::New(zone(), string); |
9325 AddInstruction(length); | 9318 AddInstruction(length); |
9326 HInstruction* checked_index = AddBoundsCheck(index, length); | 9319 HInstruction* checked_index = Add<HBoundsCheck>(index, length); |
9327 return new(zone()) HStringCharCodeAt(context, string, checked_index); | 9320 return new(zone()) HStringCharCodeAt(context, string, checked_index); |
9328 } | 9321 } |
9329 | 9322 |
9330 // Checks if the given shift amounts have form: (sa) and (32 - sa). | 9323 // Checks if the given shift amounts have form: (sa) and (32 - sa). |
9331 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, | 9324 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, |
9332 HValue* const32_minus_sa) { | 9325 HValue* const32_minus_sa) { |
9333 if (!const32_minus_sa->IsSub()) return false; | 9326 if (!const32_minus_sa->IsSub()) return false; |
9334 HSub* sub = HSub::cast(const32_minus_sa); | 9327 HSub* sub = HSub::cast(const32_minus_sa); |
9335 if (sa != sub->right()) return false; | 9328 if (sa != sub->right()) return false; |
9336 HValue* const32 = sub->left(); | 9329 HValue* const32 = sub->left(); |
(...skipping 1193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10530 // Our implementation of arguments (based on this stack frame or an | 10523 // Our implementation of arguments (based on this stack frame or an |
10531 // adapter below it) does not work for inlined functions. This runtime | 10524 // adapter below it) does not work for inlined functions. This runtime |
10532 // function is blacklisted by AstNode::IsInlineable. | 10525 // function is blacklisted by AstNode::IsInlineable. |
10533 ASSERT(function_state()->outer() == NULL); | 10526 ASSERT(function_state()->outer() == NULL); |
10534 ASSERT(call->arguments()->length() == 1); | 10527 ASSERT(call->arguments()->length() == 1); |
10535 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 10528 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
10536 HValue* index = Pop(); | 10529 HValue* index = Pop(); |
10537 HInstruction* elements = AddInstruction( | 10530 HInstruction* elements = AddInstruction( |
10538 new(zone()) HArgumentsElements(false)); | 10531 new(zone()) HArgumentsElements(false)); |
10539 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); | 10532 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); |
10540 HInstruction* checked_index = AddBoundsCheck(index, length); | 10533 HInstruction* checked_index = Add<HBoundsCheck>(index, length); |
10541 HAccessArgumentsAt* result = | 10534 HAccessArgumentsAt* result = |
10542 new(zone()) HAccessArgumentsAt(elements, length, checked_index); | 10535 new(zone()) HAccessArgumentsAt(elements, length, checked_index); |
10543 return ast_context()->ReturnInstruction(result, call->id()); | 10536 return ast_context()->ReturnInstruction(result, call->id()); |
10544 } | 10537 } |
10545 | 10538 |
10546 | 10539 |
10547 // Support for accessing the class and value fields of an object. | 10540 // Support for accessing the class and value fields of an object. |
10548 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) { | 10541 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) { |
10549 // The special form detected by IsClassOfTest is detected before we get here | 10542 // The special form detected by IsClassOfTest is detected before we get here |
10550 // and does not cause a bailout. | 10543 // and does not cause a bailout. |
(...skipping 987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11538 if (ShouldProduceTraceOutput()) { | 11531 if (ShouldProduceTraceOutput()) { |
11539 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11532 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
11540 } | 11533 } |
11541 | 11534 |
11542 #ifdef DEBUG | 11535 #ifdef DEBUG |
11543 graph_->Verify(false); // No full verify. | 11536 graph_->Verify(false); // No full verify. |
11544 #endif | 11537 #endif |
11545 } | 11538 } |
11546 | 11539 |
11547 } } // namespace v8::internal | 11540 } } // namespace v8::internal |
OLD | NEW |