Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 // Required to get M_E etc. in MSVC. | 7 // Required to get M_E etc. in MSVC. |
| 8 #if defined(_WIN32) | 8 #if defined(_WIN32) |
| 9 #define _USE_MATH_DEFINES | 9 #define _USE_MATH_DEFINES |
| 10 #endif | 10 #endif |
| (...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 748 return pos->second; | 748 return pos->second; |
| 749 } else { | 749 } else { |
| 750 uint32_t index = builder_->builder_->AddImport( | 750 uint32_t index = builder_->builder_->AddImport( |
| 751 indices->name_, indices->name_length_, sig); | 751 indices->name_, indices->name_length_, sig); |
| 752 indices->signature_to_index_[sig] = index; | 752 indices->signature_to_index_[sig] = index; |
| 753 return index; | 753 return index; |
| 754 } | 754 } |
| 755 } | 755 } |
| 756 }; | 756 }; |
| 757 | 757 |
| 758 void EmitAssignmentLhs(Expression* target, MachineType* mtype) { | 758 void EmitAssignmentLhs(Expression* target, AsmType** atype) { |
| 759 // Match the left hand side of the assignment. | 759 // Match the left hand side of the assignment. |
| 760 VariableProxy* target_var = target->AsVariableProxy(); | 760 VariableProxy* target_var = target->AsVariableProxy(); |
| 761 if (target_var != nullptr) { | 761 if (target_var != nullptr) { |
| 762 // Left hand side is a local or a global variable, no code on LHS. | 762 // Left hand side is a local or a global variable, no code on LHS. |
| 763 return; | 763 return; |
| 764 } | 764 } |
| 765 | 765 |
| 766 Property* target_prop = target->AsProperty(); | 766 Property* target_prop = target->AsProperty(); |
| 767 if (target_prop != nullptr) { | 767 if (target_prop != nullptr) { |
| 768 // Left hand side is a property access, i.e. the asm.js heap. | 768 // Left hand side is a property access, i.e. the asm.js heap. |
| 769 VisitPropertyAndEmitIndex(target_prop, mtype); | 769 VisitPropertyAndEmitIndex(target_prop, atype); |
| 770 return; | 770 return; |
| 771 } | 771 } |
| 772 | 772 |
| 773 if (target_var == nullptr && target_prop == nullptr) { | 773 if (target_var == nullptr && target_prop == nullptr) { |
| 774 UNREACHABLE(); // invalid assignment. | 774 UNREACHABLE(); // invalid assignment. |
| 775 } | 775 } |
| 776 } | 776 } |
| 777 | 777 |
| 778 void EmitAssignmentRhs(Expression* target, Expression* value, bool* is_nop) { | 778 void EmitAssignmentRhs(Expression* target, Expression* value, bool* is_nop) { |
| 779 BinaryOperation* binop = value->AsBinaryOperation(); | 779 BinaryOperation* binop = value->AsBinaryOperation(); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 807 if (target_var != nullptr && effective_value_var != nullptr && | 807 if (target_var != nullptr && effective_value_var != nullptr && |
| 808 target_var->var() == effective_value_var->var()) { | 808 target_var->var() == effective_value_var->var()) { |
| 809 *is_nop = true; | 809 *is_nop = true; |
| 810 return; | 810 return; |
| 811 } | 811 } |
| 812 } | 812 } |
| 813 } | 813 } |
| 814 RECURSE(Visit(value)); | 814 RECURSE(Visit(value)); |
| 815 } | 815 } |
| 816 | 816 |
| 817 void EmitAssignment(Assignment* expr, MachineType type, ValueFate fate) { | 817 void EmitAssignment(Assignment* expr, AsmType* type, ValueFate fate) { |
| 818 // Match the left hand side of the assignment. | 818 // Match the left hand side of the assignment. |
| 819 VariableProxy* target_var = expr->target()->AsVariableProxy(); | 819 VariableProxy* target_var = expr->target()->AsVariableProxy(); |
| 820 if (target_var != nullptr) { | 820 if (target_var != nullptr) { |
| 821 // Left hand side is a local or a global variable. | 821 // Left hand side is a local or a global variable. |
| 822 Variable* var = target_var->var(); | 822 Variable* var = target_var->var(); |
| 823 LocalType var_type = TypeOf(expr); | 823 LocalType var_type = TypeOf(expr); |
| 824 DCHECK_NE(kAstStmt, var_type); | 824 DCHECK_NE(kAstStmt, var_type); |
| 825 if (var->IsContextSlot()) { | 825 if (var->IsContextSlot()) { |
| 826 uint32_t index = LookupOrInsertGlobal(var, var_type); | 826 uint32_t index = LookupOrInsertGlobal(var, var_type); |
| 827 current_function_builder_->EmitWithVarInt(kExprSetGlobal, index); | 827 current_function_builder_->EmitWithVarInt(kExprSetGlobal, index); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 842 Property* target_prop = expr->target()->AsProperty(); | 842 Property* target_prop = expr->target()->AsProperty(); |
| 843 if (target_prop != nullptr) { | 843 if (target_prop != nullptr) { |
| 844 // Left hand side is a property access, i.e. the asm.js heap. | 844 // Left hand side is a property access, i.e. the asm.js heap. |
| 845 if (TypeOf(expr->value()) == kAstF64 && expr->target()->IsProperty() && | 845 if (TypeOf(expr->value()) == kAstF64 && expr->target()->IsProperty() && |
| 846 typer_->TypeOf(expr->target()->AsProperty()->obj()) | 846 typer_->TypeOf(expr->target()->AsProperty()->obj()) |
| 847 ->IsA(AsmType::Float32Array())) { | 847 ->IsA(AsmType::Float32Array())) { |
| 848 current_function_builder_->Emit(kExprF32ConvertF64); | 848 current_function_builder_->Emit(kExprF32ConvertF64); |
| 849 } | 849 } |
| 850 // Note that unlike StoreMem, AsmjsStoreMem ignores out-of-bounds writes. | 850 // Note that unlike StoreMem, AsmjsStoreMem ignores out-of-bounds writes. |
| 851 WasmOpcode opcode; | 851 WasmOpcode opcode; |
| 852 if (type == MachineType::Int8()) { | 852 if (type->IsA(AsmType::Int8Array())) { |
|
bradnelson
2016/11/02 13:24:22
IsA is more expensive (since it has a bunch of fal
aseemgarg
2016/11/02 19:40:01
Done.
| |
| 853 opcode = kExprI32AsmjsStoreMem8; | 853 opcode = kExprI32AsmjsStoreMem8; |
| 854 } else if (type == MachineType::Uint8()) { | 854 } else if (type->IsA(AsmType::Uint8Array())) { |
| 855 opcode = kExprI32AsmjsStoreMem8; | 855 opcode = kExprI32AsmjsStoreMem8; |
| 856 } else if (type == MachineType::Int16()) { | 856 } else if (type->IsA(AsmType::Int16Array())) { |
| 857 opcode = kExprI32AsmjsStoreMem16; | 857 opcode = kExprI32AsmjsStoreMem16; |
| 858 } else if (type == MachineType::Uint16()) { | 858 } else if (type->IsA(AsmType::Uint16Array())) { |
| 859 opcode = kExprI32AsmjsStoreMem16; | 859 opcode = kExprI32AsmjsStoreMem16; |
| 860 } else if (type == MachineType::Int32()) { | 860 } else if (type->IsA(AsmType::Int32Array())) { |
| 861 opcode = kExprI32AsmjsStoreMem; | 861 opcode = kExprI32AsmjsStoreMem; |
| 862 } else if (type == MachineType::Uint32()) { | 862 } else if (type->IsA(AsmType::Uint32Array())) { |
| 863 opcode = kExprI32AsmjsStoreMem; | 863 opcode = kExprI32AsmjsStoreMem; |
| 864 } else if (type == MachineType::Float32()) { | 864 } else if (type->IsA(AsmType::Float32Array())) { |
| 865 opcode = kExprF32AsmjsStoreMem; | 865 opcode = kExprF32AsmjsStoreMem; |
| 866 } else if (type == MachineType::Float64()) { | 866 } else if (type->IsA(AsmType::Float64Array())) { |
| 867 opcode = kExprF64AsmjsStoreMem; | 867 opcode = kExprF64AsmjsStoreMem; |
| 868 } else { | 868 } else { |
| 869 UNREACHABLE(); | 869 UNREACHABLE(); |
| 870 } | 870 } |
| 871 current_function_builder_->Emit(opcode); | 871 current_function_builder_->Emit(opcode); |
| 872 if (fate == kDrop) { | 872 if (fate == kDrop) { |
| 873 // Asm.js stores to memory leave their result on the stack. | 873 // Asm.js stores to memory leave their result on the stack. |
| 874 current_function_builder_->Emit(kExprDrop); | 874 current_function_builder_->Emit(kExprDrop); |
| 875 } | 875 } |
| 876 } | 876 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 923 return; | 923 return; |
| 924 } | 924 } |
| 925 if (expr->value()->IsCallNew()) { | 925 if (expr->value()->IsCallNew()) { |
| 926 // No init code to emit for CallNew nodes. | 926 // No init code to emit for CallNew nodes. |
| 927 return; | 927 return; |
| 928 } | 928 } |
| 929 as_init = true; | 929 as_init = true; |
| 930 } | 930 } |
| 931 | 931 |
| 932 if (as_init) LoadInitFunction(); | 932 if (as_init) LoadInitFunction(); |
| 933 MachineType mtype = MachineType::None(); | 933 AsmType* atype = AsmType::None(); |
| 934 bool is_nop = false; | 934 bool is_nop = false; |
| 935 EmitAssignmentLhs(expr->target(), &mtype); | 935 EmitAssignmentLhs(expr->target(), &atype); |
| 936 EmitAssignmentRhs(expr->target(), expr->value(), &is_nop); | 936 EmitAssignmentRhs(expr->target(), expr->value(), &is_nop); |
| 937 if (!is_nop) { | 937 if (!is_nop) { |
| 938 EmitAssignment(expr, mtype, fate); | 938 EmitAssignment(expr, atype, fate); |
| 939 } | 939 } |
| 940 if (as_init) UnLoadInitFunction(); | 940 if (as_init) UnLoadInitFunction(); |
| 941 } | 941 } |
| 942 | 942 |
| 943 void VisitYield(Yield* expr) { UNREACHABLE(); } | 943 void VisitYield(Yield* expr) { UNREACHABLE(); } |
| 944 | 944 |
| 945 void VisitThrow(Throw* expr) { UNREACHABLE(); } | 945 void VisitThrow(Throw* expr) { UNREACHABLE(); } |
| 946 | 946 |
| 947 void VisitForeignVariable(bool is_float, Variable* var, Property* expr) { | 947 void VisitForeignVariable(bool is_float, Variable* var, Property* expr) { |
| 948 DCHECK(expr->obj()->AsVariableProxy()); | 948 DCHECK(expr->obj()->AsVariableProxy()); |
| 949 DCHECK(VariableLocation::PARAMETER == | 949 DCHECK(VariableLocation::PARAMETER == |
| 950 expr->obj()->AsVariableProxy()->var()->location()); | 950 expr->obj()->AsVariableProxy()->var()->location()); |
| 951 DCHECK_EQ(1, expr->obj()->AsVariableProxy()->var()->index()); | 951 DCHECK_EQ(1, expr->obj()->AsVariableProxy()->var()->index()); |
| 952 Literal* key_literal = expr->key()->AsLiteral(); | 952 Literal* key_literal = expr->key()->AsLiteral(); |
| 953 DCHECK_NOT_NULL(key_literal); | 953 DCHECK_NOT_NULL(key_literal); |
| 954 if (!key_literal->value().is_null()) { | 954 if (!key_literal->value().is_null()) { |
| 955 Handle<Name> name = | 955 Handle<Name> name = |
| 956 i::Object::ToName(isolate_, key_literal->value()).ToHandleChecked(); | 956 i::Object::ToName(isolate_, key_literal->value()).ToHandleChecked(); |
| 957 LocalType type = is_float ? kAstF64 : kAstI32; | 957 LocalType type = is_float ? kAstF64 : kAstI32; |
| 958 foreign_variables_.push_back({name, var, type}); | 958 foreign_variables_.push_back({name, var, type}); |
| 959 } | 959 } |
| 960 } | 960 } |
| 961 | 961 |
| 962 void VisitPropertyAndEmitIndex(Property* expr, MachineType* mtype) { | 962 void VisitPropertyAndEmitIndex(Property* expr, AsmType** atype) { |
| 963 Expression* obj = expr->obj(); | 963 Expression* obj = expr->obj(); |
| 964 AsmType* type = typer_->TypeOf(obj); | 964 AsmType* type = typer_->TypeOf(obj); |
| 965 *atype = type; | |
| 965 int size; | 966 int size; |
| 966 if (type->IsA(AsmType::Uint8Array())) { | 967 if (type->IsA(AsmType::Uint8Array())) { |
|
bradnelson
2016/11/02 13:24:22
Switch this to calling:
size = type->ElementSizeI
aseemgarg
2016/11/02 19:40:01
Done.
| |
| 967 *mtype = MachineType::Uint8(); | |
| 968 size = 1; | 968 size = 1; |
| 969 } else if (type->IsA(AsmType::Int8Array())) { | 969 } else if (type->IsA(AsmType::Int8Array())) { |
| 970 *mtype = MachineType::Int8(); | |
| 971 size = 1; | 970 size = 1; |
| 972 } else if (type->IsA(AsmType::Uint16Array())) { | 971 } else if (type->IsA(AsmType::Uint16Array())) { |
| 973 *mtype = MachineType::Uint16(); | |
| 974 size = 2; | 972 size = 2; |
| 975 } else if (type->IsA(AsmType::Int16Array())) { | 973 } else if (type->IsA(AsmType::Int16Array())) { |
| 976 *mtype = MachineType::Int16(); | |
| 977 size = 2; | 974 size = 2; |
| 978 } else if (type->IsA(AsmType::Uint32Array())) { | 975 } else if (type->IsA(AsmType::Uint32Array())) { |
| 979 *mtype = MachineType::Uint32(); | |
| 980 size = 4; | 976 size = 4; |
| 981 } else if (type->IsA(AsmType::Int32Array())) { | 977 } else if (type->IsA(AsmType::Int32Array())) { |
| 982 *mtype = MachineType::Int32(); | |
| 983 size = 4; | |
| 984 } else if (type->IsA(AsmType::Uint32Array())) { | |
| 985 *mtype = MachineType::Uint32(); | |
| 986 size = 4; | 978 size = 4; |
| 987 } else if (type->IsA(AsmType::Float32Array())) { | 979 } else if (type->IsA(AsmType::Float32Array())) { |
| 988 *mtype = MachineType::Float32(); | |
| 989 size = 4; | 980 size = 4; |
| 990 } else if (type->IsA(AsmType::Float64Array())) { | 981 } else if (type->IsA(AsmType::Float64Array())) { |
| 991 *mtype = MachineType::Float64(); | |
| 992 size = 8; | 982 size = 8; |
| 993 } else { | 983 } else { |
| 994 UNREACHABLE(); | 984 UNREACHABLE(); |
| 995 } | 985 } |
| 996 if (size == 1) { | 986 if (size == 1) { |
| 997 // Allow more general expression in byte arrays than the spec | 987 // Allow more general expression in byte arrays than the spec |
| 998 // strictly permits. | 988 // strictly permits. |
| 999 // Early versions of Emscripten emit HEAP8[HEAP32[..]|0] in | 989 // Early versions of Emscripten emit HEAP8[HEAP32[..]|0] in |
| 1000 // places that strictly should be HEAP8[HEAP32[..]>>0]. | 990 // places that strictly should be HEAP8[HEAP32[..]>>0]. |
| 1001 RECURSE(Visit(expr->key())); | 991 RECURSE(Visit(expr->key())); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1023 byte mask = static_cast<byte>(~(size - 1)); | 1013 byte mask = static_cast<byte>(~(size - 1)); |
| 1024 RECURSE(Visit(binop->left())); | 1014 RECURSE(Visit(binop->left())); |
| 1025 current_function_builder_->EmitWithU8(kExprI8Const, mask); | 1015 current_function_builder_->EmitWithU8(kExprI8Const, mask); |
| 1026 current_function_builder_->Emit(kExprI32And); | 1016 current_function_builder_->Emit(kExprI32And); |
| 1027 return; | 1017 return; |
| 1028 } | 1018 } |
| 1029 UNREACHABLE(); | 1019 UNREACHABLE(); |
| 1030 } | 1020 } |
| 1031 | 1021 |
| 1032 void VisitProperty(Property* expr) { | 1022 void VisitProperty(Property* expr) { |
| 1033 MachineType type; | 1023 AsmType* type = AsmType::None(); |
| 1034 VisitPropertyAndEmitIndex(expr, &type); | 1024 VisitPropertyAndEmitIndex(expr, &type); |
| 1035 WasmOpcode opcode; | 1025 WasmOpcode opcode; |
| 1036 if (type == MachineType::Int8()) { | 1026 if (type->IsA(AsmType::Int8Array())) { |
|
bradnelson
2016/11/02 13:24:22
Same as above, IsA isn't cheap.
aseemgarg
2016/11/02 19:40:01
Done.
| |
| 1037 opcode = kExprI32AsmjsLoadMem8S; | 1027 opcode = kExprI32AsmjsLoadMem8S; |
| 1038 } else if (type == MachineType::Uint8()) { | 1028 } else if (type->IsA(AsmType::Uint8Array())) { |
| 1039 opcode = kExprI32AsmjsLoadMem8U; | 1029 opcode = kExprI32AsmjsLoadMem8U; |
| 1040 } else if (type == MachineType::Int16()) { | 1030 } else if (type->IsA(AsmType::Int16Array())) { |
| 1041 opcode = kExprI32AsmjsLoadMem16S; | 1031 opcode = kExprI32AsmjsLoadMem16S; |
| 1042 } else if (type == MachineType::Uint16()) { | 1032 } else if (type->IsA(AsmType::Uint16Array())) { |
| 1043 opcode = kExprI32AsmjsLoadMem16U; | 1033 opcode = kExprI32AsmjsLoadMem16U; |
| 1044 } else if (type == MachineType::Int32()) { | 1034 } else if (type->IsA(AsmType::Int32Array())) { |
| 1045 opcode = kExprI32AsmjsLoadMem; | 1035 opcode = kExprI32AsmjsLoadMem; |
| 1046 } else if (type == MachineType::Uint32()) { | 1036 } else if (type->IsA(AsmType::Uint32Array())) { |
| 1047 opcode = kExprI32AsmjsLoadMem; | 1037 opcode = kExprI32AsmjsLoadMem; |
| 1048 } else if (type == MachineType::Float32()) { | 1038 } else if (type->IsA(AsmType::Float32Array())) { |
| 1049 opcode = kExprF32AsmjsLoadMem; | 1039 opcode = kExprF32AsmjsLoadMem; |
| 1050 } else if (type == MachineType::Float64()) { | 1040 } else if (type->IsA(AsmType::Float64Array())) { |
| 1051 opcode = kExprF64AsmjsLoadMem; | 1041 opcode = kExprF64AsmjsLoadMem; |
| 1052 } else { | 1042 } else { |
| 1053 UNREACHABLE(); | 1043 UNREACHABLE(); |
| 1054 } | 1044 } |
| 1055 | 1045 |
| 1056 current_function_builder_->Emit(opcode); | 1046 current_function_builder_->Emit(opcode); |
| 1057 } | 1047 } |
| 1058 | 1048 |
| 1059 bool VisitStdlibFunction(Call* call, VariableProxy* expr) { | 1049 bool VisitStdlibFunction(Call* call, VariableProxy* expr) { |
| 1060 Variable* var = expr->var(); | 1050 Variable* var = expr->var(); |
| (...skipping 824 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1885 impl.builder_->WriteAsmJsOffsetTable(*asm_offsets_buffer); | 1875 impl.builder_->WriteAsmJsOffsetTable(*asm_offsets_buffer); |
| 1886 return {module_buffer, asm_offsets_buffer}; | 1876 return {module_buffer, asm_offsets_buffer}; |
| 1887 } | 1877 } |
| 1888 | 1878 |
| 1889 const char* AsmWasmBuilder::foreign_init_name = "__foreign_init__"; | 1879 const char* AsmWasmBuilder::foreign_init_name = "__foreign_init__"; |
| 1890 const char* AsmWasmBuilder::single_function_name = "__single_function__"; | 1880 const char* AsmWasmBuilder::single_function_name = "__single_function__"; |
| 1891 | 1881 |
| 1892 } // namespace wasm | 1882 } // namespace wasm |
| 1893 } // namespace internal | 1883 } // namespace internal |
| 1894 } // namespace v8 | 1884 } // namespace v8 |
| OLD | NEW |