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 |